diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..20e0241 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +.vscode +.cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 88aa47d..c8ba7ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,16 +39,6 @@ if(UNIX) # endif() # --------------------------------------- -# --------- Inclusion de Vulkan ---------- -# Vulkan Lib pour charger Vulkan, fournit avec les drivers, donc se trouve toute seul. - # find_package(Vulkan REQUIRED) - # if(VULKAN_FOUND) - # message("lib OpenGL Trouvé") - # else() - # message("lib OpenGL Introuvable") - # endif() -# --------------------------------------- - # ---------- Inclusion de GLM ----------- # GLM Lib pour mathématique, en mode header only. set(GLMlib_DIR ./lib/CMake/Linux) @@ -208,12 +198,12 @@ if(UNIX) # ---------- Inclusion de ASSIMP ----------- # Assimp Lib import modèles 3D. - # find_package(assimp REQUIRED) - # if(assimp_FOUND) - # message("lib ASSIMP Trouvé") - # else() - # message("lib ASSIMP Introuvable") - # endif() + find_package(assimp REQUIRED) + if(assimp_FOUND) + message("lib ASSIMP Trouvé") + else() + message("lib ASSIMP Introuvable") + endif() # --------------------------------------- # ---------- Inclusion de ODE ----------- @@ -265,17 +255,158 @@ else() message("lib Catch2 Introuvable") endif() +# ---------- Inclusion de SDL3----------- +# la sdl3 + +find_package(SDL3 REQUIRED) +# These tests can use the Catch2-provided main +if(SDL3_found) + message("lib Catch2 Trouvé") +else() + message("lib Catch2 Introuvable") endif() + +# ---------- Inclusion de Vulkan----------- +# vulkan +# --------- Inclusion de Vulkan ---------- +# Vulkan Lib pour charger Vulkan, fournit avec les drivers, donc se trouve toute seul. +find_package(Vulkan REQUIRED) +if(VULKAN_FOUND) + message("lib OpenGL Trouvé") +else() + message("lib OpenGL Introuvable") +endif() +# --------------------------------------- + +# ------- Inclusion de SDL2_IMAGE -------- +# SDL2_IMAGE Lib pour charger une image + # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. + find_package(SDL3_image QUIET) + # #find_library(SDL2_image libSDL2_image) + + if(SDL3_image_FOUND) + message("lib SDL3_IMAGE Trouvé") + else() + message("lib SDL3_IMAGE Introuvable") + endif() +# --------------------------------------- + +# ------- Inclusion de SDL3_TTF -------- +#SDL3_IMAGE Lib pour charger une police d'écriture. + #set(SDL3_ttf_DIR ./lib/CMake/Linux) + # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. + find_package(SDL3_ttf QUIET) + #find_library(SDL2_ttf libSDL2_ttf) + if(SDL3_ttf_FOUND) + message("lib SDL3_TTF Trouvé") + else() + message("lib SDL3_TTF Introuvable") + endif() +# --------------------------------------- + +# ------- Inclusion de Spirv-cross -------- +#Spirv-cross pour metadonnees shader spirv +# set(spirv_cross_core_DIR ./lib/CMake/Linux/spirv-crossConf) +# set(spirv_cross_glsl_DIR ./lib/CMake/Linux/spirv-crossConf) + # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. +# find_package(spirv_cross_core QUIET) +# find_package(spirv_cross_glsl QUIET) + + #find_library(SDL2_ttf libSDL2_ttf) +# if(spirv_cross_core_FOUND AND spirv_cross_glsl_FOUND) +# message("lib spirv_cross Trouvé") +# else() +# message("lib spirv_cross Introuvable") +# endif() +# --------------------------------------- + +# ------- Inclusion de Spirv-cross -------- +#Spirv-cross pour metadonnees shader spirv + set(spirvreflectlib_DIR ./lib/CMake/Linux/) + # Les autre plateforme (Linux...) ont un installateur de paquet, la lib se trouve toute seul. +# find_package(spirv_cross_core QUIET) + find_package(spirvreflectlib QUIET) + + if(spirvreflectlib_FOUND) + message("lib spirvReflect Trouvé") + else() + message("lib spirvReflect Introuvable") + endif() +# --------------------------------------- +add_library(spirv-reflect STATIC ${SPIRV_EXT_SRC}) + +# ------- Inclusion de JSONfMC++ -------- +# JSONfMC++ Lib pour gestion fichier JSON, en mode header only. +set(VulkanMemoryAllocatorlib_DIR ./lib/CMake/Linux) +find_package(VulkanMemoryAllocatorlib REQUIRED) + +if(VulkanMemoryAllocatorlib_FOUND) + message("lib VulkanMemoryAllocator Trouvé") +else() + message("lib VulkanMemoryAllocator Introuvable") +endif() +# --------------------------------------- + +endif() + + # Chemin executable set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin/${CMAKE_BUILD_TYPE}") +set(PATH_TO_SHADER_BUILD_TYPE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") +function(compile_slang_shaders SLANG_FILES OUTPUT_DIR) + set(SLANG_COMPILER ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/slang/bin/slangc) + set(GENERATED_SPV_FILES "") + set (SHADERS_DIR ${PATH_TO_SHADER_BUILD_TYPE}/assets/shaders/slang) + set (ENTRY_POINTS -entry vertMain -entry fragMain) + + foreach(SLANG_FILE ${SLANG_FILES}) + get_filename_component(FILE_NAME ${SLANG_FILE} NAME_WE) + + # Un seul fichier de sortie par shader source + set(OUTPUT_FILE "${OUTPUT_DIR}/${FILE_NAME}.spv") + + # Compiler tout le shader en un seul SPIR-V + add_custom_command( + OUTPUT ${OUTPUT_FILE} + COMMAND ${SLANG_COMPILER} + ${SLANG_FILE} + -target spirv + -profile spirv_1_4 + -emit-spirv-directly + -o ${OUTPUT_FILE} + DEPENDS ${SLANG_FILE} + COMMENT "Compiling Slang shader ${FILE_NAME} → ${OUTPUT_FILE}" + VERBATIM + ) + + list(APPEND GENERATED_SPV_FILES ${OUTPUT_FILE}) + endforeach() + + set(GENERATED_SPV_FILES ${GENERATED_SPV_FILES} PARENT_SCOPE) +endfunction() -# On indique que l'on veut un exécutable nommé PROJECT compilé à partir des fichiers décrits par les variables SRCS et HEADERS. add_library(Engine SHARED ${SRCS_ENGINE} ${SRCS_EXTERNAL_GLAD}) add_executable(${PROJECT} ${SRCS}) -add_dependencies(${PROJECT} Engine) - add_executable(CosmicTest ${SRCS_TESTS}) + +# On indique que l'on veut un exécutable nommé PROJECT compilé à partir des fichiers décrits par les variables SRCS et HEADERS. +file(GLOB_RECURSE SLANG_SHADERS "${PATH_TO_SHADER_BUILD_TYPE}/assets/shaders/slang/*.slang") +compile_slang_shaders("${SLANG_SHADERS}" "${PATH_TO_SHADER_BUILD_TYPE}/assets/shaders/slang/spv") + +message(STATUS "GENERATED_SPV_FILES = ${GENERATED_SPV_FILES}") + +# Créer la target ICI, au niveau global +if(GENERATED_SPV_FILES) + add_custom_target(CompileSlangShaders ALL + DEPENDS ${GENERATED_SPV_FILES} + ) +endif() + +add_dependencies(${PROJECT} Engine) +add_dependencies(Engine CompileSlangShaders) + + target_link_libraries(CosmicTest PRIVATE Catch2::Catch2WithMain Engine) # Fichier include @@ -295,9 +426,12 @@ include_directories(${GLM_INCLUDE_DIRS}) include_directories(${JSONFMCPP_INCLUDE_DIRS}) #ENTT include_directories(${ENTT_INCLUDE_DIRS}) +#include_directories(${SPIRV_INCLUDE_DIRS}) +include_directories(${SPIRV_REFLECT_INCLUDE_DIRS}) +include_directories(${VMA_INCLUDE_DIRS}) # ASSIMP -#include_directories(${ASSIMP_INCLUDE_DIRS}) +include_directories(${ASSIMP_INCLUDE_DIRS}) # ODE #include_directories(${ODE_INCLUDE_DIRS}) # SNDFILE @@ -314,21 +448,28 @@ include_directories(${ENTT_INCLUDE_DIRS}) # SDL2 #target_link_libraries(Engine ${SDL2_LIBRARIES}) - +target_link_libraries(Engine SDL3::SDL3) # GLEW #target_link_libraries(Engine ${GLEW_LIBRARIES}) # SDL2_image #target_link_libraries(Engine SDL2_image) +target_link_libraries(Engine SDL3_image) # SDL2_ttf #target_link_libraries(Engine SDL2_ttf) - +target_link_libraries(Engine SDL3_ttf) # Boost +#Vulkan +target_link_libraries(Engine Vulkan::Vulkan) + +target_link_libraries(Engine spirv-reflect) + +#target_link_libraries(Engine spirv-cross-glsl spirv-cross-core) # ASSIMP -#target_link_libraries(Engine ${ASSIMP_LIBRARIES}) +target_link_libraries(Engine ${ASSIMP_LIBRARIES}) # ODE @@ -368,7 +509,7 @@ endif() # Paramètre de compilation if (UNIX) - set(CMAKE_CXX_FLAGS "-Wall -ldl -fPIC") + set(CMAKE_CXX_FLAGS "-Wall -fPIC") endif () # Valgrind ne marche que pour Linux... diff --git a/assets/shaders/slang/triangle.slang b/assets/shaders/slang/triangle.slang new file mode 100644 index 0000000..79449fa --- /dev/null +++ b/assets/shaders/slang/triangle.slang @@ -0,0 +1,31 @@ +static float2 positions[3] = float2[]( + float2(0.0, -0.5), + float2(0.5, 0.5), + float2(-0.5, 0.5) +); + +static float3 colors[3] = float3[]( + float3(1.0, 0.0, 0.0), + float3(0.0, 1.0, 0.0), + float3(0.0, 0.0, 1.0) +); + +struct VertexOutput { + float3 color; + float4 sv_position : SV_Position; +}; + +[shader("vertex")] +VertexOutput vertMain(uint vid : SV_VertexID) { + VertexOutput output; + output.sv_position = float4(positions[vid], 0.0, 1.0); + output.color = colors[vid]; + return output; +} + +[shader("fragment")] +float4 fragMain(VertexOutput inVert) : SV_Target +{ + float3 color = inVert.color; + return float4(color, 1.0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/.clang-format b/lib/All/SPIRV-Reflect/.clang-format new file mode 100644 index 0000000..551b185 --- /dev/null +++ b/lib/All/SPIRV-Reflect/.clang-format @@ -0,0 +1,7 @@ +--- +Language: Cpp +BasedOnStyle: Google +DerivePointerAlignment: false +SortIncludes: true +ColumnLimit: 132 +... diff --git a/lib/All/SPIRV-Reflect/.git-blame-ignore-revs b/lib/All/SPIRV-Reflect/.git-blame-ignore-revs new file mode 100644 index 0000000..ae4e1bc --- /dev/null +++ b/lib/All/SPIRV-Reflect/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# rerun clang-format with 132 line width +dc6582bf8c1520a632dca98b11974048ad89fe16 diff --git a/lib/All/SPIRV-Reflect/.github/workflows/check-formatting.yml b/lib/All/SPIRV-Reflect/.github/workflows/check-formatting.yml new file mode 100644 index 0000000..d878faf --- /dev/null +++ b/lib/All/SPIRV-Reflect/.github/workflows/check-formatting.yml @@ -0,0 +1,47 @@ +name: Code formatting check + +on: + pull_request: + +# Cancel previous runs if a more recent commit is pushed. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +permissions: read-all + +jobs: + clang-format-check: + name: clang-format + runs-on: ubuntu-latest + steps: + - name: Setup clang-format + run: | + sudo apt-get install -yqq clang-format + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: '0' + - name: Switch to pull request branch + run: | + git checkout ${GITHUB_SHA} + - name: Run clang-format + run: | + git diff origin/${{ github.base_ref }} -U0 --no-color -- '**/*.cpp' '**/*.cc' '**/*.h' '**/*.hh' '**/*.hpp' \ + | clang-format-diff -p1 >not-formatted.diff 2>&1 + - name: Check formatting + run: | + if ! grep -q '[^[:space:]]' not-formatted.diff ; then + echo "Code is formatted." + else + echo "Code is not formatted." + echo "Run clang-format-diff on your changes:" + echo " git diff origin/${{ github.base_ref }} -U0 --no-color | clang-format-diff -p1 -i" + echo "" + echo "You can disable clang-format for specific code blocks. Follow https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code." + echo "" + echo "Diff:" + cat not-formatted.diff + echo "" + exit 3 + fi diff --git a/lib/All/SPIRV-Reflect/.github/workflows/linux-cmake-build.yml b/lib/All/SPIRV-Reflect/.github/workflows/linux-cmake-build.yml new file mode 100644 index 0000000..6f84489 --- /dev/null +++ b/lib/All/SPIRV-Reflect/.github/workflows/linux-cmake-build.yml @@ -0,0 +1,58 @@ +name: Linux build + +on: + pull_request: + +# Cancel previous runs if a more recent commit is pushed. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +permissions: read-all + +jobs: + linux-build: + name: Build and run tests on Linux using CMake + runs-on: ubuntu-latest + strategy: + matrix: + asan: ["ON", "OFF"] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: '0' + - name: Clone submodules + run: git submodule update --init --recursive + - name: Build + run: | + mkdir build + cd build + cmake .. -DCMAKE_BUILD_TYPE=Release -DSPIRV_REFLECT_BUILD_TESTS=ON -DSPIRV_REFLECT_ENABLE_ASAN=${{matrix.asan}} + make -j $(nproc) + - name: Run unit tests + run: | + cd build + ./test-spirv-reflect + - name: Clone SPIRV-Database + run: | + git clone https://github.com/LunarG/SPIRV-Database.git build/SPIRV-Database + - name: Test - SaschaWillemsVulkan + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/SaschaWillemsVulkan/ + - name: Test - clspv + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/clspv/ + - name: Test - dawn + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/dawn/ + - name: Test - gl_cts + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/gl_cts/ + - name: Test - naga + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/naga/remaps/ + - name: Test - tint + run: | + python tests/ci_database.py --dir build/SPIRV-Database/vulkan/tint/ diff --git a/lib/All/SPIRV-Reflect/.github/workflows/windows-cmake-build.yml b/lib/All/SPIRV-Reflect/.github/workflows/windows-cmake-build.yml new file mode 100644 index 0000000..19df5dd --- /dev/null +++ b/lib/All/SPIRV-Reflect/.github/workflows/windows-cmake-build.yml @@ -0,0 +1,30 @@ +name: Windows build + +on: + pull_request: + +# Cancel previous runs if a more recent commit is pushed. +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true + +permissions: read-all + +jobs: + windows-build: + name: Build and run tests on Windows using CMake + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: '0' + - name: Clone submodules + run: git submodule update --init --recursive + - name: Build + run: | + mkdir build + cd build + cmake -DSPIRV_REFLECT_BUILD_TESTS=ON .. + + cmake --build . --config Release -- /nologo /verbosity:minimal /maxcpucount diff --git a/lib/All/SPIRV-Reflect/.gitignore b/lib/All/SPIRV-Reflect/.gitignore new file mode 100644 index 0000000..cf6c326 --- /dev/null +++ b/lib/All/SPIRV-Reflect/.gitignore @@ -0,0 +1,10 @@ +/build* +/bin/* +bazel-bin +bazel-genfiles +bazel-out +bazel-spirv-reflect +bazel-SPIRV-Reflect +bazel-testlogs +/.vs +/.vscode \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/.gitmodules b/lib/All/SPIRV-Reflect/.gitmodules new file mode 100644 index 0000000..8d4f8c9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/googletest"] + path = third_party/googletest + url = https://github.com/google/googletest diff --git a/lib/All/SPIRV-Reflect/CMakeLists.txt b/lib/All/SPIRV-Reflect/CMakeLists.txt new file mode 100644 index 0000000..d893b0d --- /dev/null +++ b/lib/All/SPIRV-Reflect/CMakeLists.txt @@ -0,0 +1,130 @@ +cmake_minimum_required(VERSION 3.16) + +project(spirv-reflect) + +OPTION(SPIRV_REFLECT_EXECUTABLE "Build spirv-reflect executable" ON) + +OPTION(SPIRV_REFLECT_STATIC_LIB "Build a SPIRV-Reflect static library" OFF) +OPTION(SPIRV_REFLECT_BUILD_TESTS "Build the SPIRV-Reflect test suite" OFF) +OPTION(SPIRV_REFLECT_ENABLE_ASSERTS "Enable asserts for debugging" OFF) +OPTION(SPIRV_REFLECT_ENABLE_ASAN "Use address sanitization" OFF) +OPTION(SPIRV_REFLECT_INSTALL "Whether to install" ON) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set(CMAKE_CXX_STANDARD 14) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin") + +if (SPIRV_REFLECT_ENABLE_ASAN) + add_compile_options(-fsanitize=address -fno-omit-frame-pointer) + add_link_options(-fsanitize=address) +endif() + +if (SPIRV_REFLECT_EXECUTABLE) + # ========================================================================== + # Compile spirv_reflect.c as C + # ========================================================================== + add_executable(spirv-reflect ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.h + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.c + ${CMAKE_CURRENT_SOURCE_DIR}/examples/arg_parser.h + ${CMAKE_CURRENT_SOURCE_DIR}/examples/arg_parser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/examples/common.h + ${CMAKE_CURRENT_SOURCE_DIR}/examples/common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.cpp) + target_compile_options(spirv-reflect PRIVATE + $<$:/W4 /WX> + $<$:-Wall -Wextra -Wpedantic -Werror> + $<$:-Wall -Wextra -Wpedantic -Werror> + $<$:-Wall -Wextra -Wpedantic -Werror>) + if (SPIRV_REFLECT_ENABLE_ASSERTS) + target_compile_definitions(spirv-reflect PRIVATE SPIRV_REFLECT_ENABLE_ASSERTS) + endif() + + set_target_properties(spirv-reflect PROPERTIES CXX_STANDARD 11) + target_include_directories(spirv-reflect PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + if(WIN32) + target_compile_definitions(spirv-reflect PRIVATE _CRT_SECURE_NO_WARNINGS) + endif() + + if(SPIRV_REFLECT_INSTALL) + install(TARGETS spirv-reflect RUNTIME DESTINATION bin) + endif() + + # ========================================================================== + # Compile spirv_reflect.c as C++ + # ========================================================================== + add_executable(spirv-reflect-pp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.h + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/examples/arg_parser.h + ${CMAKE_CURRENT_SOURCE_DIR}/examples/arg_parser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/examples/common.h + ${CMAKE_CURRENT_SOURCE_DIR}/examples/common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.cpp) + target_compile_options(spirv-reflect-pp PRIVATE + $<$:/W4 /WX> + $<$:-Wall -Wextra -Wpedantic -Werror> + $<$:-Wall -Wextra -Wpedantic -Werror> + $<$:-Wall -Wextra -Wpedantic -Werror>) + if (SPIRV_REFLECT_ENABLE_ASSERTS) + target_compile_definitions(spirv-reflect-pp PRIVATE SPIRV_REFLECT_ENABLE_ASSERTS) + endif() + set_target_properties(spirv-reflect-pp PROPERTIES CXX_STANDARD 11) + target_include_directories(spirv-reflect-pp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + if(WIN32) + target_compile_definitions(spirv-reflect-pp PRIVATE _CRT_SECURE_NO_WARNINGS) + endif() + + if(SPIRV_REFLECT_INSTALL) + install(TARGETS spirv-reflect-pp RUNTIME DESTINATION bin) + endif() +endif() + +if (SPIRV_REFLECT_EXAMPLES) + add_subdirectory(examples) +endif() + +if (SPIRV_REFLECT_BUILD_TESTS) + message("Tests are enabled!") + SET(BUILD_GMOCK OFF CACHE BOOL "Builds the googlemock subproject" FORCE) + SET(BUILD_GTEST ON CACHE BOOL "Builds the googletest subproject" FORCE) + SET(INSTALL_GTEST OFF CACHE BOOL "Enable installation of googletest. (Projects embedding googletest generally turn this OFF.)" FORCE) + SET(gtest_force_shared_crt ON CACHE BOOL "Enable DLL for C runtime libraries on Windows" FORCE) + + add_subdirectory(third_party/googletest) + add_executable(test-spirv-reflect ${CMAKE_CURRENT_SOURCE_DIR}/tests/test-spirv-reflect.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.h + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.h + ${CMAKE_CURRENT_SOURCE_DIR}/common/output_stream.cpp) + set_target_properties(test-spirv-reflect PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + CXX_STANDARD 11) + target_compile_definitions(test-spirv-reflect PRIVATE + $<$:_CRT_SECURE_NO_WARNINGS>) + target_link_libraries(test-spirv-reflect gtest_main) + target_include_directories(test-spirv-reflect PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + add_custom_command(TARGET test-spirv-reflect POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests) +endif() + +if(SPIRV_REFLECT_STATIC_LIB) + add_library(spirv-reflect-static STATIC ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.h + ${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.c) + + target_include_directories(spirv-reflect-static + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + + set_target_properties(spirv-reflect-static PROPERTIES PUBLIC_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/spirv_reflect.h") + + if(SPIRV_REFLECT_INSTALL) + install(TARGETS spirv-reflect-static + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include) + endif() +endif() diff --git a/lib/All/SPIRV-Reflect/CODE_OF_CONDUCT.adoc b/lib/All/SPIRV-Reflect/CODE_OF_CONDUCT.adoc new file mode 100644 index 0000000..fc58601 --- /dev/null +++ b/lib/All/SPIRV-Reflect/CODE_OF_CONDUCT.adoc @@ -0,0 +1,11 @@ +// Copyright (c) 2018-2020 The Khronos Group Inc. +// +// SPDX-License-Identifier: CC-BY-4.0 + += Code of Conduct + +A reminder that this issue tracker is managed by the Khronos Group. +Interactions here should follow the +https://www.khronos.org/developers/code-of-conduct[Khronos Code of Conduct], +which prohibits aggressive or derogatory language. Please keep the +discussion friendly and civil. diff --git a/lib/All/SPIRV-Reflect/LICENSE b/lib/All/SPIRV-Reflect/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/lib/All/SPIRV-Reflect/README.md b/lib/All/SPIRV-Reflect/README.md new file mode 100644 index 0000000..4f7e82b --- /dev/null +++ b/lib/All/SPIRV-Reflect/README.md @@ -0,0 +1,141 @@ +# SPIRV-Reflect + +SPIRV-Reflect is a lightweight library that provides a C/C++ reflection API for +[SPIR-V](https://www.khronos.org/spir/) shader bytecode in +[Vulkan](https://www.khronos.org/vulkan/) applications. + +SPIRV-Reflect has been tested on Linux and Windows. + +## NEWS + +- **2023-07-04** - We have removed support for + [Bazel](https://bazel.build). +- **2023-06-07** - We are planning to remove support for + [Bazel](https://bazel.build/). If you rely on Bazel for + building this code, please let us know in + https://github.com/KhronosGroup/SPIRV-Reflect/issues/188. +- **2023-05-03** - The `master` branch has been renamed to `main` (see + https://github.com/KhronosGroup/SPIRV-Reflect/issues/164 for + details). Please update your fork as per instructions in that + issue. + +## Features + +- Extract descriptor bindings from SPIR-V bytecode, to assist in the generation of + Vulkan descriptor set and pipeline layouts. +- Extract push constant block size from SPIR-V bytecode to assist in the generation + of pipeline layouts. +- Extract full layout data for uniform buffer and push constant blocks from SPIR-V + bytecode, to assist in application updates of these structures. +- Extract input/output variables from SPIR-V bytecode (including semantic decorations + for HLSL shaders), to assist in validation of pipeline input/output settings. +- Remap descriptor bindings at runtime, and update the source SPIR-V bytecode + accordingly. +- Log all reflection data as human-readable text. + +## Integration + +SPIRV-Reflect is designed to make integration as easy as possible. The only +external dependency is the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home). + +To integrate SPIRV-Reflect into a project, simply add `spirv_reflect.h` and +`spirv_reflect.c` in the project's build, and include `spirv_reflect.h` from +the necessary source files. + +If the project wants to use it's own SPIRV-Header path, it can set `SPIRV_REFLECT_USE_SYSTEM_SPIRV_H` + +```cmake +# CMake example +target_compile_definitions(project_name PUBLIC SPIRV_REFLECT_USE_SYSTEM_SPIRV_H) +``` + +## Building Samples + +**This step is only necessary when building/running SPIRV-Reflect's example applications.** + +SPIRV-Reflect includes a collection of sample programs in the `examples/` directory which +demonstrate various use cases: + +- **descriptors**: This sample demonstrates the retrieval of descriptor bindings, including + the population of `VkDescriptorSetLayoutCreateInfo` structures from reflection data. +- **hlsl_resource_types**: This sample shows how various HLSL resource types are represented + in SPIR-V. +- **io_variables**: This sample demonstrates the retrieval of input/output variables, including + the population of `VkPipelineVertexInputStateCreateInfo` structures from reflection data. + +To build the included sample applications, use [CMake](https://cmake.org/) to generate the +appropriate project files for your platform, then build them as usual. + +Note that you can set VulkanSDK directory as your preference. For example, on Linux: +``` +VULKAN_SDK=$HOME/VulkanSDK/1.1.70.1/x86_64 cmake -G Ninja .. +``` + + +## Usage + +SPIRV-Reflect's core C API should be familiar to Vulkan developers: + +```c++ +#include "spirv_reflect.h" + +int SpirvReflectExample(const void* spirv_code, size_t spirv_nbytes) +{ + // Generate reflection data for a shader + SpvReflectShaderModule module; + SpvReflectResult result = spvReflectCreateShaderModule(spirv_nbytes, spirv_code, &module); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + // Enumerate and extract shader's input variables + uint32_t var_count = 0; + result = spvReflectEnumerateInputVariables(&module, &var_count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + SpvReflectInterfaceVariable** input_vars = + (SpvReflectInterfaceVariable**)malloc(var_count * sizeof(SpvReflectInterfaceVariable*)); + result = spvReflectEnumerateInputVariables(&module, &var_count, input_vars); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + // Output variables, descriptor bindings, descriptor sets, and push constants + // can be enumerated and extracted using a similar mechanism. + + // Destroy the reflection data when no longer required. + spvReflectDestroyShaderModule(&module); +} +``` + +A C++ wrapper is also provided. + +## Building Examples + +By adding `-DSPIRV_REFLECT_EXAMPLES=ON` in CMake you can see the use of the API used in action. + +The `main_explorer.cpp` file is designed to allow an user to use their debugger of choice to breakpoint +and explorer the contents of the `SpvReflectShaderModule` object. Just build with `-DCMAKE_BUILD_TYPE=Debug` +and setup a debugger to run `./bin/explorer path/to/shader.spv` + +## Building Self-Test Suite + +SPIRV-Reflect uses [googletest](https://github.com/google/googletest) for self-testing. +This component is optional, and generally only of interest to developers modifying SPIRV-Reflect. +To run the self-tests: + +- `git submodule init` +- `git submodule update` +- Enable `SPIRV_REFLECT_BUILD_TESTS` in CMake +- Build and run the `test-spirv-reflect` project. + +## License + +Copyright 2017-2018 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/lib/All/SPIRV-Reflect/SECURITY.md b/lib/All/SPIRV-Reflect/SECURITY.md new file mode 100644 index 0000000..94696df --- /dev/null +++ b/lib/All/SPIRV-Reflect/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Security updates are applied only to the latest release. + +## Reporting a Vulnerability + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/KhronosGroup/SPIRV-Reflect/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. diff --git a/lib/All/SPIRV-Reflect/common/output_stream.cpp b/lib/All/SPIRV-Reflect/common/output_stream.cpp new file mode 100644 index 0000000..fee5e04 --- /dev/null +++ b/lib/All/SPIRV-Reflect/common/output_stream.cpp @@ -0,0 +1,2362 @@ +#include "output_stream.h" + +#include +#include +#include +#include +#include +#include +#include + +enum TextLineType { + TEXT_LINE_TYPE_BLOCK_BEGIN = 0x01, + TEXT_LINE_TYPE_BLOCK_END = 0x02, + TEXT_LINE_TYPE_STRUCT_BEGIN = 0x04, + TEXT_LINE_TYPE_STRUCT_END = 0x08, + TEXT_LINE_TYPE_REF_BEGIN = 0x10, + TEXT_LINE_TYPE_REF_END = 0x20, + TEXT_LINE_TYPE_LINES = 0x40, +}; + +struct TextLine { + std::string indent; + std::string modifier; + std::string type_name; + std::string name; + uint32_t absolute_offset; + uint32_t relative_offset; + uint32_t size; + uint32_t padded_size; + uint32_t array_stride; + uint32_t block_variable_flags; + std::vector array_dims; + // Text Data + uint32_t text_line_flags; + std::vector lines; + std::string formatted_line; + std::string formatted_absolute_offset; + std::string formatted_relative_offset; + std::string formatted_size; + std::string formatted_padded_size; + std::string formatted_array_stride; + std::string formatted_block_variable_flags; +}; + +static std::string AsHexString(uint32_t n) { + // std::iomanip can die in a fire. + char out_word[11]; + int len = snprintf(out_word, 11, "0x%08X", n); + assert(len == 10); + (void)len; + return std::string(out_word); +} + +std::string ToStringGenerator(SpvReflectGenerator generator) { + switch (generator) { + case SPV_REFLECT_GENERATOR_KHRONOS_LLVM_SPIRV_TRANSLATOR: + return "Khronos LLVM/SPIR-V Translator"; + break; + case SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_ASSEMBLER: + return "Khronos SPIR-V Tools Assembler"; + break; + case SPV_REFLECT_GENERATOR_KHRONOS_GLSLANG_REFERENCE_FRONT_END: + return "Khronos Glslang Reference Front End"; + break; + case SPV_REFLECT_GENERATOR_GOOGLE_SHADERC_OVER_GLSLANG: + return "Google Shaderc over Glslang"; + break; + case SPV_REFLECT_GENERATOR_GOOGLE_SPIREGG: + return "Google spiregg"; + break; + case SPV_REFLECT_GENERATOR_GOOGLE_RSPIRV: + return "Google rspirv"; + break; + case SPV_REFLECT_GENERATOR_X_LEGEND_MESA_MESAIR_SPIRV_TRANSLATOR: + return "X-LEGEND Mesa-IR/SPIR-V Translator"; + break; + case SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_LINKER: + return "Khronos SPIR-V Tools Linker"; + break; + case SPV_REFLECT_GENERATOR_WINE_VKD3D_SHADER_COMPILER: + return "Wine VKD3D Shader Compiler"; + break; + case SPV_REFLECT_GENERATOR_CLAY_CLAY_SHADER_COMPILER: + return "Clay Clay Shader Compiler"; + break; + case SPV_REFLECT_GENERATOR_SLANG_SHADER_COMPILER: + return "Slang Shader Compiler"; + break; + } + // unhandled SpvReflectGenerator enum value + return "???"; +} + +std::string ToStringSpvSourceLanguage(SpvSourceLanguage lang) { + switch (lang) { + case SpvSourceLanguageESSL: + return "ESSL"; + case SpvSourceLanguageGLSL: + return "GLSL"; + case SpvSourceLanguageOpenCL_C: + return "OpenCL_C"; + case SpvSourceLanguageOpenCL_CPP: + return "OpenCL_CPP"; + case SpvSourceLanguageHLSL: + return "HLSL"; + case SpvSourceLanguageCPP_for_OpenCL: + return "CPP_for_OpenCL"; + case SpvSourceLanguageSYCL: + return "SYCL"; + case SpvSourceLanguageHERO_C: + return "Hero C"; + case SpvSourceLanguageNZSL: + return "NZSL"; + case SpvSourceLanguageWGSL: + return "WGSL"; + case SpvSourceLanguageSlang: + return "Slang"; + case SpvSourceLanguageZig: + return "Zig"; + case SpvSourceLanguageRust: + return "Rust"; + + default: + break; + } + // SpvSourceLanguageUnknown, SpvSourceLanguageMax, or another value that does + // not correspond to a known language. + return "Unknown"; +} + +std::string ToStringSpvExecutionModel(SpvExecutionModel model) { + switch (model) { + case SpvExecutionModelVertex: + return "Vertex"; + case SpvExecutionModelTessellationControl: + return "TessellationControl"; + case SpvExecutionModelTessellationEvaluation: + return "TessellationEvaluation"; + case SpvExecutionModelGeometry: + return "Geometry"; + case SpvExecutionModelFragment: + return "Fragment"; + case SpvExecutionModelGLCompute: + return "GLCompute"; + case SpvExecutionModelKernel: + return "Kernel"; + case SpvExecutionModelTaskNV: + return "TaskNV"; + case SpvExecutionModelMeshNV: + return "MeshNV"; + case SpvExecutionModelTaskEXT: + return "TaskEXT"; + case SpvExecutionModelMeshEXT: + return "MeshEXT"; + case SpvExecutionModelRayGenerationKHR: + return "RayGenerationKHR"; + case SpvExecutionModelIntersectionKHR: + return "IntersectionKHR"; + case SpvExecutionModelAnyHitKHR: + return "AnyHitKHR"; + case SpvExecutionModelClosestHitKHR: + return "ClosestHitKHR"; + case SpvExecutionModelMissKHR: + return "MissKHR"; + case SpvExecutionModelCallableKHR: + return "CallableKHR"; + + case SpvExecutionModelMax: + break; + + default: + break; + } + + // unhandled SpvExecutionModel enum value + return "???"; +} + +std::string ToStringShaderStage(SpvReflectShaderStageFlagBits stage) { + switch (stage) { + case SPV_REFLECT_SHADER_STAGE_VERTEX_BIT: + return "VS"; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return "HS"; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return "DS"; + case SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT: + return "GS"; + case SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT: + return "PS"; + case SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT: + return "CS"; + case SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV: + return "TASK"; + case SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV: + return "MESH"; + case SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR: + return "RAYGEN"; + case SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR: + return "ANY_HIT"; + case SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: + return "CLOSEST_HIT"; + case SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR: + return "MISS"; + case SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR: + return "INTERSECTION"; + case SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR: + return "CALLABLE"; + + default: + break; + } + + // Unhandled SpvReflectShaderStageFlagBits enum value + return "???"; +} + +std::string ToStringSpvStorageClass(int storage_class) { + switch (storage_class) { + case SpvStorageClassUniformConstant: + return "UniformConstant"; + case SpvStorageClassInput: + return "Input"; + case SpvStorageClassUniform: + return "Uniform"; + case SpvStorageClassOutput: + return "Output"; + case SpvStorageClassWorkgroup: + return "Workgroup"; + case SpvStorageClassCrossWorkgroup: + return "CrossWorkgroup"; + case SpvStorageClassPrivate: + return "Private"; + case SpvStorageClassFunction: + return "Function"; + case SpvStorageClassGeneric: + return "Generic"; + case SpvStorageClassPushConstant: + return "PushConstant"; + case SpvStorageClassAtomicCounter: + return "AtomicCounter"; + case SpvStorageClassImage: + return "Image"; + case SpvStorageClassStorageBuffer: + return "StorageBuffer"; + case SpvStorageClassCallableDataKHR: + return "CallableDataKHR"; + case SpvStorageClassIncomingCallableDataKHR: + return "IncomingCallableDataKHR"; + case SpvStorageClassRayPayloadKHR: + return "RayPayloadKHR"; + case SpvStorageClassHitAttributeKHR: + return "HitAttributeKHR"; + case SpvStorageClassIncomingRayPayloadKHR: + return "IncomingRayPayloadKHR"; + case SpvStorageClassShaderRecordBufferKHR: + return "ShaderRecordBufferKHR"; + case SpvStorageClassPhysicalStorageBuffer: + return "PhysicalStorageBuffer"; + case SpvStorageClassCodeSectionINTEL: + return "CodeSectionINTEL"; + case SpvStorageClassDeviceOnlyINTEL: + return "DeviceOnlyINTEL"; + case SpvStorageClassHostOnlyINTEL: + return "HostOnlyINTEL"; + case SpvStorageClassMax: + break; + + default: + break; + } + + // Special case: this specific "unhandled" value does actually seem to show + // up. + if (storage_class == (SpvStorageClass)-1) { + return "NOT APPLICABLE"; + } + + // unhandled SpvStorageClass enum value + return "???"; +} + +std::string ToStringSpvDim(SpvDim dim) { + switch (dim) { + case SpvDim1D: + return "1D"; + case SpvDim2D: + return "2D"; + case SpvDim3D: + return "3D"; + case SpvDimCube: + return "Cube"; + case SpvDimRect: + return "Rect"; + case SpvDimBuffer: + return "Buffer"; + case SpvDimSubpassData: + return "SubpassData"; + case SpvDimTileImageDataEXT: + return "DimTileImageDataEXT"; + + case SpvDimMax: + break; + } + // unhandled SpvDim enum value + return "???"; +} + +std::string ToStringResourceType(SpvReflectResourceType res_type) { + switch (res_type) { + case SPV_REFLECT_RESOURCE_FLAG_UNDEFINED: + return "UNDEFINED"; + case SPV_REFLECT_RESOURCE_FLAG_SAMPLER: + return "SAMPLER"; + case SPV_REFLECT_RESOURCE_FLAG_CBV: + return "CBV"; + case SPV_REFLECT_RESOURCE_FLAG_SRV: + return "SRV"; + case SPV_REFLECT_RESOURCE_FLAG_UAV: + return "UAV"; + } + // unhandled SpvReflectResourceType enum value + return "???"; +} + +std::string ToStringDescriptorType(SpvReflectDescriptorType value) { + switch (value) { + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_SAMPLER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE"; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER"; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC"; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC"; + case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT"; + case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return "VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR"; + } + // unhandled SpvReflectDescriptorType enum value + return "VK_DESCRIPTOR_TYPE_???"; +} + +static std::string ToStringSpvBuiltIn(int built_in) { + switch (built_in) { + case SpvBuiltInPosition: + return "Position"; + case SpvBuiltInPointSize: + return "PointSize"; + case SpvBuiltInClipDistance: + return "ClipDistance"; + case SpvBuiltInCullDistance: + return "CullDistance"; + case SpvBuiltInVertexId: + return "VertexId"; + case SpvBuiltInInstanceId: + return "InstanceId"; + case SpvBuiltInPrimitiveId: + return "PrimitiveId"; + case SpvBuiltInInvocationId: + return "InvocationId"; + case SpvBuiltInLayer: + return "Layer"; + case SpvBuiltInViewportIndex: + return "ViewportIndex"; + case SpvBuiltInTessLevelOuter: + return "TessLevelOuter"; + case SpvBuiltInTessLevelInner: + return "TessLevelInner"; + case SpvBuiltInTessCoord: + return "TessCoord"; + case SpvBuiltInPatchVertices: + return "PatchVertices"; + case SpvBuiltInFragCoord: + return "FragCoord"; + case SpvBuiltInPointCoord: + return "PointCoord"; + case SpvBuiltInFrontFacing: + return "FrontFacing"; + case SpvBuiltInSampleId: + return "SampleId"; + case SpvBuiltInSamplePosition: + return "SamplePosition"; + case SpvBuiltInSampleMask: + return "SampleMask"; + case SpvBuiltInFragDepth: + return "FragDepth"; + case SpvBuiltInHelperInvocation: + return "HelperInvocation"; + case SpvBuiltInNumWorkgroups: + return "NumWorkgroups"; + case SpvBuiltInWorkgroupSize: + return "WorkgroupSize"; + case SpvBuiltInWorkgroupId: + return "WorkgroupId"; + case SpvBuiltInLocalInvocationId: + return "LocalInvocationId"; + case SpvBuiltInGlobalInvocationId: + return "GlobalInvocationId"; + case SpvBuiltInLocalInvocationIndex: + return "LocalInvocationIndex"; + case SpvBuiltInWorkDim: + return "WorkDim"; + case SpvBuiltInGlobalSize: + return "GlobalSize"; + case SpvBuiltInEnqueuedWorkgroupSize: + return "EnqueuedWorkgroupSize"; + case SpvBuiltInGlobalOffset: + return "GlobalOffset"; + case SpvBuiltInGlobalLinearId: + return "GlobalLinearId"; + case SpvBuiltInSubgroupSize: + return "SubgroupSize"; + case SpvBuiltInSubgroupMaxSize: + return "SubgroupMaxSize"; + case SpvBuiltInNumSubgroups: + return "NumSubgroups"; + case SpvBuiltInNumEnqueuedSubgroups: + return "NumEnqueuedSubgroups"; + case SpvBuiltInSubgroupId: + return "SubgroupId"; + case SpvBuiltInSubgroupLocalInvocationId: + return "SubgroupLocalInvocationId"; + case SpvBuiltInVertexIndex: + return "VertexIndex"; + case SpvBuiltInInstanceIndex: + return "InstanceIndex"; + case SpvBuiltInSubgroupEqMaskKHR: + return "SubgroupEqMaskKHR"; + case SpvBuiltInSubgroupGeMaskKHR: + return "SubgroupGeMaskKHR"; + case SpvBuiltInSubgroupGtMaskKHR: + return "SubgroupGtMaskKHR"; + case SpvBuiltInSubgroupLeMaskKHR: + return "SubgroupLeMaskKHR"; + case SpvBuiltInSubgroupLtMaskKHR: + return "SubgroupLtMaskKHR"; + case SpvBuiltInBaseVertex: + return "BaseVertex"; + case SpvBuiltInBaseInstance: + return "BaseInstance"; + case SpvBuiltInDrawIndex: + return "DrawIndex"; + case SpvBuiltInDeviceIndex: + return "DeviceIndex"; + case SpvBuiltInViewIndex: + return "ViewIndex"; + case SpvBuiltInBaryCoordNoPerspAMD: + return "BaryCoordNoPerspAMD"; + case SpvBuiltInBaryCoordNoPerspCentroidAMD: + return "BaryCoordNoPerspCentroidAMD"; + case SpvBuiltInBaryCoordNoPerspSampleAMD: + return "BaryCoordNoPerspSampleAMD"; + case SpvBuiltInBaryCoordSmoothAMD: + return "BaryCoordSmoothAMD"; + case SpvBuiltInBaryCoordSmoothCentroidAMD: + return "BaryCoordSmoothCentroidAMD"; + case SpvBuiltInBaryCoordSmoothSampleAMD: + return "BaryCoordSmoothSampleAMD"; + case SpvBuiltInBaryCoordPullModelAMD: + return "BaryCoordPullModelAMD"; + case SpvBuiltInFragStencilRefEXT: + return "FragStencilRefEXT"; + case SpvBuiltInViewportMaskNV: + return "ViewportMaskNV"; + case SpvBuiltInSecondaryPositionNV: + return "SecondaryPositionNV"; + case SpvBuiltInSecondaryViewportMaskNV: + return "SecondaryViewportMaskNV"; + case SpvBuiltInPositionPerViewNV: + return "PositionPerViewNV"; + case SpvBuiltInViewportMaskPerViewNV: + return "ViewportMaskPerViewNV"; + case SpvBuiltInLaunchIdKHR: + return "InLaunchIdKHR"; + case SpvBuiltInLaunchSizeKHR: + return "InLaunchSizeKHR"; + case SpvBuiltInWorldRayOriginKHR: + return "InWorldRayOriginKHR"; + case SpvBuiltInWorldRayDirectionKHR: + return "InWorldRayDirectionKHR"; + case SpvBuiltInObjectRayOriginKHR: + return "InObjectRayOriginKHR"; + case SpvBuiltInObjectRayDirectionKHR: + return "InObjectRayDirectionKHR"; + case SpvBuiltInRayTminKHR: + return "InRayTminKHR"; + case SpvBuiltInRayTmaxKHR: + return "InRayTmaxKHR"; + case SpvBuiltInInstanceCustomIndexKHR: + return "InInstanceCustomIndexKHR"; + case SpvBuiltInObjectToWorldKHR: + return "InObjectToWorldKHR"; + case SpvBuiltInWorldToObjectKHR: + return "InWorldToObjectKHR"; + case SpvBuiltInHitTNV: + return "InHitTNV"; + case SpvBuiltInHitKindKHR: + return "InHitKindKHR"; + case SpvBuiltInIncomingRayFlagsKHR: + return "InIncomingRayFlagsKHR"; + case SpvBuiltInRayGeometryIndexKHR: + return "InRayGeometryIndexKHR"; + + case SpvBuiltInMax: + default: + break; + } + // unhandled SpvBuiltIn enum value + std::stringstream ss; + ss << "??? (" << built_in << ")"; + return ss.str(); +} + +std::string ToStringSpvBuiltIn(const SpvReflectInterfaceVariable& variable, bool preface) { + std::stringstream ss; + if (variable.decoration_flags & SPV_REFLECT_DECORATION_BLOCK) { + if (preface) { + ss << "(built-in block) "; + } + ss << "["; + for (uint32_t i = 0; i < variable.member_count; i++) { + ss << ToStringSpvBuiltIn(variable.members[i].built_in); + if (i < (variable.member_count - 1)) { + ss << ", "; + } + } + ss << "]"; + } else { + if (preface) { + ss << "(built-in) "; + } + ss << ToStringSpvBuiltIn(variable.built_in); + } + return ss.str(); +} + +std::string ToStringSpvImageFormat(SpvImageFormat fmt) { + switch (fmt) { + case SpvImageFormatUnknown: + return "Unknown"; + case SpvImageFormatRgba32f: + return "Rgba32f"; + case SpvImageFormatRgba16f: + return "Rgba16f"; + case SpvImageFormatR32f: + return "R32f"; + case SpvImageFormatRgba8: + return "Rgba8"; + case SpvImageFormatRgba8Snorm: + return "Rgba8Snorm"; + case SpvImageFormatRg32f: + return "Rg32f"; + case SpvImageFormatRg16f: + return "Rg16f"; + case SpvImageFormatR11fG11fB10f: + return "R11fG11fB10f"; + case SpvImageFormatR16f: + return "R16f"; + case SpvImageFormatRgba16: + return "Rgba16"; + case SpvImageFormatRgb10A2: + return "Rgb10A2"; + case SpvImageFormatRg16: + return "Rg16"; + case SpvImageFormatRg8: + return "Rg8"; + case SpvImageFormatR16: + return "R16"; + case SpvImageFormatR8: + return "R8"; + case SpvImageFormatRgba16Snorm: + return "Rgba16Snorm"; + case SpvImageFormatRg16Snorm: + return "Rg16Snorm"; + case SpvImageFormatRg8Snorm: + return "Rg8Snorm"; + case SpvImageFormatR16Snorm: + return "R16Snorm"; + case SpvImageFormatR8Snorm: + return "R8Snorm"; + case SpvImageFormatRgba32i: + return "Rgba32i"; + case SpvImageFormatRgba16i: + return "Rgba16i"; + case SpvImageFormatRgba8i: + return "Rgba8i"; + case SpvImageFormatR32i: + return "R32i"; + case SpvImageFormatRg32i: + return "Rg32i"; + case SpvImageFormatRg16i: + return "Rg16i"; + case SpvImageFormatRg8i: + return "Rg8i"; + case SpvImageFormatR16i: + return "R16i"; + case SpvImageFormatR8i: + return "R8i"; + case SpvImageFormatRgba32ui: + return "Rgba32ui"; + case SpvImageFormatRgba16ui: + return "Rgba16ui"; + case SpvImageFormatRgba8ui: + return "Rgba8ui"; + case SpvImageFormatR32ui: + return "R32ui"; + case SpvImageFormatRgb10a2ui: + return "Rgb10a2ui"; + case SpvImageFormatRg32ui: + return "Rg32ui"; + case SpvImageFormatRg16ui: + return "Rg16ui"; + case SpvImageFormatRg8ui: + return "Rg8ui"; + case SpvImageFormatR16ui: + return "R16ui"; + case SpvImageFormatR8ui: + return "R8ui"; + case SpvImageFormatR64ui: + return "R64ui"; + case SpvImageFormatR64i: + return "R64i"; + + case SpvImageFormatMax: + break; + } + // unhandled SpvImageFormat enum value + return "???"; +} + +std::string ToStringUserType(SpvReflectUserType user_type) { + switch (user_type) { + case SPV_REFLECT_USER_TYPE_CBUFFER: + return "cbuffer"; + case SPV_REFLECT_USER_TYPE_TBUFFER: + return "tbuffer"; + case SPV_REFLECT_USER_TYPE_APPEND_STRUCTURED_BUFFER: + return "AppendStructuredBuffer"; + case SPV_REFLECT_USER_TYPE_BUFFER: + return "Buffer"; + case SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER: + return "ByteAddressBuffer"; + case SPV_REFLECT_USER_TYPE_CONSTANT_BUFFER: + return "ConstantBuffer"; + case SPV_REFLECT_USER_TYPE_CONSUME_STRUCTURED_BUFFER: + return "ConsumeStructuredBuffer"; + case SPV_REFLECT_USER_TYPE_INPUT_PATCH: + return "InputPatch"; + case SPV_REFLECT_USER_TYPE_OUTPUT_PATCH: + return "OutputPatch"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BUFFER: + return "RasterizerOrderedBuffer"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BYTE_ADDRESS_BUFFER: + return "RasterizerOrderedByteAddressBuffer"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_STRUCTURED_BUFFER: + return "RasterizerOrderedStructuredBuffer"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D: + return "RasterizerOrderedTexture1D"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D_ARRAY: + return "RasterizerOrderedTexture1DArray"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D: + return "RasterizerOrderedTexture2D"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D_ARRAY: + return "RasterizerOrderedTexture2DArray"; + case SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_3D: + return "RasterizerOrderedTexture3D"; + case SPV_REFLECT_USER_TYPE_RAYTRACING_ACCELERATION_STRUCTURE: + return "RaytracingAccelerationStructure"; + case SPV_REFLECT_USER_TYPE_RW_BUFFER: + return "RWBuffer"; + case SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER: + return "RWByteAddressBuffer"; + case SPV_REFLECT_USER_TYPE_RW_STRUCTURED_BUFFER: + return "RWStructuredBuffer"; + case SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D: + return "RWTexture1D"; + case SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D_ARRAY: + return "RWTexture1DArray"; + case SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D: + return "RWTexture2D"; + case SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D_ARRAY: + return "RWTexture2DArray"; + case SPV_REFLECT_USER_TYPE_RW_TEXTURE_3D: + return "RWTexture3D"; + case SPV_REFLECT_USER_TYPE_STRUCTURED_BUFFER: + return "StructuredBuffer"; + case SPV_REFLECT_USER_TYPE_SUBPASS_INPUT: + return "SubpassInput"; + case SPV_REFLECT_USER_TYPE_SUBPASS_INPUT_MS: + return "SubpassInputMS"; + case SPV_REFLECT_USER_TYPE_TEXTURE_1D: + return "Texture1D"; + case SPV_REFLECT_USER_TYPE_TEXTURE_1D_ARRAY: + return "Texture1DArray"; + case SPV_REFLECT_USER_TYPE_TEXTURE_2D: + return "Texture2D"; + case SPV_REFLECT_USER_TYPE_TEXTURE_2D_ARRAY: + return "Texture2DArray"; + case SPV_REFLECT_USER_TYPE_TEXTURE_2DMS: + return "Texture2DMS"; + case SPV_REFLECT_USER_TYPE_TEXTURE_2DMS_ARRAY: + return "Texture2DMSArray"; + case SPV_REFLECT_USER_TYPE_TEXTURE_3D: + return "Texture3D"; + case SPV_REFLECT_USER_TYPE_TEXTURE_BUFFER: + return "TextureBuffer"; + case SPV_REFLECT_USER_TYPE_TEXTURE_CUBE: + return "TextureCube"; + case SPV_REFLECT_USER_TYPE_TEXTURE_CUBE_ARRAY: + return "TextureCubeArray"; + default: + return "???"; + } +} + +std::string ToStringTypeFlags(SpvReflectTypeFlags type_flags) { + if (type_flags == SPV_REFLECT_TYPE_FLAG_UNDEFINED) { + return "UNDEFINED"; + } + +#define PRINT_AND_CLEAR_TYPE_FLAG(stream, flags, bit) \ + if (((flags) & (SPV_REFLECT_TYPE_FLAG_##bit)) == (SPV_REFLECT_TYPE_FLAG_##bit)) { \ + stream << #bit << " "; \ + flags ^= SPV_REFLECT_TYPE_FLAG_##bit; \ + } + std::stringstream sstream; + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, ARRAY); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, STRUCT); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, REF); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, EXTERNAL_MASK); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, EXTERNAL_BLOCK); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, EXTERNAL_SAMPLED_IMAGE); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, EXTERNAL_SAMPLER); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, EXTERNAL_IMAGE); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, MATRIX); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, VECTOR); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, FLOAT); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, INT); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, BOOL); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, type_flags, VOID); +#undef PRINT_AND_CLEAR_TYPE_FLAG + if (type_flags != 0) { + // Unhandled SpvReflectTypeFlags bit + sstream << "???"; + } + return sstream.str(); +} + +std::string ToStringVariableFlags(SpvReflectVariableFlags var_flags) { + if (var_flags == SPV_REFLECT_VARIABLE_FLAGS_NONE) { + return "NONE"; + } + +#define PRINT_AND_CLEAR_TYPE_FLAG(stream, flags, bit) \ + if (((flags) & (SPV_REFLECT_VARIABLE_FLAGS_##bit)) == (SPV_REFLECT_VARIABLE_FLAGS_##bit)) { \ + stream << #bit << " "; \ + flags ^= SPV_REFLECT_VARIABLE_FLAGS_##bit; \ + } + std::stringstream sstream; + PRINT_AND_CLEAR_TYPE_FLAG(sstream, var_flags, UNUSED); + PRINT_AND_CLEAR_TYPE_FLAG(sstream, var_flags, PHYSICAL_POINTER_COPY); +#undef PRINT_AND_CLEAR_TYPE_FLAG + if (var_flags != 0) { + // Unhandled SpvReflectVariableFlags bit + sstream << "???"; + } + return sstream.str(); +} + +std::string ToStringDecorationFlags(SpvReflectDecorationFlags decoration_flags) { + if (decoration_flags == SPV_REFLECT_DECORATION_NONE) { + return "NONE"; + } + +#define PRINT_AND_CLEAR_DECORATION_FLAG(stream, flags, bit) \ + if (((flags) & (SPV_REFLECT_DECORATION_##bit)) == (SPV_REFLECT_DECORATION_##bit)) { \ + stream << #bit << " "; \ + flags ^= SPV_REFLECT_DECORATION_##bit; \ + } + std::stringstream sstream; + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, NON_WRITABLE); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, NON_READABLE); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, FLAT); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, NOPERSPECTIVE); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, BUILT_IN); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, COLUMN_MAJOR); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, ROW_MAJOR); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, BUFFER_BLOCK); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, BLOCK); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, PATCH); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, PER_VERTEX); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, PER_TASK); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, WEIGHT_TEXTURE); + PRINT_AND_CLEAR_DECORATION_FLAG(sstream, decoration_flags, BLOCK_MATCH_TEXTURE); +#undef PRINT_AND_CLEAR_DECORATION_FLAG + if (decoration_flags != 0) { + // Unhandled SpvReflectDecorationFlags bit + sstream << "???"; + } + return sstream.str(); +} + +std::string ToStringFormat(SpvReflectFormat fmt) { + switch (fmt) { + case SPV_REFLECT_FORMAT_UNDEFINED: + return "VK_FORMAT_UNDEFINED"; + case SPV_REFLECT_FORMAT_R16_UINT: + return "VK_FORMAT_R16_UINT"; + case SPV_REFLECT_FORMAT_R16_SINT: + return "VK_FORMAT_R16_SINT"; + case SPV_REFLECT_FORMAT_R16_SFLOAT: + return "VK_FORMAT_R16_SFLOAT"; + case SPV_REFLECT_FORMAT_R16G16_UINT: + return "VK_FORMAT_R16G16_UINT"; + case SPV_REFLECT_FORMAT_R16G16_SINT: + return "VK_FORMAT_R16G16_SINT"; + case SPV_REFLECT_FORMAT_R16G16_SFLOAT: + return "VK_FORMAT_R16G16_SFLOAT"; + case SPV_REFLECT_FORMAT_R16G16B16_UINT: + return "VK_FORMAT_R16G16B16_UINT"; + case SPV_REFLECT_FORMAT_R16G16B16_SINT: + return "VK_FORMAT_R16G16B16_SINT"; + case SPV_REFLECT_FORMAT_R16G16B16_SFLOAT: + return "VK_FORMAT_R16G16B16_SFLOAT"; + case SPV_REFLECT_FORMAT_R16G16B16A16_UINT: + return "VK_FORMAT_R16G16B16A16_UINT"; + case SPV_REFLECT_FORMAT_R16G16B16A16_SINT: + return "VK_FORMAT_R16G16B16A16_SINT"; + case SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT: + return "VK_FORMAT_R16G16B16A16_SFLOAT"; + case SPV_REFLECT_FORMAT_R32_UINT: + return "VK_FORMAT_R32_UINT"; + case SPV_REFLECT_FORMAT_R32_SINT: + return "VK_FORMAT_R32_SINT"; + case SPV_REFLECT_FORMAT_R32_SFLOAT: + return "VK_FORMAT_R32_SFLOAT"; + case SPV_REFLECT_FORMAT_R32G32_UINT: + return "VK_FORMAT_R32G32_UINT"; + case SPV_REFLECT_FORMAT_R32G32_SINT: + return "VK_FORMAT_R32G32_SINT"; + case SPV_REFLECT_FORMAT_R32G32_SFLOAT: + return "VK_FORMAT_R32G32_SFLOAT"; + case SPV_REFLECT_FORMAT_R32G32B32_UINT: + return "VK_FORMAT_R32G32B32_UINT"; + case SPV_REFLECT_FORMAT_R32G32B32_SINT: + return "VK_FORMAT_R32G32B32_SINT"; + case SPV_REFLECT_FORMAT_R32G32B32_SFLOAT: + return "VK_FORMAT_R32G32B32_SFLOAT"; + case SPV_REFLECT_FORMAT_R32G32B32A32_UINT: + return "VK_FORMAT_R32G32B32A32_UINT"; + case SPV_REFLECT_FORMAT_R32G32B32A32_SINT: + return "VK_FORMAT_R32G32B32A32_SINT"; + case SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT: + return "VK_FORMAT_R32G32B32A32_SFLOAT"; + case SPV_REFLECT_FORMAT_R64_UINT: + return "VK_FORMAT_R64_UINT"; + case SPV_REFLECT_FORMAT_R64_SINT: + return "VK_FORMAT_R64_SINT"; + case SPV_REFLECT_FORMAT_R64_SFLOAT: + return "VK_FORMAT_R64_SFLOAT"; + case SPV_REFLECT_FORMAT_R64G64_UINT: + return "VK_FORMAT_R64G64_UINT"; + case SPV_REFLECT_FORMAT_R64G64_SINT: + return "VK_FORMAT_R64G64_SINT"; + case SPV_REFLECT_FORMAT_R64G64_SFLOAT: + return "VK_FORMAT_R64G64_SFLOAT"; + case SPV_REFLECT_FORMAT_R64G64B64_UINT: + return "VK_FORMAT_R64G64B64_UINT"; + case SPV_REFLECT_FORMAT_R64G64B64_SINT: + return "VK_FORMAT_R64G64B64_SINT"; + case SPV_REFLECT_FORMAT_R64G64B64_SFLOAT: + return "VK_FORMAT_R64G64B64_SFLOAT"; + case SPV_REFLECT_FORMAT_R64G64B64A64_UINT: + return "VK_FORMAT_R64G64B64A64_UINT"; + case SPV_REFLECT_FORMAT_R64G64B64A64_SINT: + return "VK_FORMAT_R64G64B64A64_SINT"; + case SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT: + return "VK_FORMAT_R64G64B64A64_SFLOAT"; + } + // unhandled SpvReflectFormat enum value + return "VK_FORMAT_???"; +} + +static std::string ToStringScalarType(const SpvReflectTypeDescription& type) { + switch (type.op) { + case SpvOpTypeVoid: { + return "void"; + break; + } + case SpvOpTypeBool: { + return "bool"; + break; + } + case SpvOpTypeInt: { + if (type.traits.numeric.scalar.signedness) + return "int"; + else + return "uint"; + } + case SpvOpTypeFloat: { + switch (type.traits.numeric.scalar.width) { + case 32: + return "float"; + case 64: + return "double"; + default: + break; + } + break; + } + case SpvOpTypeStruct: { + return "struct"; + } + case SpvOpTypePointer: { + return "ptr"; + } + default: { + break; + } + } + return ""; +} + +static std::string ToStringGlslType(const SpvReflectTypeDescription& type) { + switch (type.op) { + case SpvOpTypeVector: { + switch (type.traits.numeric.scalar.width) { + case 32: { + switch (type.traits.numeric.vector.component_count) { + case 2: + return "vec2"; + case 3: + return "vec3"; + case 4: + return "vec4"; + } + } break; + + case 64: { + switch (type.traits.numeric.vector.component_count) { + case 2: + return "dvec2"; + case 3: + return "dvec3"; + case 4: + return "dvec4"; + } + } break; + } + } break; + default: + break; + } + return ToStringScalarType(type); +} + +static std::string ToStringHlslType(const SpvReflectTypeDescription& type) { + switch (type.op) { + case SpvOpTypeVector: { + switch (type.traits.numeric.scalar.width) { + case 32: { + switch (type.traits.numeric.vector.component_count) { + case 2: + return "float2"; + case 3: + return "float3"; + case 4: + return "float4"; + } + } break; + + case 64: { + switch (type.traits.numeric.vector.component_count) { + case 2: + return "double2"; + case 3: + return "double3"; + case 4: + return "double4"; + } + } break; + } + } break; + + default: + break; + } + return ToStringScalarType(type); +} + +std::string ToStringType(SpvSourceLanguage src_lang, const SpvReflectTypeDescription& type) { + if (src_lang == SpvSourceLanguageHLSL) { + return ToStringHlslType(type); + } + + return ToStringGlslType(type); +} + +std::string ToStringComponentType(const SpvReflectTypeDescription& type, uint32_t member_decoration_flags) { + uint32_t masked_type = type.type_flags & 0xF; + if (masked_type == 0) { + return ""; + } + + std::stringstream ss; + + if (type.type_flags & SPV_REFLECT_TYPE_FLAG_MATRIX) { + if (member_decoration_flags & SPV_REFLECT_DECORATION_COLUMN_MAJOR) { + ss << "column_major" + << " "; + } else if (member_decoration_flags & SPV_REFLECT_DECORATION_ROW_MAJOR) { + ss << "row_major" + << " "; + } + } + + switch (masked_type) { + default: + assert(false && "unsupported component type"); + break; + case SPV_REFLECT_TYPE_FLAG_BOOL: + ss << "bool"; + break; + case SPV_REFLECT_TYPE_FLAG_INT: + ss << (type.traits.numeric.scalar.signedness ? "int" : "uint"); + break; + case SPV_REFLECT_TYPE_FLAG_FLOAT: + ss << "float"; + break; + } + + if (type.type_flags & SPV_REFLECT_TYPE_FLAG_MATRIX) { + ss << type.traits.numeric.matrix.row_count; + ss << "x"; + ss << type.traits.numeric.matrix.column_count; + } else if (type.type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR) { + ss << type.traits.numeric.vector.component_count; + } + + if (type.type_flags & SPV_REFLECT_TYPE_FLAG_REF) { + ss << "*"; + } + + return ss.str(); +} + +void ParseBlockMembersToTextLines(const char* indent, int indent_depth, bool flatten_cbuffers, const std::string& parent_name, + uint32_t member_count, const SpvReflectBlockVariable* p_members, + std::vector* p_text_lines, std::unordered_set& physical_pointer_spirv_id) { + const char* t = indent; + for (uint32_t member_index = 0; member_index < member_count; ++member_index) { + indent_depth = flatten_cbuffers ? 2 : indent_depth; + std::stringstream ss_indent; + for (int indent_count = 0; indent_count < indent_depth; ++indent_count) { + ss_indent << t; + } + std::string expanded_indent = ss_indent.str(); + + const auto& member = p_members[member_index]; + if (!member.type_description) { + // TODO 212 - If a buffer ref has an array of itself, all members are null + continue; + } + + bool is_struct = ((member.type_description->type_flags & static_cast(SPV_REFLECT_TYPE_FLAG_STRUCT)) != 0); + bool is_ref = ((member.type_description->type_flags & static_cast(SPV_REFLECT_TYPE_FLAG_REF)) != 0); + bool is_array = ((member.type_description->type_flags & static_cast(SPV_REFLECT_TYPE_FLAG_ARRAY)) != 0); + if (is_struct) { + const std::string name = (member.name == nullptr ? "" : member.name); + + // Begin struct + TextLine tl = {}; + tl.indent = expanded_indent; + tl.type_name = (member.type_description->type_name == nullptr ? "" : member.type_description->type_name); + tl.absolute_offset = member.absolute_offset; + tl.relative_offset = member.offset; + tl.size = member.size; + tl.padded_size = member.padded_size; + tl.array_stride = member.array.stride; + tl.block_variable_flags = member.flags; + tl.text_line_flags = is_ref ? TEXT_LINE_TYPE_REF_BEGIN : TEXT_LINE_TYPE_STRUCT_BEGIN; + if (!flatten_cbuffers) { + p_text_lines->push_back(tl); + } + + const bool array_of_structs = is_array && member.type_description->struct_type_description; + const uint32_t struct_id = + array_of_structs ? member.type_description->struct_type_description->id : member.type_description->id; + + if (physical_pointer_spirv_id.count(struct_id) == 0) { + physical_pointer_spirv_id.insert(member.type_description->id); + if (array_of_structs) { + physical_pointer_spirv_id.insert(member.type_description->struct_type_description->id); + } + + // Members + tl = {}; + std::string current_parent_name; + if (flatten_cbuffers) { + current_parent_name = parent_name.empty() ? name : (parent_name + "." + name); + } + std::vector* p_target_text_line = flatten_cbuffers ? p_text_lines : &tl.lines; + ParseBlockMembersToTextLines(t, indent_depth + 1, flatten_cbuffers, current_parent_name, member.member_count, + member.members, p_target_text_line, physical_pointer_spirv_id); + tl.text_line_flags = TEXT_LINE_TYPE_LINES; + p_text_lines->push_back(tl); + } + physical_pointer_spirv_id.erase(member.type_description->id); + + // End struct + tl = {}; + tl.indent = expanded_indent; + tl.name = name; + if ((member.array.dims_count > 0) || (member.type_description->traits.array.dims[0] > 0)) { + const SpvReflectArrayTraits* p_array_info = (member.array.dims_count > 0) ? &member.array : nullptr; + if (p_array_info == nullptr) { + // + // glslang based compilers stores array information in the type and + // not the variable + // + p_array_info = (member.type_description->traits.array.dims[0] > 0) ? &member.type_description->traits.array : nullptr; + } + if (p_array_info != nullptr) { + std::stringstream ss_array; + for (uint32_t array_dim_index = 0; array_dim_index < p_array_info->dims_count; ++array_dim_index) { + uint32_t dim = p_array_info->dims[array_dim_index]; + // + // dim = 0 means it's an unbounded array + // + if (dim > 0) { + ss_array << "[" << dim << "]"; + } else { + ss_array << "[]"; + } + } + tl.name += ss_array.str(); + } + } + tl.absolute_offset = member.absolute_offset; + tl.relative_offset = member.offset; + tl.size = member.size; + tl.padded_size = member.padded_size; + tl.array_stride = member.array.stride; + tl.block_variable_flags = member.flags; + tl.text_line_flags = is_ref ? TEXT_LINE_TYPE_REF_END : TEXT_LINE_TYPE_STRUCT_END; + if (!flatten_cbuffers) { + p_text_lines->push_back(tl); + } + } else { + std::string name = (member.name == nullptr ? "" : member.name); + if (flatten_cbuffers) { + if (!parent_name.empty()) { + name = parent_name + "." + name; + } + } + + TextLine tl = {}; + tl.indent = expanded_indent; + tl.type_name = ToStringComponentType(*member.type_description, member.decoration_flags); + tl.name = name; + if (member.array.dims_count > 0) { + std::stringstream ss_array; + for (uint32_t array_dim_index = 0; array_dim_index < member.array.dims_count; ++array_dim_index) { + uint32_t dim = member.array.dims[array_dim_index]; + ss_array << "[" << dim << "]"; + } + tl.name += ss_array.str(); + } + tl.absolute_offset = member.absolute_offset; + tl.relative_offset = member.offset; + tl.size = member.size; + tl.padded_size = member.padded_size; + tl.array_stride = member.array.stride; + tl.block_variable_flags = member.flags; + p_text_lines->push_back(tl); + } + } +} + +void ParseBlockVariableToTextLines(const char* indent, bool flatten_cbuffers, const SpvReflectBlockVariable& block_var, + std::vector* p_text_lines) { + // Begin block + TextLine tl = {}; + tl.indent = indent; + tl.type_name = (block_var.type_description->type_name != nullptr) ? block_var.type_description->type_name : ""; + tl.size = block_var.size; + tl.padded_size = block_var.padded_size; + tl.text_line_flags = TEXT_LINE_TYPE_BLOCK_BEGIN; + p_text_lines->push_back(tl); + + // Members + tl = {}; + std::unordered_set physical_pointer_spirv_id; + ParseBlockMembersToTextLines(indent, 2, flatten_cbuffers, "", block_var.member_count, block_var.members, &tl.lines, + physical_pointer_spirv_id); + tl.text_line_flags = TEXT_LINE_TYPE_LINES; + p_text_lines->push_back(tl); + + // End block + tl = {}; + tl.indent = indent; + tl.name = (block_var.name != nullptr) ? block_var.name : ""; + tl.absolute_offset = 0; + tl.relative_offset = 0; + tl.size = block_var.size; + tl.padded_size = block_var.padded_size; + tl.text_line_flags = TEXT_LINE_TYPE_BLOCK_END; + p_text_lines->push_back(tl); +} + +void FormatTextLines(const std::vector& text_lines, const char* indent, std::vector* p_formatted_lines) { + size_t modifier_width = 0; + size_t type_name_width = 0; + size_t name_width = 0; + + // Widths + for (auto& tl : text_lines) { + if (tl.text_line_flags != 0) { + continue; + } + modifier_width = std::max(modifier_width, tl.modifier.length()); + type_name_width = std::max(type_name_width, tl.type_name.length()); + name_width = std::max(name_width, tl.name.length()); + } + + // Output + size_t n = text_lines.size(); + for (size_t i = 0; i < n; ++i) { + auto& tl = text_lines[i]; + + std::stringstream ss; + if ((tl.text_line_flags == TEXT_LINE_TYPE_BLOCK_BEGIN) || (tl.text_line_flags == TEXT_LINE_TYPE_STRUCT_BEGIN) || + (tl.text_line_flags == TEXT_LINE_TYPE_REF_BEGIN)) { + ss << indent; + ss << tl.indent; + if (tl.text_line_flags == TEXT_LINE_TYPE_REF_BEGIN) ss << "ref "; + ss << "struct "; + ss << tl.type_name; + ss << " {"; + } else if ((tl.text_line_flags == TEXT_LINE_TYPE_BLOCK_END) || (tl.text_line_flags == TEXT_LINE_TYPE_STRUCT_END) || + (tl.text_line_flags == TEXT_LINE_TYPE_REF_END)) { + ss << indent; + ss << tl.indent; + ss << "} "; + ss << tl.name; + ss << ";"; + } else if (tl.text_line_flags == TEXT_LINE_TYPE_LINES) { + FormatTextLines(tl.lines, indent, p_formatted_lines); + } else { + ss << indent; + ss << tl.indent; + if (modifier_width > 0) { + ss << std::setw(modifier_width) << std::left << tl.modifier; + ss << " "; + } + ss << std::setw(type_name_width) << std::left << tl.type_name; + ss << " "; + ss << std::setw(name_width) << (tl.name + ";"); + } + + // Reuse the various strings to store the formatted texts + TextLine out_tl = {}; + out_tl.formatted_line = ss.str(); + if (out_tl.formatted_line.length() > 0) { + out_tl.array_stride = tl.array_stride; + out_tl.text_line_flags = tl.text_line_flags; + out_tl.formatted_absolute_offset = std::to_string(tl.absolute_offset); + out_tl.formatted_relative_offset = std::to_string(tl.relative_offset); + out_tl.formatted_size = std::to_string(tl.size); + out_tl.formatted_padded_size = std::to_string(tl.padded_size); + out_tl.formatted_array_stride = std::to_string(tl.array_stride); + // Block variable flags + if (tl.block_variable_flags != 0) { + std::stringstream ss_flags; + if (tl.block_variable_flags & SPV_REFLECT_VARIABLE_FLAGS_UNUSED) { + ss_flags << "UNUSED"; + } + out_tl.formatted_block_variable_flags = ss_flags.str(); + } + p_formatted_lines->push_back(out_tl); + } + } +} + +void StreamWriteTextLines(std::ostream& os, const char* indent, bool flatten_cbuffers, const std::vector& text_lines) { + std::vector formatted_lines; + FormatTextLines(text_lines, indent, &formatted_lines); + + size_t line_width = 0; + size_t offset_width = 0; + size_t absolute_offset_width = 0; + size_t size_width = 0; + size_t padded_size_width = 0; + size_t array_stride_width = 0; + + // Width + for (auto& tl : formatted_lines) { + if (tl.text_line_flags != 0) { + continue; + } + line_width = std::max(line_width, tl.formatted_line.length()); + absolute_offset_width = std::max(absolute_offset_width, tl.formatted_absolute_offset.length()); + offset_width = std::max(offset_width, tl.formatted_relative_offset.length()); + size_width = std::max(size_width, tl.formatted_size.length()); + padded_size_width = std::max(padded_size_width, tl.formatted_padded_size.length()); + array_stride_width = std::max(array_stride_width, tl.formatted_array_stride.length()); + } + + size_t n = formatted_lines.size(); + for (size_t i = 0; i < n; ++i) { + auto& tl = formatted_lines[i]; + + if (tl.text_line_flags == TEXT_LINE_TYPE_BLOCK_BEGIN) { + if (i > 0) { + os << "\n"; + } + + size_t pos = tl.formatted_line.find_first_not_of(' '); + if (pos != std::string::npos) { + std::string s(pos, ' '); + os << s << "//" + << " "; + os << "size = " << tl.formatted_size << ", "; + os << "padded size = " << tl.formatted_padded_size; + os << "\n"; + } + + os << std::setw(line_width) << std::left << tl.formatted_line; + } else if (tl.text_line_flags == TEXT_LINE_TYPE_BLOCK_END) { + os << std::setw(line_width) << std::left << tl.formatted_line; + if (i < (n - 1)) { + os << "\n"; + } + } else if (tl.text_line_flags == TEXT_LINE_TYPE_STRUCT_BEGIN || tl.text_line_flags == TEXT_LINE_TYPE_REF_BEGIN) { + if (!flatten_cbuffers) { + if (i > 0) { + os << "\n"; + } + + size_t pos = tl.formatted_line.find_first_not_of(' '); + if (pos != std::string::npos) { + std::string s(pos, ' '); + os << s << "//" + << " "; + os << "abs offset = " << tl.formatted_absolute_offset << ", "; + os << "rel offset = " << tl.formatted_relative_offset << ", "; + os << "size = " << tl.formatted_size << ", "; + os << "padded size = " << tl.formatted_padded_size; + if (tl.array_stride > 0) { + os << ", "; + os << "array stride = " << tl.formatted_array_stride; + } + if (!tl.formatted_block_variable_flags.empty()) { + os << " "; + os << tl.formatted_block_variable_flags; + } + os << "\n"; + } + + os << std::setw(line_width) << std::left << tl.formatted_line; + } + } else if (tl.text_line_flags == TEXT_LINE_TYPE_STRUCT_END || tl.text_line_flags == TEXT_LINE_TYPE_REF_END) { + if (!flatten_cbuffers) { + os << std::setw(line_width) << std::left << tl.formatted_line; + if (i < (n - 1)) { + os << "\n"; + } + } + } else { + os << std::setw(line_width) << std::left << tl.formatted_line; + os << " " + << "//" + << " "; + os << "abs offset = " << std::setw(absolute_offset_width) << std::right << tl.formatted_absolute_offset << ", "; + if (!flatten_cbuffers) { + os << "rel offset = " << std::setw(offset_width) << std::right << tl.formatted_relative_offset << ", "; + } + os << "size = " << std::setw(size_width) << std::right << tl.formatted_size << ", "; + os << "padded size = " << std::setw(padded_size_width) << std::right << tl.formatted_padded_size; + if (tl.array_stride > 0) { + os << ", "; + os << "array stride = " << std::setw(array_stride_width) << tl.formatted_array_stride; + } + if (!tl.formatted_block_variable_flags.empty()) { + os << " "; + os << tl.formatted_block_variable_flags; + } + } + + if (i < (n - 1)) { + os << "\n"; + } + } +} + +void StreamWritePushConstantsBlock(std::ostream& os, const SpvReflectBlockVariable& obj, bool flatten_cbuffers, + const char* indent) { + const char* t = indent; + os << t << "spirv id : " << obj.spirv_id << "\n"; + + os << t << "name : " << ((obj.name != nullptr) ? obj.name : ""); + if ((obj.type_description->type_name != nullptr) && (strlen(obj.type_description->type_name) > 0)) { + os << " " + << "(" << obj.type_description->type_name << ")"; + } + + std::vector text_lines; + ParseBlockVariableToTextLines(" ", flatten_cbuffers, obj, &text_lines); + if (!text_lines.empty()) { + os << "\n"; + StreamWriteTextLines(os, t, flatten_cbuffers, text_lines); + os << "\n"; + } +} + +void StreamWriteDescriptorBinding(std::ostream& os, const SpvReflectDescriptorBinding& obj, bool write_set, bool flatten_cbuffers, + const char* indent) { + const char* t = indent; + os << t << "spirv id : " << obj.spirv_id << "\n"; + if (write_set) { + os << t << "set : " << obj.set << "\n"; + } + os << t << "binding : " << obj.binding << "\n"; + os << t << "type : " << ToStringDescriptorType(obj.descriptor_type); + os << " " + << "(" << ToStringResourceType(obj.resource_type) << ")" + << "\n"; + + // count + os << t << "count : " << obj.count << "\n"; + + // array + if (obj.array.dims_count > 0) { + os << t << "array : "; + for (uint32_t dim_index = 0; dim_index < obj.array.dims_count; ++dim_index) { + os << "[" << obj.array.dims[dim_index] << "]"; + } + os << "\n"; + } + + // counter + if (obj.uav_counter_binding != nullptr) { + os << t << "counter : "; + os << "("; + os << "set=" << obj.uav_counter_binding->set << ", "; + os << "binding=" << obj.uav_counter_binding->binding << ", "; + os << "name=" << obj.uav_counter_binding->name; + os << ");"; + os << "\n"; + } + + // accessed + os << t << "accessed : " << (obj.accessed ? "true" : "false") << "\n"; + + os << t << "name : " << ((obj.name != nullptr) ? obj.name : ""); + if ((obj.type_description->type_name != nullptr) && (strlen(obj.type_description->type_name) > 0)) { + os << " " + << "(" << obj.type_description->type_name << ")"; + } + + if (obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER || + obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + std::vector text_lines; + ParseBlockVariableToTextLines(" ", flatten_cbuffers, obj.block, &text_lines); + if (!text_lines.empty()) { + os << "\n"; + StreamWriteTextLines(os, t, flatten_cbuffers, text_lines); + os << "\n"; + } + } +} + +void StreamWriteInterfaceVariable(std::ostream& os, const SpvReflectInterfaceVariable& obj, const char* indent) { + const char* t = indent; + os << t << "spirv id : " << obj.spirv_id << "\n"; + os << t << "location : "; + if (obj.decoration_flags & SPV_REFLECT_DECORATION_BUILT_IN) { + os << ToStringSpvBuiltIn(obj, true); + } else { + os << obj.location; + } + os << "\n"; + os << t << "type : " << ToStringComponentType(*obj.type_description, 0) << "\n"; + + // array + if (obj.array.dims_count > 0) { + os << t << "array : "; + for (uint32_t dim_index = 0; dim_index < obj.array.dims_count; ++dim_index) { + os << "[" << obj.array.dims[dim_index] << "]"; + } + os << "\n"; + } + + os << t << "semantic : " << (obj.semantic != NULL ? obj.semantic : "") << "\n"; + os << t << "name : " << (obj.name != NULL ? obj.name : ""); + if ((obj.type_description->type_name != nullptr) && (strlen(obj.type_description->type_name) > 0)) { + os << " " + << "(" << obj.type_description->type_name << ")"; + } + os << "\n"; + os << t << "qualifier : "; + if (obj.decoration_flags & SPV_REFLECT_DECORATION_FLAT) { + os << "flat"; + } else if (obj.decoration_flags & SPV_REFLECT_DECORATION_NOPERSPECTIVE) { + os << "noperspective"; + } +} + +void StreamWriteEntryPoint(std::ostream& os, const SpvReflectEntryPoint& obj, const char* indent) { + os << indent << "entry point : " << obj.name; + os << " (stage=" << ToStringShaderStage(obj.shader_stage) << ")"; + if (obj.shader_stage == SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT) { + os << "\n"; + os << "local size : " + << "(" << (obj.local_size.x == (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT ? "Spec Constant" : std::to_string(obj.local_size.x)) + << ", " + << (obj.local_size.y == (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT ? "Spec Constant" : std::to_string(obj.local_size.y)) + << ", " + << (obj.local_size.z == (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT ? "Spec Constant" : std::to_string(obj.local_size.z)) + << ")"; + } +} + +void StreamWriteShaderModule(std::ostream& os, const SpvReflectShaderModule& obj, const char* indent) { + (void)indent; + os << "generator : " << ToStringGenerator(obj.generator) << "\n"; + os << "source lang : " << spvReflectSourceLanguage(obj.source_language) << "\n"; + os << "source lang ver : " << obj.source_language_version << "\n"; + os << "source file : " << (obj.source_file != NULL ? obj.source_file : "") << "\n"; + // os << "shader stage : " << ToStringShaderStage(obj.shader_stage) << + // "\n"; + + for (uint32_t i = 0; i < obj.entry_point_count; ++i) { + StreamWriteEntryPoint(os, obj.entry_points[i], ""); + if (i < (obj.entry_point_count - 1)) { + os << "\n"; + } + } +} + +// Avoid unused variable warning/error on Linux +#ifndef NDEBUG +#define USE_ASSERT(x) assert(x) +#else +#define USE_ASSERT(x) ((void)(x)) +#endif + +void WriteReflection(const spv_reflect::ShaderModule& obj, bool flatten_cbuffers, std::ostream& os) { + const char* t = " "; + const char* tt = " "; + const char* ttt = " "; + + StreamWriteShaderModule(os, obj.GetShaderModule(), ""); + + uint32_t count = 0; + std::vector variables; + std::vector bindings; + std::vector sets; + std::vector push_constant_bocks; + + count = 0; + SpvReflectResult result = obj.EnumerateInputVariables(&count, nullptr); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + variables.resize(count); + result = obj.EnumerateInputVariables(&count, variables.data()); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + if (count > 0) { + os << "\n"; + os << "\n"; + os << "\n"; + os << t << "Input variables: " << count << "\n\n"; + for (size_t i = 0; i < variables.size(); ++i) { + auto p_var = variables[i]; + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + os << tt << i << ":" + << "\n"; + StreamWriteInterfaceVariable(os, *p_var, ttt); + if (i < (count - 1)) { + os << "\n"; + } + } + } + + count = 0; + result = obj.EnumerateOutputVariables(&count, nullptr); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + variables.resize(count); + result = obj.EnumerateOutputVariables(&count, variables.data()); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + if (count > 0) { + os << "\n"; + os << "\n"; + os << "\n"; + os << t << "Output variables: " << count << "\n\n"; + for (size_t i = 0; i < variables.size(); ++i) { + auto p_var = variables[i]; + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + os << tt << i << ":" + << "\n"; + StreamWriteInterfaceVariable(os, *p_var, ttt); + if (i < (count - 1)) { + os << "\n"; + } + } + } + + count = 0; + result = obj.EnumeratePushConstantBlocks(&count, nullptr); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + push_constant_bocks.resize(count); + result = obj.EnumeratePushConstantBlocks(&count, push_constant_bocks.data()); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + if (count > 0) { + os << "\n"; + os << "\n"; + os << "\n"; + os << t << "Push constant blocks: " << count << "\n\n"; + for (size_t i = 0; i < push_constant_bocks.size(); ++i) { + auto p_block = push_constant_bocks[i]; + os << tt << i << ":" + << "\n"; + StreamWritePushConstantsBlock(os, *p_block, flatten_cbuffers, ttt); + } + } + + count = 0; + result = obj.EnumerateDescriptorBindings(&count, nullptr); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + bindings.resize(count); + result = obj.EnumerateDescriptorBindings(&count, bindings.data()); + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + std::sort(std::begin(bindings), std::end(bindings), [](SpvReflectDescriptorBinding* a, SpvReflectDescriptorBinding* b) -> bool { + if (a->set != b->set) { + return a->set < b->set; + } + return a->binding < b->binding; + }); + if (count > 0) { + os << "\n"; + os << "\n"; + os << "\n"; + os << t << "Descriptor bindings: " << count << "\n\n"; + for (size_t i = 0; i < bindings.size(); ++i) { + auto p_binding = bindings[i]; + USE_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + os << tt << "Binding" + << " " << p_binding->set << "." << p_binding->binding << "" + << "\n"; + StreamWriteDescriptorBinding(os, *p_binding, true, flatten_cbuffers, ttt); + if (i < (count - 1)) { + os << "\n\n"; + } + } + } +} + +////////////////////////////////// + +SpvReflectToYaml::SpvReflectToYaml(const SpvReflectShaderModule& shader_module, uint32_t verbosity) + : sm_(shader_module), verbosity_(verbosity) {} + +void SpvReflectToYaml::WriteTypeDescription(std::ostream& os, const SpvReflectTypeDescription& td, uint32_t indent_level) { + // YAML anchors can only refer to points earlier in the doc, so child type + // descriptions must be processed before the parent. + if (!td.copied) { + for (uint32_t i = 0; i < td.member_count; ++i) { + WriteTypeDescription(os, td.members[i], indent_level); + } + } + const std::string t0 = Indent(indent_level); + const std::string t1 = Indent(indent_level + 1); + const std::string t2 = Indent(indent_level + 2); + const std::string t3 = Indent(indent_level + 3); + const std::string t4 = Indent(indent_level + 4); + + // Determine the index of this type within the shader module's list. + uint32_t type_description_index = static_cast(type_description_to_index_.size()); + type_description_to_index_[&td] = type_description_index; + + os << t0 << "- &td" << type_description_index << std::endl; + // typedef struct SpvReflectTypeDescription { + // uint32_t id; + os << t1 << "id: " << td.id << std::endl; + // SpvOp op; + os << t1 << "op: " << td.op << std::endl; + // const char* type_name; + os << t1 << "type_name: " << SafeString(td.type_name) << std::endl; + // const char* struct_member_name; + os << t1 << "struct_member_name: " << SafeString(td.struct_member_name) << std::endl; + // SpvStorageClass storage_class; + os << t1 << "storage_class: " << td.storage_class << " # " << ToStringSpvStorageClass(td.storage_class) << std::endl; + // SpvReflectTypeFlags type_flags; + os << t1 << "type_flags: " << AsHexString(td.type_flags) << " # " << ToStringTypeFlags(td.type_flags) << std::endl; + // SpvReflectDecorationFlags decoration_flags; + os << t1 << "decoration_flags: " << AsHexString(td.decoration_flags) << " # " << ToStringDecorationFlags(td.decoration_flags) + << std::endl; + // struct Traits { + os << t1 << "traits:" << std::endl; + // SpvReflectNumericTraits numeric; + // typedef struct SpvReflectNumericTraits { + os << t2 << "numeric:" << std::endl; + // struct Scalar { + // uint32_t width; + // uint32_t signedness; + // } scalar; + os << t3 << "scalar: { "; + os << "width: " << td.traits.numeric.scalar.width << ", "; + os << "signedness: " << td.traits.numeric.scalar.signedness; + os << " }" << std::endl; + // struct Vector { + // uint32_t component_count; + // } vector; + os << t3 << "vector: { "; + os << "component_count: " << td.traits.numeric.vector.component_count; + os << " }" << std::endl; + // struct Matrix { + // uint32_t column_count; + // uint32_t row_count; + // uint32_t stride; // Measured in bytes + // } matrix; + os << t3 << "matrix: { "; + os << "column_count: " << td.traits.numeric.matrix.column_count << ", "; + os << "row_count: " << td.traits.numeric.matrix.row_count << ", "; + ; + os << "stride: " << td.traits.numeric.matrix.stride; + os << " }" << std::endl; + // } SpvReflectNumericTraits; + + // SpvReflectImageTraits image; + os << t2 << "image: { "; + // typedef struct SpvReflectImageTraits { + // SpvDim dim; + os << "dim: " << td.traits.image.dim << ", "; + // uint32_t depth; + os << "depth: " << td.traits.image.depth << ", "; + // uint32_t arrayed; + os << "arrayed: " << td.traits.image.arrayed << ", "; + // uint32_t ms; + os << "ms: " << td.traits.image.ms << ", "; + // uint32_t sampled; + os << "sampled: " << td.traits.image.sampled << ", "; + // SpvImageFormat image_format; + os << "image_format: " << td.traits.image.image_format; + // } SpvReflectImageTraits; + os << " }" + << " # dim=" << ToStringSpvDim(td.traits.image.dim) << " image_format=" << ToStringSpvImageFormat(td.traits.image.image_format) + << std::endl; + + // SpvReflectArrayTraits array; + os << t2 << "array: { "; + // typedef struct SpvReflectArrayTraits { + // uint32_t dims_count; + os << "dims_count: " << td.traits.array.dims_count << ", "; + // uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; + os << "dims: ["; + for (uint32_t i_dim = 0; i_dim < td.traits.array.dims_count; ++i_dim) { + os << td.traits.array.dims[i_dim] << ","; + } + os << "], "; + // uint32_t stride; // Measured in bytes + os << "stride: " << td.traits.array.stride; + // } SpvReflectArrayTraits; + os << " }" << std::endl; + // } traits; + + // uint32_t member_count; + os << t1 << "member_count: " << td.member_count << std::endl; + // struct SpvReflectTypeDescription* members; + os << t1 << "members:" << std::endl; + if (td.copied) { + os << t1 << "- [forward pointer]" << std::endl; + } else { + for (uint32_t i_member = 0; i_member < td.member_count; ++i_member) { + os << t2 << "- *td" << type_description_to_index_[&(td.members[i_member])] << std::endl; + } + } + // } SpvReflectTypeDescription; +} + +void SpvReflectToYaml::WriteBlockVariable(std::ostream& os, const SpvReflectBlockVariable& bv, uint32_t indent_level) { + if ((bv.flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY)) { + return; // catches recursive buffer references + } + + for (uint32_t i = 0; i < bv.member_count; ++i) { + WriteBlockVariable(os, bv.members[i], indent_level); + } + + const std::string t0 = Indent(indent_level); + const std::string t1 = Indent(indent_level + 1); + const std::string t2 = Indent(indent_level + 2); + const std::string t3 = Indent(indent_level + 3); + + assert(block_variable_to_index_.find(&bv) == block_variable_to_index_.end()); + uint32_t block_variable_index = static_cast(block_variable_to_index_.size()); + block_variable_to_index_[&bv] = block_variable_index; + + os << t0 << "- &bv" << block_variable_index << std::endl; + // typedef struct SpvReflectBlockVariable { + // const char* name; + os << t1 << "name: " << SafeString(bv.name) << std::endl; + // uint32_t offset; // Measured in bytes + os << t1 << "offset: " << bv.offset << std::endl; + // uint32_t absolute_offset; // Measured in bytes + os << t1 << "absolute_offset: " << bv.absolute_offset << std::endl; + // uint32_t size; // Measured in bytes + os << t1 << "size: " << bv.size << std::endl; + // uint32_t padded_size; // Measured in bytes + os << t1 << "padded_size: " << bv.padded_size << std::endl; + // SpvReflectDecorationFlags decoration_flags; + os << t1 << "decorations: " << AsHexString(bv.decoration_flags) << " # " << ToStringDecorationFlags(bv.decoration_flags) + << std::endl; + // SpvReflectNumericTraits numeric; + // typedef struct SpvReflectNumericTraits { + os << t1 << "numeric:" << std::endl; + // struct Scalar { + // uint32_t width; + // uint32_t signedness; + // } scalar; + os << t2 << "scalar: { "; + os << "width: " << bv.numeric.scalar.width << ", "; + os << "signedness: " << bv.numeric.scalar.signedness << " }" << std::endl; + // struct Vector { + // uint32_t component_count; + // } vector; + os << t2 << "vector: { "; + os << "component_count: " << bv.numeric.vector.component_count << " }" << std::endl; + // struct Matrix { + // uint32_t column_count; + // uint32_t row_count; + // uint32_t stride; // Measured in bytes + // } matrix; + os << t2 << "matrix: { "; + os << "column_count: " << bv.numeric.matrix.column_count << ", "; + os << "row_count: " << bv.numeric.matrix.row_count << ", "; + os << "stride: " << bv.numeric.matrix.stride << " }" << std::endl; + // } SpvReflectNumericTraits; + + // SpvReflectArrayTraits array; + os << t1 << "array: { "; + // typedef struct SpvReflectArrayTraits { + // uint32_t dims_count; + os << "dims_count: " << bv.array.dims_count << ", "; + // uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; + os << "dims: ["; + for (uint32_t i_dim = 0; i_dim < bv.array.dims_count; ++i_dim) { + os << bv.array.dims[i_dim] << ","; + } + os << "], "; + // uint32_t stride; // Measured in bytes + os << "stride: " << bv.array.stride; + // } SpvReflectArrayTraits; + os << " }" << std::endl; + + // SpvReflectVariableFlags flags; + os << t1 << "flags: " << AsHexString(bv.flags) << " # " << ToStringVariableFlags(bv.flags) << std::endl; + + // uint32_t member_count; + os << t1 << "member_count: " << bv.member_count << std::endl; + // struct SpvReflectBlockVariable* members; + os << t1 << "members:" << std::endl; + for (uint32_t i = 0; i < bv.member_count; ++i) { + auto itor = block_variable_to_index_.find(&bv.members[i]); + if (itor != block_variable_to_index_.end()) { + os << t2 << "- *bv" << itor->second << std::endl; + } else { + os << t2 << "- [recursive]" << std::endl; + } + } + if (verbosity_ >= 1) { + // SpvReflectTypeDescription* type_description; + if (bv.type_description == nullptr) { + os << t1 << "type_description:" << std::endl; + } else { + auto itor = type_description_to_index_.find(bv.type_description); + assert(itor != type_description_to_index_.end()); + os << t1 << "type_description: *td" << itor->second << std::endl; + } + } + // } SpvReflectBlockVariable; +} + +void SpvReflectToYaml::WriteDescriptorBinding(std::ostream& os, const SpvReflectDescriptorBinding& db, uint32_t indent_level) { + if (db.uav_counter_binding != nullptr) { + auto itor = descriptor_binding_to_index_.find(db.uav_counter_binding); + if (itor == descriptor_binding_to_index_.end()) { + WriteDescriptorBinding(os, *(db.uav_counter_binding), indent_level); + } + } + + const std::string t0 = Indent(indent_level); + const std::string t1 = Indent(indent_level + 1); + const std::string t2 = Indent(indent_level + 2); + const std::string t3 = Indent(indent_level + 3); + + // A binding's UAV binding later may appear later in the table than the + // binding itself, in which case we've already output entries for both + // bindings, and can just write another reference here. + { + auto itor = descriptor_binding_to_index_.find(&db); + if (itor != descriptor_binding_to_index_.end()) { + os << t0 << "- *db" << itor->second << std::endl; + return; + } + } + + uint32_t descriptor_binding_index = static_cast(descriptor_binding_to_index_.size()); + descriptor_binding_to_index_[&db] = descriptor_binding_index; + + os << t0 << "- &db" << descriptor_binding_index << std::endl; + // typedef struct SpvReflectDescriptorBinding { + // uint32_t spirv_id; + os << t1 << "spirv_id: " << db.spirv_id << std::endl; + // const char* name; + os << t1 << "name: " << SafeString(db.name) << std::endl; + // uint32_t binding; + os << t1 << "binding: " << db.binding << std::endl; + // uint32_t input_attachment_index; + os << t1 << "input_attachment_index: " << db.input_attachment_index << std::endl; + // uint32_t set; + os << t1 << "set: " << db.set << std::endl; + // SpvReflectDecorationFlags decoration_flags; + os << t1 << "decoration_flags: " << AsHexString(db.decoration_flags) << " # " << ToStringDecorationFlags(db.decoration_flags) + << std::endl; + // SpvReflectDescriptorType descriptor_type; + os << t1 << "descriptor_type: " << db.descriptor_type << " # " << ToStringDescriptorType(db.descriptor_type) << std::endl; + // SpvReflectResourceType resource_type; + os << t1 << "resource_type: " << db.resource_type << " # " << ToStringResourceType(db.resource_type) << std::endl; + // SpvReflectImageTraits image; + os << t1 << "image: { "; + // typedef struct SpvReflectImageTraits { + // SpvDim dim; + os << "dim: " << db.image.dim << ", "; + // uint32_t depth; + os << "depth: " << db.image.depth << ", "; + // uint32_t arrayed; + os << "arrayed: " << db.image.arrayed << ", "; + // uint32_t ms; + os << "ms: " << db.image.ms << ", "; + // uint32_t sampled; + os << "sampled: " << db.image.sampled << ", "; + // SpvImageFormat image_format; + os << "image_format: " << db.image.image_format; + // } SpvReflectImageTraits; + os << " }" + << " # dim=" << ToStringSpvDim(db.image.dim) << " image_format=" << ToStringSpvImageFormat(db.image.image_format) << std::endl; + + // SpvReflectBlockVariable block; + { + auto itor = block_variable_to_index_.find(&db.block); + assert(itor != block_variable_to_index_.end()); + os << t1 << "block: *bv" << itor->second << " # " << SafeString(db.block.name) << std::endl; + } + // SpvReflectBindingArrayTraits array; + os << t1 << "array: { "; + // typedef struct SpvReflectBindingArrayTraits { + // uint32_t dims_count; + os << "dims_count: " << db.array.dims_count << ", "; + // uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; + os << "dims: ["; + for (uint32_t i_dim = 0; i_dim < db.array.dims_count; ++i_dim) { + os << db.array.dims[i_dim] << ","; + } + // } SpvReflectBindingArrayTraits; + os << "] }" << std::endl; + + // uint32_t accessed; + os << t1 << "accessed: " << db.accessed << std::endl; + + // uint32_t uav_counter_id; + os << t1 << "uav_counter_id: " << db.uav_counter_id << std::endl; + // struct SpvReflectDescriptorBinding* uav_counter_binding; + if (db.uav_counter_binding == nullptr) { + os << t1 << "uav_counter_binding:" << std::endl; + } else { + auto itor = descriptor_binding_to_index_.find(db.uav_counter_binding); + assert(itor != descriptor_binding_to_index_.end()); + os << t1 << "uav_counter_binding: *db" << itor->second << " # " << SafeString(db.uav_counter_binding->name) << std::endl; + } + + if (db.byte_address_buffer_offset_count > 0) { + os << t1 << "ByteAddressBuffer offsets: ["; + for (uint32_t i = 0; i < db.byte_address_buffer_offset_count; i++) { + os << db.byte_address_buffer_offsets[i]; + if (i < (db.byte_address_buffer_offset_count - 1)) { + os << ", "; + } + } + os << "]\n"; + } + + if (verbosity_ >= 1) { + // SpvReflectTypeDescription* type_description; + if (db.type_description == nullptr) { + os << t1 << "type_description:" << std::endl; + } else { + auto itor = type_description_to_index_.find(db.type_description); + assert(itor != type_description_to_index_.end()); + os << t1 << "type_description: *td" << itor->second << std::endl; + } + } + // struct { + // uint32_t binding; + // uint32_t set; + // } word_offset; + os << t1 << "word_offset: { binding: " << db.word_offset.binding; + os << ", set: " << db.word_offset.set << " }" << std::endl; + + if (db.user_type != SPV_REFLECT_USER_TYPE_INVALID) { + os << t1 << "user_type: " << ToStringUserType(db.user_type) << std::endl; + } + // } SpvReflectDescriptorBinding; +} + +void SpvReflectToYaml::WriteInterfaceVariable(std::ostream& os, const SpvReflectInterfaceVariable& iv, uint32_t indent_level) { + for (uint32_t i = 0; i < iv.member_count; ++i) { + assert(interface_variable_to_index_.find(&iv.members[i]) == interface_variable_to_index_.end()); + WriteInterfaceVariable(os, iv.members[i], indent_level); + } + + const std::string t0 = Indent(indent_level); + const std::string t1 = Indent(indent_level + 1); + const std::string t2 = Indent(indent_level + 2); + const std::string t3 = Indent(indent_level + 3); + + uint32_t interface_variable_index = static_cast(interface_variable_to_index_.size()); + interface_variable_to_index_[&iv] = interface_variable_index; + + // typedef struct SpvReflectInterfaceVariable { + os << t0 << "- &iv" << interface_variable_index << std::endl; + // uint32_t spirv_id; + os << t1 << "spirv_id: " << iv.spirv_id << std::endl; + // const char* name; + os << t1 << "name: " << SafeString(iv.name) << std::endl; + // uint32_t location; + os << t1 << "location: " << iv.location << std::endl; + // SpvStorageClass storage_class; + os << t1 << "storage_class: " << iv.storage_class << " # " << ToStringSpvStorageClass(iv.storage_class) << std::endl; + // const char* semantic; + os << t1 << "semantic: " << SafeString(iv.semantic) << std::endl; + // SpvReflectDecorationFlags decoration_flags; + os << t1 << "decoration_flags: " << AsHexString(iv.decoration_flags) << " # " << ToStringDecorationFlags(iv.decoration_flags) + << std::endl; + // SpvBuiltIn built_in; + os << t1 << "built_in: "; + if (iv.decoration_flags & SPV_REFLECT_DECORATION_BLOCK) { + for (uint32_t i = 0; i < iv.member_count; i++) { + os << iv.members[i].built_in; + if (i < (iv.member_count - 1)) { + os << ", "; + } + } + } else { + os << iv.built_in; + } + os << " # " << ToStringSpvBuiltIn(iv, false) << std::endl; + // SpvReflectNumericTraits numeric; + // typedef struct SpvReflectNumericTraits { + os << t1 << "numeric:" << std::endl; + // struct Scalar { + // uint32_t width; + // uint32_t signedness; + // } scalar; + os << t2 << "scalar: { "; + os << "width: " << iv.numeric.scalar.width << ", "; + os << "signedness: " << iv.numeric.scalar.signedness << " }" << std::endl; + // struct Vector { + // uint32_t component_count; + // } vector; + os << t2 << "vector: { "; + os << "component_count: " << iv.numeric.vector.component_count << " }" << std::endl; + // struct Matrix { + // uint32_t column_count; + // uint32_t row_count; + // uint32_t stride; // Measured in bytes + // } matrix; + os << t2 << "matrix: { "; + os << "column_count: " << iv.numeric.matrix.column_count << ", "; + os << "row_count: " << iv.numeric.matrix.row_count << ", "; + os << "stride: " << iv.numeric.matrix.stride << " }" << std::endl; + // } SpvReflectNumericTraits; + + // SpvReflectArrayTraits array; + os << t1 << "array: { "; + // typedef struct SpvReflectArrayTraits { + // uint32_t dims_count; + os << "dims_count: " << iv.array.dims_count << ", "; + // uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; + os << "dims: ["; + for (uint32_t i_dim = 0; i_dim < iv.array.dims_count; ++i_dim) { + os << iv.array.dims[i_dim] << ","; + } + os << "], "; + // uint32_t stride; // Measured in bytes + os << "stride: " << iv.array.stride; + // } SpvReflectArrayTraits; + os << " }" << std::endl; + + // uint32_t member_count; + os << t1 << "member_count: " << iv.member_count << std::endl; + // struct SpvReflectInterfaceVariable* members; + os << t1 << "members:" << std::endl; + for (uint32_t i = 0; i < iv.member_count; ++i) { + auto itor = interface_variable_to_index_.find(&iv.members[i]); + assert(itor != interface_variable_to_index_.end()); + os << t2 << "- *iv" << itor->second << " # " << SafeString(iv.members[i].name) << std::endl; + } + + // SpvReflectFormat format; + os << t1 << "format: " << iv.format << " # " << ToStringFormat(iv.format) << std::endl; + + if (verbosity_ >= 1) { + // SpvReflectTypeDescription* type_description; + if (!iv.type_description) { + os << t1 << "type_description:" << std::endl; + } else { + auto itor = type_description_to_index_.find(iv.type_description); + assert(itor != type_description_to_index_.end()); + os << t1 << "type_description: *td" << itor->second << std::endl; + } + } + + // struct { + // uint32_t location; + // } word_offset; + os << t1 << "word_offset: { location: " << iv.word_offset.location << " }" << std::endl; + + // } SpvReflectInterfaceVariable; +} + +void SpvReflectToYaml::WriteBlockVariableTypes(std::ostream& os, const SpvReflectBlockVariable& bv, uint32_t indent_level) { + const auto* td = bv.type_description; + if (td && type_description_to_index_.find(td) == type_description_to_index_.end()) { + WriteTypeDescription(os, *td, indent_level); + } + + if (bv.flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) { + return; + } + for (uint32_t i = 0; i < bv.member_count; ++i) { + WriteBlockVariableTypes(os, bv.members[i], indent_level); + } +} +void SpvReflectToYaml::WriteDescriptorBindingTypes(std::ostream& os, const SpvReflectDescriptorBinding& db, uint32_t indent_level) { + WriteBlockVariableTypes(os, db.block, indent_level); + + if (db.uav_counter_binding) { + WriteDescriptorBindingTypes(os, *(db.uav_counter_binding), indent_level); + } + + const auto* td = db.type_description; + if (td && type_description_to_index_.find(td) == type_description_to_index_.end()) { + WriteTypeDescription(os, *td, indent_level); + } +} +void SpvReflectToYaml::WriteInterfaceVariableTypes(std::ostream& os, const SpvReflectInterfaceVariable& iv, uint32_t indent_level) { + const auto* td = iv.type_description; + if (td && type_description_to_index_.find(td) == type_description_to_index_.end()) { + WriteTypeDescription(os, *td, indent_level); + } + + for (uint32_t i = 0; i < iv.member_count; ++i) { + WriteInterfaceVariableTypes(os, iv.members[i], indent_level); + } +} + +void SpvReflectToYaml::Write(std::ostream& os) { + if (!sm_._internal) { + return; + } + + uint32_t indent_level = 0; + const std::string t0 = Indent(indent_level); + const std::string t1 = Indent(indent_level + 1); + const std::string t2 = Indent(indent_level + 2); + const std::string t3 = Indent(indent_level + 3); + + os << "%YAML 1.1" << std::endl; + os << "---" << std::endl; + + type_description_to_index_.clear(); + if (verbosity_ >= 2) { + os << t0 << "all_type_descriptions:" << std::endl; + // Write the entire internal type_description table; all type descriptions + // are reachable from there, though most of them are purely internal & not + // referenced by any of the public-facing structures. + for (size_t i = 0; i < sm_._internal->type_description_count; ++i) { + WriteTypeDescription(os, sm_._internal->type_descriptions[i], indent_level + 1); + } + } else if (verbosity_ >= 1) { + os << t0 << "all_type_descriptions:" << std::endl; + // Iterate through all public-facing structures and write any type + // descriptions we find (and their children). + for (uint32_t i = 0; i < sm_.descriptor_binding_count; ++i) { + WriteDescriptorBindingTypes(os, sm_.descriptor_bindings[i], indent_level + 1); + } + for (uint32_t i = 0; i < sm_.push_constant_block_count; ++i) { + WriteBlockVariableTypes(os, sm_.push_constant_blocks[i], indent_level + 1); + } + for (uint32_t i = 0; i < sm_.input_variable_count; ++i) { + WriteInterfaceVariableTypes(os, *sm_.input_variables[i], indent_level + 1); + } + for (uint32_t i = 0; i < sm_.output_variable_count; ++i) { + WriteInterfaceVariableTypes(os, *sm_.output_variables[i], indent_level + 1); + } + } + + block_variable_to_index_.clear(); + os << t0 << "all_block_variables:" << std::endl; + for (uint32_t i = 0; i < sm_.descriptor_binding_count; ++i) { + WriteBlockVariable(os, sm_.descriptor_bindings[i].block, indent_level + 1); + } + for (uint32_t i = 0; i < sm_.push_constant_block_count; ++i) { + WriteBlockVariable(os, sm_.push_constant_blocks[i], indent_level + 1); + } + + descriptor_binding_to_index_.clear(); + os << t0 << "all_descriptor_bindings:" << std::endl; + for (uint32_t i = 0; i < sm_.descriptor_binding_count; ++i) { + WriteDescriptorBinding(os, sm_.descriptor_bindings[i], indent_level + 1); + } + + interface_variable_to_index_.clear(); + os << t0 << "all_interface_variables:" << std::endl; + for (uint32_t i = 0; i < sm_.input_variable_count; ++i) { + WriteInterfaceVariable(os, *sm_.input_variables[i], indent_level + 1); + } + for (uint32_t i = 0; i < sm_.output_variable_count; ++i) { + WriteInterfaceVariable(os, *sm_.output_variables[i], indent_level + 1); + } + + // struct SpvReflectShaderModule { + os << t0 << "module:" << std::endl; + // uint16_t generator; + os << t1 << "generator: " << sm_.generator << " # " << ToStringGenerator(sm_.generator) << std::endl; + // const char* entry_point_name; + os << t1 << "entry_point_name: " << SafeString(sm_.entry_point_name) << std::endl; + // uint32_t entry_point_id; + os << t1 << "entry_point_id: " << sm_.entry_point_id << std::endl; + // SpvSourceLanguage source_language; + os << t1 << "source_language: " << sm_.source_language << " # " << ToStringSpvSourceLanguage(sm_.source_language) << std::endl; + // uint32_t source_language_version; + os << t1 << "source_language_version: " << sm_.source_language_version << std::endl; + // SpvExecutionModel spirv_execution_model; + os << t1 << "spirv_execution_model: " << sm_.spirv_execution_model << " # " + << ToStringSpvExecutionModel(sm_.spirv_execution_model) << std::endl; + // SpvShaderStageFlagBits shader_stage; + os << t1 << "shader_stage: " << AsHexString(sm_.shader_stage) << " # " << ToStringShaderStage(sm_.shader_stage) << std::endl; + // uint32_t descriptor_binding_count; + os << t1 << "descriptor_binding_count: " << sm_.descriptor_binding_count << std::endl; + // SpvReflectDescriptorBinding* descriptor_bindings; + os << t1 << "descriptor_bindings:" << std::endl; + for (uint32_t i = 0; i < sm_.descriptor_binding_count; ++i) { + auto itor = descriptor_binding_to_index_.find(&sm_.descriptor_bindings[i]); + assert(itor != descriptor_binding_to_index_.end()); + os << t2 << "- *db" << itor->second << " # " << SafeString(sm_.descriptor_bindings[i].name) << std::endl; + } + // uint32_t descriptor_set_count; + os << t1 << "descriptor_set_count: " << sm_.descriptor_set_count << std::endl; + // SpvReflectDescriptorSet descriptor_sets[SPV_REFLECT_MAX_DESCRIPTOR_SETS]; + os << t1 << "descriptor_sets:" << std::endl; + for (uint32_t i_set = 0; i_set < sm_.descriptor_set_count; ++i_set) { + // typedef struct SpvReflectDescriptorSet { + const auto& dset = sm_.descriptor_sets[i_set]; + // uint32_t set; + os << t1 << "- " + << "set: " << dset.set << std::endl; + // uint32_t binding_count; + os << t2 << "binding_count: " << dset.binding_count << std::endl; + // SpvReflectDescriptorBinding** bindings; + os << t2 << "bindings:" << std::endl; + for (uint32_t i_binding = 0; i_binding < dset.binding_count; ++i_binding) { + auto itor = descriptor_binding_to_index_.find(dset.bindings[i_binding]); + assert(itor != descriptor_binding_to_index_.end()); + os << t3 << "- *db" << itor->second << " # " << SafeString(dset.bindings[i_binding]->name) << std::endl; + } + // } SpvReflectDescriptorSet; + } + // uint32_t input_variable_count; + os << t1 << "input_variable_count: " << sm_.input_variable_count << ",\n"; + // SpvReflectInterfaceVariable* input_variables; + os << t1 << "input_variables:" << std::endl; + for (uint32_t i = 0; i < sm_.input_variable_count; ++i) { + auto itor = interface_variable_to_index_.find(sm_.input_variables[i]); + assert(itor != interface_variable_to_index_.end()); + os << t2 << "- *iv" << itor->second << " # " << SafeString(sm_.input_variables[i]->name) << std::endl; + } + // uint32_t output_variable_count; + os << t1 << "output_variable_count: " << sm_.output_variable_count << ",\n"; + // SpvReflectInterfaceVariable* output_variables; + os << t1 << "output_variables:" << std::endl; + for (uint32_t i = 0; i < sm_.output_variable_count; ++i) { + auto itor = interface_variable_to_index_.find(sm_.output_variables[i]); + assert(itor != interface_variable_to_index_.end()); + os << t2 << "- *iv" << itor->second << " # " << SafeString(sm_.output_variables[i]->name) << std::endl; + } + // uint32_t push_constant_count; + os << t1 << "push_constant_count: " << sm_.push_constant_block_count << ",\n"; + // SpvReflectBlockVariable* push_constants; + os << t1 << "push_constants:" << std::endl; + for (uint32_t i = 0; i < sm_.push_constant_block_count; ++i) { + auto itor = block_variable_to_index_.find(&sm_.push_constant_blocks[i]); + assert(itor != block_variable_to_index_.end()); + os << t2 << "- *bv" << itor->second << " # " << SafeString(sm_.push_constant_blocks[i].name) << std::endl; + } + + // uint32_t spec_constant_count; + os << t1 << "specialization_constant_count: " << sm_.spec_constant_count << ",\n"; + // SpvReflectSpecializationConstant* spec_constants; + os << t1 << "specialization_constants:" << std::endl; + for (uint32_t i = 0; i < sm_.spec_constant_count; ++i) { + os << t3 << "- name: " << SafeString(sm_.spec_constants[i].name) << std::endl; + os << t3 << " spirv_id: " << sm_.spec_constants[i].spirv_id << std::endl; + os << t3 << " constant_id: " << sm_.spec_constants[i].constant_id << std::endl; + } + + if (verbosity_ >= 2) { + // struct Internal { + os << t1 << "_internal:" << std::endl; + if (sm_._internal) { + // size_t spirv_size; + os << t2 << "spirv_size: " << sm_._internal->spirv_size << std::endl; + // uint32_t* spirv_code; + os << t2 << "spirv_code: ["; + for (size_t i = 0; i < sm_._internal->spirv_word_count; ++i) { + if ((i % 6) == 0) { + os << std::endl << t3; + } + os << AsHexString(sm_._internal->spirv_code[i]) << ","; + } + os << "]" << std::endl; + // uint32_t spirv_word_count; + os << t2 << "spirv_word_count: " << sm_._internal->spirv_word_count << std::endl; + // size_t type_description_count; + os << t2 << "type_description_count: " << sm_._internal->type_description_count << std::endl; + // SpvReflectTypeDescription* type_descriptions; + os << t2 << "type_descriptions:" << std::endl; + for (uint32_t i = 0; i < sm_._internal->type_description_count; ++i) { + auto itor = type_description_to_index_.find(&sm_._internal->type_descriptions[i]); + assert(itor != type_description_to_index_.end()); + os << t3 << "- *td" << itor->second << std::endl; + } + } + // } * _internal; + } + + os << "..." << std::endl; +} diff --git a/lib/All/SPIRV-Reflect/common/output_stream.h b/lib/All/SPIRV-Reflect/common/output_stream.h new file mode 100644 index 0000000..42c837d --- /dev/null +++ b/lib/All/SPIRV-Reflect/common/output_stream.h @@ -0,0 +1,70 @@ +#ifndef SPIRV_REFLECT_OUTPUT_STREAM_H +#define SPIRV_REFLECT_OUTPUT_STREAM_H + +#include +#include +#include + +#include "spirv_reflect.h" + +std::string ToStringSpvSourceLanguage(SpvSourceLanguage lang); +std::string ToStringSpvExecutionModel(SpvExecutionModel model); +std::string ToStringSpvStorageClass(int storage_class); +std::string ToStringSpvDim(SpvDim dim); +std::string ToStringSpvBuiltIn(const SpvReflectInterfaceVariable& variable, bool preface); +std::string ToStringSpvImageFormat(SpvImageFormat fmt); + +std::string ToStringGenerator(SpvReflectGenerator generator); +std::string ToStringShaderStage(SpvReflectShaderStageFlagBits stage); +std::string ToStringResourceType(SpvReflectResourceType type); +std::string ToStringDescriptorType(SpvReflectDescriptorType value); +std::string ToStringTypeFlags(SpvReflectTypeFlags type_flags); +std::string ToStringVariableFlags(SpvReflectVariableFlags flags); +std::string ToStringDecorationFlags(SpvReflectDecorationFlags decoration_flags); +std::string ToStringDescriptorType(SpvReflectDescriptorType value); +std::string ToStringFormat(SpvReflectFormat fmt); +std::string ToStringComponentType(const SpvReflectTypeDescription& type, uint32_t member_decoration_flags); +std::string ToStringType(SpvSourceLanguage src_lang, const SpvReflectTypeDescription& type); + +// std::ostream& operator<<(std::ostream& os, const spv_reflect::ShaderModule& obj); +void WriteReflection(const spv_reflect::ShaderModule& obj, bool flatten_cbuffers, std::ostream& os); + +class SpvReflectToYaml { + public: + // verbosity = 0: top-level tables only (module, block variables, interface variables, descriptor bindings). + // verbosity = 1: everything above, plus type description tables for all public objects. + // verbosity = 2: everything above, plus SPIRV bytecode and full type description table. HUGE. + explicit SpvReflectToYaml(const SpvReflectShaderModule& shader_module, uint32_t verbosity = 0); + + friend std::ostream& operator<<(std::ostream& os, SpvReflectToYaml& to_yaml) { + to_yaml.Write(os); + return os; + } + + private: + void Write(std::ostream& os); + + SpvReflectToYaml(const SpvReflectToYaml&) = delete; + SpvReflectToYaml(const SpvReflectToYaml&&) = delete; + static std::string Indent(uint32_t level) { return std::string(2 * level, ' '); } + static std::string SafeString(const char* str) { return str ? (std::string("\"") + str + "\"") : ""; } + void WriteTypeDescription(std::ostream& os, const SpvReflectTypeDescription& td, uint32_t indent_level); + void WriteBlockVariable(std::ostream& os, const SpvReflectBlockVariable& bv, uint32_t indent_level); + void WriteDescriptorBinding(std::ostream& os, const SpvReflectDescriptorBinding& db, uint32_t indent_level); + void WriteInterfaceVariable(std::ostream& os, const SpvReflectInterfaceVariable& iv, uint32_t indent_level); + + // Write all SpvReflectTypeDescription objects reachable from the specified objects, if they haven't been + // written already. + void WriteBlockVariableTypes(std::ostream& os, const SpvReflectBlockVariable& bv, uint32_t indent_level); + void WriteDescriptorBindingTypes(std::ostream& os, const SpvReflectDescriptorBinding& db, uint32_t indent_level); + void WriteInterfaceVariableTypes(std::ostream& os, const SpvReflectInterfaceVariable& iv, uint32_t indent_level); + + const SpvReflectShaderModule& sm_; + uint32_t verbosity_ = 0; + std::map type_description_to_index_; + std::map block_variable_to_index_; + std::map descriptor_binding_to_index_; + std::map interface_variable_to_index_; +}; + +#endif diff --git a/lib/All/SPIRV-Reflect/examples/CMakeLists.txt b/lib/All/SPIRV-Reflect/examples/CMakeLists.txt new file mode 100644 index 0000000..e704229 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/CMakeLists.txt @@ -0,0 +1,76 @@ +cmake_minimum_required(VERSION 3.16) + +project(examples) + +list(APPEND SPIRV_REFLECT_FILES + ${CMAKE_SOURCE_DIR}/spirv_reflect.h + ${CMAKE_SOURCE_DIR}/spirv_reflect.c +) + +list(APPEND COMMON_FILES + common.h + common.cpp + ../common/output_stream.h + ../common/output_stream.cpp + sample_spv.h +) + +################################################################################ +# descriptors +################################################################################ +add_executable(descriptors ${CMAKE_CURRENT_SOURCE_DIR}/main_descriptors.cpp ${COMMON_FILES} ${SPIRV_REFLECT_FILES}) +target_include_directories(descriptors PRIVATE ${CMAKE_SOURCE_DIR}) +if (${VULKAN_DIR_FOUND}) + target_compile_definitions(descriptors PRIVATE SPIRV_REFLECT_HAS_VULKAN_H) + target_include_directories(descriptors PRIVATE ${VULKAN_DIR}/include) + set_target_properties(descriptors PROPERTIES CXX_STANDARD 11) +endif() +if(WIN32) + target_compile_definitions(descriptors PRIVATE _CRT_SECURE_NO_WARNINGS) + set_target_properties(descriptors PROPERTIES FOLDER "examples") +endif() + +################################################################################ +# io_variables +################################################################################ +add_executable(io_variables ${CMAKE_CURRENT_SOURCE_DIR}/main_io_variables.cpp ${COMMON_FILES} ${SPIRV_REFLECT_FILES}) +target_include_directories(io_variables PRIVATE ${CMAKE_SOURCE_DIR}) +if (${VULKAN_DIR_FOUND}) + target_compile_definitions(io_variables PRIVATE SPIRV_REFLECT_HAS_VULKAN_H) + target_include_directories(io_variables PRIVATE ${VULKAN_DIR}/include) + set_target_properties(io_variables PROPERTIES CXX_STANDARD 11) +endif() +if(WIN32) + target_compile_definitions(io_variables PRIVATE _CRT_SECURE_NO_WARNINGS) + set_target_properties(io_variables PROPERTIES FOLDER "examples") +endif() + +################################################################################ +# hlsl_resource_types +################################################################################ +add_executable(hlsl_resource_types ${CMAKE_CURRENT_SOURCE_DIR}/main_hlsl_resource_types.cpp ${COMMON_FILES} ${SPIRV_REFLECT_FILES}) +target_include_directories(hlsl_resource_types PRIVATE ${CMAKE_SOURCE_DIR}) +if (${VULKAN_DIR_FOUND}) + target_compile_definitions(hlsl_resource_types PRIVATE SPIRV_REFLECT_HAS_VULKAN_H) + target_include_directories(hlsl_resource_types PRIVATE ${VULKAN_DIR}/include) + set_target_properties(hlsl_resource_types PROPERTIES CXX_STANDARD 11) +endif() +if(WIN32) + target_compile_definitions(hlsl_resource_types PRIVATE _CRT_SECURE_NO_WARNINGS) + set_target_properties(hlsl_resource_types PROPERTIES FOLDER "examples") +endif() + +################################################################################ +# explorer +################################################################################ +add_executable(explorer ${CMAKE_CURRENT_SOURCE_DIR}/main_explorer.cpp ${COMMON_FILES} ${SPIRV_REFLECT_FILES}) +target_include_directories(explorer PRIVATE ${CMAKE_SOURCE_DIR}) +if (${VULKAN_DIR_FOUND}) + target_compile_definitions(explorer PRIVATE SPIRV_REFLECT_HAS_VULKAN_H) + target_include_directories(explorer PRIVATE ${VULKAN_DIR}/include) + set_target_properties(explorer PROPERTIES CXX_STANDARD 11) +endif() +if(WIN32) + target_compile_definitions(explorer PRIVATE _CRT_SECURE_NO_WARNINGS) + set_target_properties(explorer PROPERTIES FOLDER "examples") +endif() diff --git a/lib/All/SPIRV-Reflect/examples/arg_parser.cpp b/lib/All/SPIRV-Reflect/examples/arg_parser.cpp new file mode 100644 index 0000000..86f509a --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/arg_parser.cpp @@ -0,0 +1,362 @@ +#include "arg_parser.h" + +#include +#include +#include + +ArgParser::ArgParser() {} + +ArgParser::~ArgParser() {} + +ArgParser::Option* ArgParser::FindOptionByShortName(const std::string& short_name) { + ArgParser::Option* p_option = nullptr; + auto it = std::find_if(std::begin(m_options), std::end(m_options), + [short_name](const ArgParser::Option& elem) -> bool { return elem.short_name == short_name; }); + if (it != std::end(m_options)) { + p_option = &(*it); + } + return p_option; +} + +const ArgParser::Option* ArgParser::FindOptionByShortName(const std::string& short_name) const { + const ArgParser::Option* p_option = nullptr; + auto it = std::find_if(std::begin(m_options), std::end(m_options), + [short_name](const ArgParser::Option& elem) -> bool { return elem.short_name == short_name; }); + if (it != std::end(m_options)) { + p_option = &(*it); + } + return p_option; +} + +ArgParser::Option* ArgParser::FindOptionByLongName(const std::string& long_name) { + ArgParser::Option* p_option = nullptr; + auto it = std::find_if(std::begin(m_options), std::end(m_options), + [long_name](const ArgParser::Option& elem) -> bool { return elem.long_name == long_name; }); + if (it != std::end(m_options)) { + p_option = &(*it); + } + return p_option; +} + +const ArgParser::Option* ArgParser::FindOptionByLongName(const std::string& long_name) const { + const ArgParser::Option* p_option = nullptr; + auto it = std::find_if(std::begin(m_options), std::end(m_options), + [long_name](const ArgParser::Option& elem) -> bool { return elem.long_name == long_name; }); + if (it != std::end(m_options)) { + p_option = &(*it); + } + return p_option; +} + +bool ArgParser::AddFlag(const std::string& short_name, const std::string& long_name, const std::string& desc) { + Option option = {}; + option.short_name = short_name; + option.long_name = long_name; + option.type = OPTION_TYPE_FLAG; + option.desc = desc; + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + if ((p_short != nullptr) || (p_long != nullptr)) { + return false; + } + m_options.push_back(option); + return true; +} + +bool ArgParser::AddOptionString(const std::string& short_name, const std::string& long_name, const std::string& desc, + const std::string& default_value) { + Option option = {}; + option.short_name = short_name; + option.long_name = long_name; + option.type = OPTION_TYPE_STRING; + option.desc = desc; + option.default_value.str = default_value; + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + if ((p_short != nullptr) || (p_long != nullptr)) { + return false; + } + m_options.push_back(option); + return true; +} + +bool ArgParser::AddOptionInt(const std::string& short_name, const std::string& long_name, const std::string& desc, + int default_value) { + Option option = {}; + option.short_name = short_name; + option.long_name = long_name; + option.type = OPTION_TYPE_INT; + option.desc = desc; + option.default_value.i32 = default_value; + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + if ((p_short != nullptr) || (p_long != nullptr)) { + return false; + } + m_options.push_back(option); + return true; +} + +bool ArgParser::AddOptionFloat(const std::string& short_name, const std::string& long_name, const std::string& desc, + float default_value) { + Option option = {}; + option.short_name = short_name; + option.long_name = long_name; + option.type = OPTION_TYPE_FLOAT; + option.desc = desc; + option.default_value.f32 = default_value; + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + if ((p_short != nullptr) || (p_long != nullptr)) { + return false; + } + m_options.push_back(option); + return true; +} + +bool ArgParser::Parse(int argc, char** argv, std::ostream& os) { + for (auto& opt : m_options) { + opt.value = opt.default_value; + opt.parsed = false; + } + + int i = 1; + while (i < argc) { + std::string s = argv[i]; + if (s[0] == '-') { + ArgParser::Option* p_option = nullptr; + if ((s.length() >= 2) && ((s[0] == '-') && (s[1] == '-'))) { + std::string long_name = s.substr(2); + p_option = FindOptionByLongName(long_name); + } else { + std::string short_name = s.substr(1); + p_option = FindOptionByShortName(short_name); + } + + if (p_option == nullptr) { + os << "ERROR: invalid argument " << s << std::endl; + return false; + } + + switch (p_option->type) { + case OPTION_TYPE_FLAG: { + p_option->parsed = true; + i += 1; + } break; + + case OPTION_TYPE_STRING: { + if ((i + 1) >= argc) { + os << "ERROR: missing option data for " << s << std::endl; + return false; + } + + s = argv[i + 1]; + p_option->value.str = s; + p_option->parsed = true; + + i += 2; + } break; + + case OPTION_TYPE_INT: { + if ((i + 1) >= argc) { + os << "ERROR: missing option data for " << s << std::endl; + return false; + } + + s = argv[i + 1]; + p_option->value.i32 = atoi(s.c_str()); + p_option->parsed = true; + + i += 2; + } break; + + case OPTION_TYPE_FLOAT: { + if ((i + 1) >= argc) { + os << "ERROR: missing option data for " << s << std::endl; + return false; + } + + s = argv[i + 1]; + p_option->value.f32 = static_cast(atof(s.c_str())); + p_option->parsed = true; + + i += 2; + } break; + + case OPTION_TYPE_UNDEFINED: { + } break; + } + } else { + m_args.push_back(s); + i += 1; + } + } + + return true; +} + +size_t ArgParser::GetArgCount() const { return m_args.size(); } + +bool ArgParser::GetArg(size_t i, std::string* p_value) const { + if ((GetArgCount() == 0) && (i >= GetArgCount())) { + return false; + } + + if (p_value != nullptr) { + *p_value = m_args[i]; + } + + return true; +} + +const std::vector& ArgParser::GetArgs() const { return m_args; } + +bool ArgParser::GetFlag(const std::string& short_name, const std::string& long_name) const { + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + + const ArgParser::Option* p_option = nullptr; + if (p_short != nullptr) { + p_option = p_short; + } + if ((p_option == nullptr) && (p_long != nullptr)) { + p_option = p_short; + } + + if (p_option == nullptr) { + return false; + } + + if (p_option->type != OPTION_TYPE_FLAG) { + return false; + } + + return p_option->parsed; +} + +bool ArgParser::GetString(const std::string& short_name, const std::string& long_name, std::string* p_value) const { + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + + const ArgParser::Option* p_option = nullptr; + if (p_short != nullptr) { + p_option = p_short; + } + if ((p_option == nullptr) && (p_long != nullptr)) { + p_option = p_short; + } + + if (p_option == nullptr) { + return false; + } + + if (!p_option->parsed || (p_option->type != OPTION_TYPE_STRING)) { + return false; + } + + if (p_value != nullptr) { + *p_value = p_option->value.str; + } + + return true; +} + +bool ArgParser::GetInt(const std::string& short_name, const std::string& long_name, int* p_value) const { + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + + const ArgParser::Option* p_option = nullptr; + if (p_short != nullptr) { + p_option = p_short; + } + if ((p_option == nullptr) && (p_long != nullptr)) { + p_option = p_short; + } + + if (p_option == nullptr) { + return false; + } + + if (!p_option->parsed || (p_option->type != OPTION_TYPE_INT)) { + return false; + } + + if (p_value != nullptr) { + *p_value = p_option->value.i32; + } + + return true; +} + +bool ArgParser::GetFloat(const std::string& short_name, const std::string& long_name, float* p_value) const { + auto p_short = FindOptionByShortName(short_name); + auto p_long = FindOptionByLongName(long_name); + + const ArgParser::Option* p_option = nullptr; + if (p_short != nullptr) { + p_option = p_short; + } + if ((p_option == nullptr) && (p_long != nullptr)) { + p_option = p_short; + } + + if (p_option == nullptr) { + return false; + } + + if (!p_option->parsed || (p_option->type != OPTION_TYPE_FLOAT)) { + return false; + } + + if (p_value != nullptr) { + *p_value = p_option->value.f32; + } + + return true; +} + +void ArgParser::PrintHelp(std::ostream& os) { + (void)os; + + /* + if (m_options.empty()) { + return; + } + + struct TextLine { + std::string option; + std::string desc; + }; + std::vector text_lines; + + size_t max_width = 0; + for (auto& it : m_options) { + std::stringstream ss; + ss << "--" << it.first; + switch (it.second.type) { + default: break; + case OPTION_TYPE_STRING : ss << " " << "[s]"; break; + case OPTION_TYPE_INT : ss << " " << "[i]"; break; + case OPTION_TYPE_FLOAT : ss << " " << "[f]"; break; + } + + std::string option = ss.str(); + max_width = std::max(max_width, option.size()); + + TextLine tl; + tl.option = option; + tl.desc = it.second.desc; + text_lines.push_back(tl); + } + max_width += 2; + + os << "\n"; + os << "Options:" << "\n"; + for (auto& tl : text_lines) { + os << " "; + os << std::left << std::setw(max_width) << tl.option; + os << tl.desc; + os << "\n"; + } + */ +} diff --git a/lib/All/SPIRV-Reflect/examples/arg_parser.h b/lib/All/SPIRV-Reflect/examples/arg_parser.h new file mode 100644 index 0000000..40f7059 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/arg_parser.h @@ -0,0 +1,65 @@ +#ifndef __VERIFLECT_ARG_PARSER_H__ +#define __VERIFLECT_ARG_PARSER_H__ + +#include +#include +#include +#include + +class ArgParser { + public: + enum OptionType { OPTION_TYPE_UNDEFINED = 0, OPTION_TYPE_FLAG, OPTION_TYPE_STRING, OPTION_TYPE_INT, OPTION_TYPE_FLOAT }; + + struct OptionValue { + std::string str; + union { + int i32; + float f32; + }; + }; + + struct Option { + std::string short_name; + std::string long_name; + OptionType type; + std::string desc; + OptionValue value; + OptionValue default_value; + bool parsed; + }; + + ArgParser(); + ~ArgParser(); + + bool AddFlag(const std::string& short_name, const std::string& long_name, const std::string& desc); + bool AddOptionString(const std::string& short_name, const std::string& long_name, const std::string& desc, + const std::string& default_value = ""); + bool AddOptionInt(const std::string& short_name, const std::string& long_name, const std::string& desc, int default_value = 0); + bool AddOptionFloat(const std::string& short_name, const std::string& long_name, const std::string& desc, + float default_value = 0); + + bool Parse(int argc, char** argv, std::ostream& os); + + size_t GetArgCount() const; + bool GetArg(size_t i, std::string* p_value) const; + const std::vector& GetArgs() const; + + bool GetFlag(const std::string& short_name, const std::string& long_name) const; + bool GetString(const std::string& short_name, const std::string& long_name, std::string* p_value) const; + bool GetInt(const std::string& short_name, const std::string& long_name, int* p_value) const; + bool GetFloat(const std::string& short_name, const std::string& long_name, float* p_value) const; + + void PrintHelp(std::ostream& os); + + private: + ArgParser::Option* FindOptionByShortName(const std::string& short_name); + const ArgParser::Option* FindOptionByShortName(const std::string& short_name) const; + ArgParser::Option* FindOptionByLongName(const std::string& long_name); + const ArgParser::Option* FindOptionByLongName(const std::string& long_name) const; + + private: + std::vector m_options; + std::vector m_args; +}; + +#endif // __VERIFLECT_ARG_PARSER_H__ \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/examples/build_sample_spv_h.sh b/lib/All/SPIRV-Reflect/examples/build_sample_spv_h.sh new file mode 100644 index 0000000..30e7dd9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/build_sample_spv_h.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +echo -e "#ifndef SAMPLE_SPV_H" > sample_spv.h +echo -e "#define SAMPLE_SPV_H" >> sample_spv.h + +echo -e "" >> sample_spv.h +echo -e "/* Source from sample.hlsl" >> sample_spv.h +echo -e "" >> sample_spv.h +cat sample.hlsl >> sample_spv.h +echo -e "\n" >> sample_spv.h +echo -e "*/" >> sample_spv.h + +echo -e "" >> sample_spv.h + +echo -e "// Imported from file 'sample.spv'" >> sample_spv.h +echo -e "const uint32_t k_sample_spv[] = {" >> sample_spv.h +glslc.exe -fshader-stage=frag -fentry-point=main -mfmt=num -o - sample.hlsl >> sample_spv.h +echo -e "};" >> sample_spv.h +echo -e "" >> sample_spv.h + +echo -e "/* SPIRV Disassembly" >> sample_spv.h +echo -e "" >> sample_spv.h +spirv-dis --raw-id sample.spv >> sample_spv.h +echo -e "" >> sample_spv.h +echo -e "*/" >> sample_spv.h + +echo -e "" >> sample_spv.h +echo -e "#endif // SAMPLE_SPV_H" >> sample_spv.h + +dos2unix sample_spv.h + +rm -f tmp_sample_spv_h \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/examples/common.cpp b/lib/All/SPIRV-Reflect/examples/common.cpp new file mode 100644 index 0000000..9317cda --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/common.cpp @@ -0,0 +1,128 @@ +#include "common.h" + +#include +#include +#include + +#include "../common/output_stream.h" + +void PrintModuleInfo(std::ostream& os, const SpvReflectShaderModule& obj, const char* /*indent*/) { + os << "entry point : " << obj.entry_point_name << "\n"; + os << "source lang : " << spvReflectSourceLanguage(obj.source_language) << "\n"; + os << "source lang ver : " << obj.source_language_version << "\n"; + if (obj.source_language == SpvSourceLanguageHLSL) { + os << "stage : "; + switch (obj.shader_stage) { + default: + break; + case SPV_REFLECT_SHADER_STAGE_VERTEX_BIT: + os << "VS"; + break; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + os << "HS"; + break; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + os << "DS"; + break; + case SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT: + os << "GS"; + break; + case SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT: + os << "PS"; + break; + case SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT: + os << "CS"; + break; + } + } +} + +void PrintDescriptorSet(std::ostream& os, const SpvReflectDescriptorSet& obj, const char* indent) { + const char* t = indent; + std::string tt = std::string(indent) + " "; + std::string ttttt = std::string(indent) + " "; + + os << t << "set : " << obj.set << "\n"; + os << t << "binding count : " << obj.binding_count; + os << "\n"; + for (uint32_t i = 0; i < obj.binding_count; ++i) { + const SpvReflectDescriptorBinding& binding = *obj.bindings[i]; + os << tt << i << ":" + << "\n"; + PrintDescriptorBinding(os, binding, false, ttttt.c_str()); + if (i < (obj.binding_count - 1)) { + os << "\n"; + } + } +} + +void PrintDescriptorBinding(std::ostream& os, const SpvReflectDescriptorBinding& obj, bool write_set, const char* indent) { + const char* t = indent; + os << t << "binding : " << obj.binding << "\n"; + if (write_set) { + os << t << "set : " << obj.set << "\n"; + } + os << t << "type : " << ToStringDescriptorType(obj.descriptor_type) << "\n"; + + // array + if (obj.array.dims_count > 0) { + os << t << "array : "; + for (uint32_t dim_index = 0; dim_index < obj.array.dims_count; ++dim_index) { + os << "[" << obj.array.dims[dim_index] << "]"; + } + os << "\n"; + } + + // counter + if (obj.uav_counter_binding != nullptr) { + os << t << "counter : "; + os << "("; + os << "set=" << obj.uav_counter_binding->set << ", "; + os << "binding=" << obj.uav_counter_binding->binding << ", "; + os << "name=" << obj.uav_counter_binding->name; + os << ");"; + os << "\n"; + } + + os << t << "name : " << obj.name; + if ((obj.type_description->type_name != nullptr) && (strlen(obj.type_description->type_name) > 0)) { + os << " " + << "(" << obj.type_description->type_name << ")"; + } +} + +void PrintInterfaceVariable(std::ostream& os, SpvSourceLanguage src_lang, const SpvReflectInterfaceVariable& obj, + const char* indent) { + const char* t = indent; + os << t << "location : "; + if (obj.decoration_flags & SPV_REFLECT_DECORATION_BUILT_IN) { + os << ToStringSpvBuiltIn(obj, true); + } else { + os << obj.location; + } + os << "\n"; + if (obj.semantic != nullptr) { + os << t << "semantic : " << obj.semantic << "\n"; + } + os << t << "type : " << ToStringType(src_lang, *obj.type_description) << "\n"; + os << t << "format : " << ToStringFormat(obj.format) << "\n"; + os << t << "qualifier : "; + if (obj.decoration_flags & SPV_REFLECT_DECORATION_FLAT) { + os << "flat"; + } else if (obj.decoration_flags & SPV_REFLECT_DECORATION_NOPERSPECTIVE) { + os << "noperspective"; + } else if (obj.decoration_flags & SPV_REFLECT_DECORATION_PATCH) { + os << "patch"; + } else if (obj.decoration_flags & SPV_REFLECT_DECORATION_PER_VERTEX) { + os << "pervertex"; + } else if (obj.decoration_flags & SPV_REFLECT_DECORATION_PER_TASK) { + os << "pertask"; + } + os << "\n"; + + os << t << "name : " << obj.name; + if ((obj.type_description->type_name != nullptr) && (strlen(obj.type_description->type_name) > 0)) { + os << " " + << "(" << obj.type_description->type_name << ")"; + } +} diff --git a/lib/All/SPIRV-Reflect/examples/common.h b/lib/All/SPIRV-Reflect/examples/common.h new file mode 100644 index 0000000..c9e8b4a --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/common.h @@ -0,0 +1,14 @@ +#ifndef SPIRV_REFLECT_EXAMPLES_COMMON_H +#define SPIRV_REFLECT_EXAMPLES_COMMON_H + +#include + +#include "spirv_reflect.h" + +void PrintModuleInfo(std::ostream& os, const SpvReflectShaderModule& obj, const char* indent = ""); +void PrintDescriptorSet(std::ostream& os, const SpvReflectDescriptorSet& obj, const char* indent = ""); +void PrintDescriptorBinding(std::ostream& os, const SpvReflectDescriptorBinding& obj, bool write_set, const char* indent = ""); +void PrintInterfaceVariable(std::ostream& os, SpvSourceLanguage src_lang, const SpvReflectInterfaceVariable& obj, + const char* indent); + +#endif diff --git a/lib/All/SPIRV-Reflect/examples/main_descriptors.cpp b/lib/All/SPIRV-Reflect/examples/main_descriptors.cpp new file mode 100644 index 0000000..6a4bddc --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/main_descriptors.cpp @@ -0,0 +1,85 @@ +#include + +#include "common.h" +#include "sample_spv.h" + +#if defined(SPIRV_REFLECT_HAS_VULKAN_H) +#include +struct DescriptorSetLayoutData { + uint32_t set_number; + VkDescriptorSetLayoutCreateInfo create_info; + std::vector bindings; +}; +#endif + +int main(int argn, char** argv) { + SpvReflectShaderModule module = {}; + SpvReflectResult result = spvReflectCreateShaderModule(sizeof(k_sample_spv), k_sample_spv, &module); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + uint32_t count = 0; + result = spvReflectEnumerateDescriptorSets(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + std::vector sets(count); + result = spvReflectEnumerateDescriptorSets(&module, &count, sets.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + +#if defined(SPIRV_REFLECT_HAS_VULKAN_H) + // Demonstrates how to generate all necessary data structures to create a + // VkDescriptorSetLayout for each descriptor set in this shader. + std::vector set_layouts(sets.size(), DescriptorSetLayoutData{}); + for (size_t i_set = 0; i_set < sets.size(); ++i_set) { + const SpvReflectDescriptorSet& refl_set = *(sets[i_set]); + DescriptorSetLayoutData& layout = set_layouts[i_set]; + layout.bindings.resize(refl_set.binding_count); + for (uint32_t i_binding = 0; i_binding < refl_set.binding_count; ++i_binding) { + const SpvReflectDescriptorBinding& refl_binding = *(refl_set.bindings[i_binding]); + VkDescriptorSetLayoutBinding& layout_binding = layout.bindings[i_binding]; + layout_binding.binding = refl_binding.binding; + layout_binding.descriptorType = static_cast(refl_binding.descriptor_type); + layout_binding.descriptorCount = 1; + for (uint32_t i_dim = 0; i_dim < refl_binding.array.dims_count; ++i_dim) { + layout_binding.descriptorCount *= refl_binding.array.dims[i_dim]; + } + layout_binding.stageFlags = static_cast(module.shader_stage); + } + layout.set_number = refl_set.set; + layout.create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout.create_info.bindingCount = refl_set.binding_count; + layout.create_info.pBindings = layout.bindings.data(); + } + // Nothing further is done with set_layouts in this sample; in a real + // application they would be merged with similar structures from other shader + // stages and/or pipelines to create a VkPipelineLayout. +#endif + + // Log the descriptor set contents to stdout + const char* t = " "; + const char* tt = " "; + + PrintModuleInfo(std::cout, module); + std::cout << "\n\n"; + + std::cout << "Descriptor sets:" + << "\n"; + for (size_t index = 0; index < sets.size(); ++index) { + auto p_set = sets[index]; + + // descriptor sets can also be retrieved directly from the module, by set + // index + auto p_set2 = spvReflectGetDescriptorSet(&module, p_set->set, &result); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + assert(p_set == p_set2); + (void)p_set2; + + std::cout << t << index << ":" + << "\n"; + PrintDescriptorSet(std::cout, *p_set, tt); + std::cout << "\n\n"; + } + + spvReflectDestroyShaderModule(&module); + + return 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/examples/main_explorer.cpp b/lib/All/SPIRV-Reflect/examples/main_explorer.cpp new file mode 100644 index 0000000..a5b5755 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/main_explorer.cpp @@ -0,0 +1,104 @@ +/* Copyright (c) 2023 LunarG, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "spirv_reflect.h" + +// ================================================================================================= +// PrintUsage() +// ================================================================================================= +void PrintUsage() { + std::cout << "Usage: explorer path/to/SPIR-V/bytecode.spv\n" + << "\tThis is used to set a breakpoint and explorer the API and " + "how to access info needed\n"; +} + +// ================================================================================================= +// main() +// ================================================================================================= +int main(int argn, char** argv) { + if (argn != 2) { + PrintUsage(); + return EXIT_FAILURE; + } else if (std::string(argv[1]) == "--help") { + PrintUsage(); + return EXIT_SUCCESS; + } + std::string input_spv_path = argv[1]; + + std::ifstream spv_ifstream(input_spv_path.c_str(), std::ios::binary); + if (!spv_ifstream.is_open()) { + std::cerr << "ERROR: could not open '" << input_spv_path << "' for reading\n"; + return EXIT_FAILURE; + } + + spv_ifstream.seekg(0, std::ios::end); + size_t size = static_cast(spv_ifstream.tellg()); + spv_ifstream.seekg(0, std::ios::beg); + + std::vector spv_data(size); + spv_ifstream.read(spv_data.data(), size); + + SpvReflectShaderModule module = {}; + SpvReflectResult result = spvReflectCreateShaderModule(spv_data.size(), spv_data.data(), &module); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + // Go through each enumerate to examine it + uint32_t count = 0; + + result = spvReflectEnumerateDescriptorSets(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector sets(count); + result = spvReflectEnumerateDescriptorSets(&module, &count, sets.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + result = spvReflectEnumerateDescriptorBindings(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector bindings(count); + result = spvReflectEnumerateDescriptorBindings(&module, &count, bindings.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + result = spvReflectEnumerateInterfaceVariables(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector interface_variables(count); + result = spvReflectEnumerateInterfaceVariables(&module, &count, interface_variables.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + result = spvReflectEnumerateInputVariables(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector input_variables(count); + result = spvReflectEnumerateInputVariables(&module, &count, input_variables.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + result = spvReflectEnumerateOutputVariables(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector output_variables(count); + result = spvReflectEnumerateOutputVariables(&module, &count, output_variables.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + result = spvReflectEnumeratePushConstantBlocks(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + std::vector push_constant(count); + result = spvReflectEnumeratePushConstantBlocks(&module, &count, push_constant.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + // Can set a breakpoint here and explorer the various variables enumerated. + spvReflectDestroyShaderModule(&module); + + return 0; +} diff --git a/lib/All/SPIRV-Reflect/examples/main_hlsl_resource_types.cpp b/lib/All/SPIRV-Reflect/examples/main_hlsl_resource_types.cpp new file mode 100644 index 0000000..5122c37 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/main_hlsl_resource_types.cpp @@ -0,0 +1,149 @@ +/* + Copyright 2017-2018 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#if defined(WIN32) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "../common/output_stream.h" +#include "examples/common.h" +#include "spirv_reflect.h" + +void StreamWrite(std::ostream& os, const SpvReflectDescriptorBinding& obj, bool write_set, const char* indent = "") { + const char* t = indent; + + os << " " << obj.name; + os << "\n"; + os << t; + os << ToStringDescriptorType(obj.descriptor_type); + os << " " + << "(" << ToStringResourceType(obj.resource_type) << ")"; + if ((obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE) || + (obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE) || + (obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) || + (obj.descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) { + os << "\n"; + os << t; + os << "dim=" << obj.image.dim << ", "; + os << "depth=" << obj.image.depth << ", "; + os << "arrayed=" << obj.image.arrayed << ", "; + os << "ms=" << obj.image.ms << ", "; + os << "sampled=" << obj.image.sampled; + } +} + +void StreamWrite(std::ostream& os, const SpvReflectShaderModule& obj, const char* indent = "") { + os << "entry point : " << obj.entry_point_name << "\n"; + os << "source lang : " << spvReflectSourceLanguage(obj.source_language) << "\n"; + os << "source lang ver : " << obj.source_language_version; +} + +void StreamWrite(std::ostream& os, const SpvReflectDescriptorBinding& obj) { StreamWrite(os, obj, true, " "); } + +// Specialized stream-writer that only includes descriptor bindings. +void StreamWrite(std::ostream& os, const spv_reflect::ShaderModule& obj) { + const char* t = " "; + const char* tt = " "; + const char* ttt = " "; + + StreamWrite(os, obj.GetShaderModule(), ""); + + SpvReflectResult result = SPV_REFLECT_RESULT_NOT_READY; + uint32_t count = 0; + std::vector variables; + std::vector bindings; + std::vector sets; + + count = 0; + result = obj.EnumerateDescriptorBindings(&count, nullptr); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + bindings.resize(count); + result = obj.EnumerateDescriptorBindings(&count, bindings.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + if (count > 0) { + os << "\n"; + os << "\n"; + os << t << "Descriptor bindings: " << count << "\n"; + for (size_t i = 0; i < bindings.size(); ++i) { + auto p_binding = bindings[i]; + assert(result == SPV_REFLECT_RESULT_SUCCESS); + os << tt << i << ":"; + StreamWrite(os, *p_binding, true, ttt); + if (i < (count - 1)) { + os << "\n\n"; + } + } + } +} + +// ================================================================================================= +// PrintUsage() +// ================================================================================================= +void PrintUsage() { + std::cout << "Usage: hlsl_resource_types [OPTIONS] path/to/SPIR-V/bytecode.spv" << std::endl + << "Options:" << std::endl + << " --help: Display this message" << std::endl + << std::endl; +} + +// ================================================================================================= +// main() +// ================================================================================================= +int main(int argn, char** argv) { + if (argn != 2) { + PrintUsage(); + return EXIT_FAILURE; + } else if (std::string(argv[1]) == "--help") { + PrintUsage(); + return EXIT_SUCCESS; + } + std::string input_spv_path = argv[1]; + + std::ifstream spv_ifstream(input_spv_path.c_str(), std::ios::binary); + if (!spv_ifstream.is_open()) { + std::cerr << "ERROR: could not open '" << input_spv_path << "' for reading" << std::endl; + return EXIT_FAILURE; + } + + spv_ifstream.seekg(0, std::ios::end); + size_t size = static_cast(spv_ifstream.tellg()); + spv_ifstream.seekg(0, std::ios::beg); + + { + std::vector spv_data(size); + spv_ifstream.read(spv_data.data(), size); + + spv_reflect::ShaderModule reflection(spv_data.size(), spv_data.data()); + if (reflection.GetResult() != SPV_REFLECT_RESULT_SUCCESS) { + std::cerr << "ERROR: could not process '" << input_spv_path << "' (is it a valid SPIR-V bytecode?)" << std::endl; + return EXIT_FAILURE; + } + + StreamWrite(std::cout, reflection); + std::cout << std::endl << std::endl; + } + + return 0; +} diff --git a/lib/All/SPIRV-Reflect/examples/main_io_variables.cpp b/lib/All/SPIRV-Reflect/examples/main_io_variables.cpp new file mode 100644 index 0000000..b5b8f98 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/main_io_variables.cpp @@ -0,0 +1,557 @@ +#include +#include + +#include "common.h" +#include "sample_spv.h" + +#if defined(SPIRV_REFLECT_HAS_VULKAN_H) +#include +// Returns the size in bytes of the provided VkFormat. +// As this is only intended for vertex attribute formats, not all VkFormats are +// supported. +static uint32_t FormatSize(VkFormat format) { + uint32_t result = 0; + switch (format) { + case VK_FORMAT_UNDEFINED: + result = 0; + break; + case VK_FORMAT_R4G4_UNORM_PACK8: + result = 1; + break; + case VK_FORMAT_R4G4B4A4_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_B4G4R4A4_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_B5G6R5_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_R5G5B5A1_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_B5G5R5A1_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_A1R5G5B5_UNORM_PACK16: + result = 2; + break; + case VK_FORMAT_R8_UNORM: + result = 1; + break; + case VK_FORMAT_R8_SNORM: + result = 1; + break; + case VK_FORMAT_R8_USCALED: + result = 1; + break; + case VK_FORMAT_R8_SSCALED: + result = 1; + break; + case VK_FORMAT_R8_UINT: + result = 1; + break; + case VK_FORMAT_R8_SINT: + result = 1; + break; + case VK_FORMAT_R8_SRGB: + result = 1; + break; + case VK_FORMAT_R8G8_UNORM: + result = 2; + break; + case VK_FORMAT_R8G8_SNORM: + result = 2; + break; + case VK_FORMAT_R8G8_USCALED: + result = 2; + break; + case VK_FORMAT_R8G8_SSCALED: + result = 2; + break; + case VK_FORMAT_R8G8_UINT: + result = 2; + break; + case VK_FORMAT_R8G8_SINT: + result = 2; + break; + case VK_FORMAT_R8G8_SRGB: + result = 2; + break; + case VK_FORMAT_R8G8B8_UNORM: + result = 3; + break; + case VK_FORMAT_R8G8B8_SNORM: + result = 3; + break; + case VK_FORMAT_R8G8B8_USCALED: + result = 3; + break; + case VK_FORMAT_R8G8B8_SSCALED: + result = 3; + break; + case VK_FORMAT_R8G8B8_UINT: + result = 3; + break; + case VK_FORMAT_R8G8B8_SINT: + result = 3; + break; + case VK_FORMAT_R8G8B8_SRGB: + result = 3; + break; + case VK_FORMAT_B8G8R8_UNORM: + result = 3; + break; + case VK_FORMAT_B8G8R8_SNORM: + result = 3; + break; + case VK_FORMAT_B8G8R8_USCALED: + result = 3; + break; + case VK_FORMAT_B8G8R8_SSCALED: + result = 3; + break; + case VK_FORMAT_B8G8R8_UINT: + result = 3; + break; + case VK_FORMAT_B8G8R8_SINT: + result = 3; + break; + case VK_FORMAT_B8G8R8_SRGB: + result = 3; + break; + case VK_FORMAT_R8G8B8A8_UNORM: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_SNORM: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_USCALED: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_SSCALED: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_UINT: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_SINT: + result = 4; + break; + case VK_FORMAT_R8G8B8A8_SRGB: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_UNORM: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_SNORM: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_USCALED: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_SSCALED: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_UINT: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_SINT: + result = 4; + break; + case VK_FORMAT_B8G8R8A8_SRGB: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_UNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_SNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_USCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_UINT_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_SINT_PACK32: + result = 4; + break; + case VK_FORMAT_A8B8G8R8_SRGB_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_UNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_SNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_USCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_UINT_PACK32: + result = 4; + break; + case VK_FORMAT_A2R10G10B10_SINT_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_SNORM_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_USCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_UINT_PACK32: + result = 4; + break; + case VK_FORMAT_A2B10G10R10_SINT_PACK32: + result = 4; + break; + case VK_FORMAT_R16_UNORM: + result = 2; + break; + case VK_FORMAT_R16_SNORM: + result = 2; + break; + case VK_FORMAT_R16_USCALED: + result = 2; + break; + case VK_FORMAT_R16_SSCALED: + result = 2; + break; + case VK_FORMAT_R16_UINT: + result = 2; + break; + case VK_FORMAT_R16_SINT: + result = 2; + break; + case VK_FORMAT_R16_SFLOAT: + result = 2; + break; + case VK_FORMAT_R16G16_UNORM: + result = 4; + break; + case VK_FORMAT_R16G16_SNORM: + result = 4; + break; + case VK_FORMAT_R16G16_USCALED: + result = 4; + break; + case VK_FORMAT_R16G16_SSCALED: + result = 4; + break; + case VK_FORMAT_R16G16_UINT: + result = 4; + break; + case VK_FORMAT_R16G16_SINT: + result = 4; + break; + case VK_FORMAT_R16G16_SFLOAT: + result = 4; + break; + case VK_FORMAT_R16G16B16_UNORM: + result = 6; + break; + case VK_FORMAT_R16G16B16_SNORM: + result = 6; + break; + case VK_FORMAT_R16G16B16_USCALED: + result = 6; + break; + case VK_FORMAT_R16G16B16_SSCALED: + result = 6; + break; + case VK_FORMAT_R16G16B16_UINT: + result = 6; + break; + case VK_FORMAT_R16G16B16_SINT: + result = 6; + break; + case VK_FORMAT_R16G16B16_SFLOAT: + result = 6; + break; + case VK_FORMAT_R16G16B16A16_UNORM: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_SNORM: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_USCALED: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_SSCALED: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_UINT: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_SINT: + result = 8; + break; + case VK_FORMAT_R16G16B16A16_SFLOAT: + result = 8; + break; + case VK_FORMAT_R32_UINT: + result = 4; + break; + case VK_FORMAT_R32_SINT: + result = 4; + break; + case VK_FORMAT_R32_SFLOAT: + result = 4; + break; + case VK_FORMAT_R32G32_UINT: + result = 8; + break; + case VK_FORMAT_R32G32_SINT: + result = 8; + break; + case VK_FORMAT_R32G32_SFLOAT: + result = 8; + break; + case VK_FORMAT_R32G32B32_UINT: + result = 12; + break; + case VK_FORMAT_R32G32B32_SINT: + result = 12; + break; + case VK_FORMAT_R32G32B32_SFLOAT: + result = 12; + break; + case VK_FORMAT_R32G32B32A32_UINT: + result = 16; + break; + case VK_FORMAT_R32G32B32A32_SINT: + result = 16; + break; + case VK_FORMAT_R32G32B32A32_SFLOAT: + result = 16; + break; + case VK_FORMAT_R64_UINT: + result = 8; + break; + case VK_FORMAT_R64_SINT: + result = 8; + break; + case VK_FORMAT_R64_SFLOAT: + result = 8; + break; + case VK_FORMAT_R64G64_UINT: + result = 16; + break; + case VK_FORMAT_R64G64_SINT: + result = 16; + break; + case VK_FORMAT_R64G64_SFLOAT: + result = 16; + break; + case VK_FORMAT_R64G64B64_UINT: + result = 24; + break; + case VK_FORMAT_R64G64B64_SINT: + result = 24; + break; + case VK_FORMAT_R64G64B64_SFLOAT: + result = 24; + break; + case VK_FORMAT_R64G64B64A64_UINT: + result = 32; + break; + case VK_FORMAT_R64G64B64A64_SINT: + result = 32; + break; + case VK_FORMAT_R64G64B64A64_SFLOAT: + result = 32; + break; + case VK_FORMAT_B10G11R11_UFLOAT_PACK32: + result = 4; + break; + case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: + result = 4; + break; + + default: + break; + } + return result; +} +#endif + +int main(int argn, char** argv) { + SpvReflectShaderModule module = {}; + SpvReflectResult result = spvReflectCreateShaderModule(sizeof(k_sample_spv), k_sample_spv, &module); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + uint32_t count = 0; + result = spvReflectEnumerateInputVariables(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + std::vector input_vars(count); + result = spvReflectEnumerateInputVariables(&module, &count, input_vars.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + count = 0; + result = spvReflectEnumerateOutputVariables(&module, &count, NULL); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + std::vector output_vars(count); + result = spvReflectEnumerateOutputVariables(&module, &count, output_vars.data()); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + +#if defined(SPIRV_REFLECT_HAS_VULKAN_H) + if (module.shader_stage == SPV_REFLECT_SHADER_STAGE_VERTEX_BIT) { + // Demonstrates how to generate all necessary data structures to populate + // a VkPipelineVertexInputStateCreateInfo structure, given the module's + // expected input variables. + // + // Simplifying assumptions: + // - All vertex input attributes are sourced from a single vertex buffer, + // bound to VB slot 0. + // - Each vertex's attribute are laid out in ascending order by location. + // - The format of each attribute matches its usage in the shader; + // float4 -> VK_FORMAT_R32G32B32A32_FLOAT, etc. No attribute compression + // is applied. + // - All attributes are provided per-vertex, not per-instance. + VkVertexInputBindingDescription binding_description = {}; + binding_description.binding = 0; + binding_description.stride = 0; // computed below + binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}; + std::vector attribute_descriptions; + attribute_descriptions.reserve(input_vars.size()); + for (size_t i_var = 0; i_var < input_vars.size(); ++i_var) { + const SpvReflectInterfaceVariable& refl_var = *(input_vars[i_var]); + // ignore built-in variables + if (refl_var.decoration_flags & SPV_REFLECT_DECORATION_BUILT_IN) { + continue; + } + VkVertexInputAttributeDescription attr_desc{}; + attr_desc.location = refl_var.location; + attr_desc.binding = binding_description.binding; + attr_desc.format = static_cast(refl_var.format); + attr_desc.offset = 0; // final offset computed below after sorting. + attribute_descriptions.push_back(attr_desc); + } + // Sort attributes by location + std::sort(std::begin(attribute_descriptions), std::end(attribute_descriptions), + [](const VkVertexInputAttributeDescription& a, const VkVertexInputAttributeDescription& b) { + return a.location < b.location; + }); + // Compute final offsets of each attribute, and total vertex stride. + for (auto& attribute : attribute_descriptions) { + uint32_t format_size = FormatSize(attribute.format); + attribute.offset = binding_description.stride; + binding_description.stride += format_size; + } + // Nothing further is done with attribute_descriptions or + // binding_description in this sample. A real application would probably + // derive this information from its mesh format(s); a similar mechanism + // could be used to ensure mesh/shader compatibility. + } +#endif + + // Log the interface variables to stdout + const char* t = " "; + const char* tt = " "; + + PrintModuleInfo(std::cout, module); + std::cout << "\n\n"; + + std::cout << "Input variables:" + << "\n"; + for (size_t index = 0; index < input_vars.size(); ++index) { + auto p_var = input_vars[index]; + + // input variables can also be retrieved directly from the module, by + // location (unless the location is (uint32_t)-1, as is the case with + // built-in inputs) + auto p_var2 = spvReflectGetInputVariableByLocation(&module, p_var->location, &result); + if (p_var->location == UINT32_MAX) { + assert(result == SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + assert(p_var2 == nullptr); + } else { + assert(result == SPV_REFLECT_RESULT_SUCCESS); + assert(p_var == p_var2); + } + (void)p_var2; + + // input variables can also be retrieved directly from the module, by + // semantic (if present) + p_var2 = spvReflectGetInputVariableBySemantic(&module, p_var->semantic, &result); + if (!p_var->semantic) { + assert(result == SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + assert(p_var2 == nullptr); + } else if (p_var->semantic[0] != '\0') { + assert(result == SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + assert(p_var2 == nullptr); + } else { + assert(result == SPV_REFLECT_RESULT_SUCCESS); + assert(p_var == p_var2); + } + (void)p_var2; + + std::cout << t << index << ":" + << "\n"; + PrintInterfaceVariable(std::cout, module.source_language, *p_var, tt); + std::cout << "\n\n"; + } + + std::cout << "Output variables:" + << "\n"; + for (size_t index = 0; index < output_vars.size(); ++index) { + auto p_var = output_vars[index]; + + // output variables can also be retrieved directly from the module, by + // location (unless the location is (uint32_t)-1, as is the case with + // built-in outputs) + auto p_var2 = spvReflectGetOutputVariableByLocation(&module, p_var->location, &result); + if (p_var->location == UINT32_MAX) { + assert(result == SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + assert(p_var2 == nullptr); + } else { + assert(result == SPV_REFLECT_RESULT_SUCCESS); + assert(p_var == p_var2); + } + (void)p_var2; + + // output variables can also be retrieved directly from the module, by + // semantic (if present) + p_var2 = spvReflectGetOutputVariableBySemantic(&module, p_var->semantic, &result); + if (!p_var->semantic) { + assert(result == SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + assert(p_var2 == nullptr); + } else if (p_var->semantic[0] != '\0') { + assert(result == SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + assert(p_var2 == nullptr); + } else { + assert(result == SPV_REFLECT_RESULT_SUCCESS); + assert(p_var == p_var2); + } + (void)p_var2; + + std::cout << t << index << ":" + << "\n"; + PrintInterfaceVariable(std::cout, module.source_language, *p_var, tt); + std::cout << "\n\n"; + } + + spvReflectDestroyShaderModule(&module); + + return 0; +} diff --git a/lib/All/SPIRV-Reflect/examples/sample.hlsl b/lib/All/SPIRV-Reflect/examples/sample.hlsl new file mode 100644 index 0000000..7617069 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/sample.hlsl @@ -0,0 +1,64 @@ +Texture2D MyTexture : register(t0, space0); +SamplerState MySampler : register(s1, space1); + +struct RGB { + float r; + float g; + float b; +}; + +struct UBO { + float4x4 XformMatrix; + float3 Scale; + RGB Rgb; + float t; + float2 uv; +}; + +ConstantBuffer MyConstants : register(b2, space2); + +struct Data { + float4 Element; +}; + +ConsumeStructuredBuffer MyBufferIn : register(u3, space2); +AppendStructuredBuffer MyBufferOut : register(u4, space2); + +struct PSInput { + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float3 Color : COLOR; + float Alpha : OPACITY; + float4 Scaling : SCALE; + float2 TexCoord0 : TEXCOORD0; + float2 TexCoord1 : TEXCOORD1; + float2 TexCoord2 : TEXCOORD2; +}; + +struct PSOutput { + float4 oColor0 : SV_TARGET0; + float4 oColor1 : SV_TARGET1; + float4 oColor2 : SV_TARGET2; + float4 oColor3 : SV_TARGET3; + float4 oColor4 : SV_TARGET4; + float4 oColor5 : SV_TARGET5; + float4 oColor6 : SV_TARGET6; + float4 oColor7 : SV_TARGET7; +}; + +PSOutput main(PSInput input) +{ + Data val = MyBufferIn[0]; + MyBufferOut[0] = val; + + PSOutput ret; + ret.oColor0 = mul(MyConstants.XformMatrix, input.Position); + ret.oColor1 = float4(input.Normal, 1) + float4(MyConstants.Scale, 0); + ret.oColor2 = float4(input.Color, 1); + ret.oColor3 = float4(MyTexture.Sample(MySampler, input.TexCoord0).xyz, input.Alpha); + ret.oColor4 = input.Scaling; + ret.oColor5 = float4(input.TexCoord0, 0, 0); + ret.oColor6 = float4(input.TexCoord1, 0, 0); + ret.oColor7 = float4(input.TexCoord2, 0, 0); + return ret; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/examples/sample.spv b/lib/All/SPIRV-Reflect/examples/sample.spv new file mode 100644 index 0000000..7a7fe01 Binary files /dev/null and b/lib/All/SPIRV-Reflect/examples/sample.spv differ diff --git a/lib/All/SPIRV-Reflect/examples/sample_spv.h b/lib/All/SPIRV-Reflect/examples/sample_spv.h new file mode 100644 index 0000000..6aeadb4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/examples/sample_spv.h @@ -0,0 +1,527 @@ +#ifndef SAMPLE_SPV_H +#define SAMPLE_SPV_H + +#include + +/* Source from sample.hlsl + +Texture2D MyTexture : register(t0, space0); +SamplerState MySampler : register(s1, space1); + +struct RGB { + float r; + float g; + float b; +}; + +struct UBO { + float4x4 XformMatrix; + float3 Scale; + RGB Rgb; + float t; + float2 uv; +}; + +ConstantBuffer MyConstants : register(b2, space2); + +struct Data { + float4 Element; +}; + +ConsumeStructuredBuffer MyBufferIn : register(u3, space2); +AppendStructuredBuffer MyBufferOut : register(u4, space2); + +struct PSInput { + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float3 Color : COLOR; + float Alpha : OPACITY; + float4 Scaling : SCALE; + float2 TexCoord0 : TEXCOORD0; + float2 TexCoord1 : TEXCOORD1; + float2 TexCoord2 : TEXCOORD2; +}; + +struct PSOutput { + float4 oColor0 : SV_TARGET0; + float4 oColor1 : SV_TARGET1; + float4 oColor2 : SV_TARGET2; + float4 oColor3 : SV_TARGET3; + float4 oColor4 : SV_TARGET4; + float4 oColor5 : SV_TARGET5; + float4 oColor6 : SV_TARGET6; + float4 oColor7 : SV_TARGET7; +}; + +PSOutput main(PSInput input) +{ + Data val = MyBufferIn[0]; + MyBufferOut[0] = val; + + PSOutput ret; + ret.oColor0 = mul(MyConstants.XformMatrix, input.Position); + ret.oColor1 = float4(input.Normal, 1) + float4(MyConstants.Scale, 0); + ret.oColor2 = float4(input.Color, 1); + ret.oColor3 = float4(MyTexture.Sample(MySampler, input.TexCoord0).xyz, input.Alpha); + ret.oColor4 = input.Scaling; + ret.oColor5 = float4(input.TexCoord0, 0, 0); + ret.oColor6 = float4(input.TexCoord1, 0, 0); + ret.oColor7 = float4(input.TexCoord2, 0, 0); + return ret; +} + +*/ + +// Imported from file 'sample.spv' +const uint32_t k_sample_spv[] = { +0x07230203,0x00010000,0x000d0004,0x00000106, +0x00000000,0x00020011,0x00000001,0x0006000b, +0x00000001,0x4c534c47,0x6474732e,0x3035342e, +0x00000000,0x0003000e,0x00000000,0x00000001, +0x0015000f,0x00000004,0x00000004,0x6e69616d, +0x00000000,0x00000086,0x0000008a,0x0000008d, +0x00000091,0x00000094,0x00000098,0x0000009b, +0x0000009e,0x000000a6,0x000000a9,0x000000ac, +0x000000af,0x000000b2,0x000000b5,0x000000b8, +0x000000bb,0x00030010,0x00000004,0x00000007, +0x00030003,0x00000005,0x000001f4,0x000a0004, +0x475f4c47,0x4c474f4f,0x70635f45,0x74735f70, +0x5f656c79,0x656e696c,0x7269645f,0x69746365, +0x00006576,0x00080004,0x475f4c47,0x4c474f4f, +0x6e695f45,0x64756c63,0x69645f65,0x74636572, +0x00657669,0x00040005,0x00000004,0x6e69616d, +0x00000000,0x00040005,0x00000014,0x61746144, +0x00000000,0x00050006,0x00000014,0x00000000, +0x6d656c45,0x00746e65,0x00050005,0x00000016, +0x7542794d,0x72656666,0x00006e49,0x00050006, +0x00000016,0x00000000,0x74616440,0x00000061, +0x00050005,0x00000018,0x7542794d,0x72656666, +0x00006e49,0x00050005,0x00000021,0x7542794d, +0x72656666,0x0074754f,0x00030005,0x0000002c, +0x00424752,0x00040006,0x0000002c,0x00000000, +0x00000072,0x00040006,0x0000002c,0x00000001, +0x00000067,0x00040006,0x0000002c,0x00000002, +0x00000062,0x00050005,0x0000002d,0x6f43794d, +0x6174736e,0x0073746e,0x00060006,0x0000002d, +0x00000000,0x726f6658,0x74614d6d,0x00786972, +0x00050006,0x0000002d,0x00000001,0x6c616353, +0x00000065,0x00040006,0x0000002d,0x00000002, +0x00626752,0x00040006,0x0000002d,0x00000003, +0x00000074,0x00040006,0x0000002d,0x00000004, +0x00007675,0x00050005,0x0000002f,0x6f43794d, +0x6174736e,0x0073746e,0x00050005,0x00000053, +0x6554794d,0x72757478,0x00000065,0x00050005, +0x00000057,0x6153794d,0x656c706d,0x00000072, +0x00060005,0x00000086,0x75706e69,0x6f502e74, +0x69746973,0x00006e6f,0x00060005,0x0000008a, +0x75706e69,0x6f4e2e74,0x6c616d72,0x00000000, +0x00050005,0x0000008d,0x75706e69,0x6f432e74, +0x00726f6c,0x00050005,0x00000091,0x75706e69, +0x6c412e74,0x00616870,0x00060005,0x00000094, +0x75706e69,0x63532e74,0x6e696c61,0x00000067, +0x00060005,0x00000098,0x75706e69,0x65542e74, +0x6f6f4378,0x00306472,0x00060005,0x0000009b, +0x75706e69,0x65542e74,0x6f6f4378,0x00316472, +0x00060005,0x0000009e,0x75706e69,0x65542e74, +0x6f6f4378,0x00326472,0x00090005,0x000000a6, +0x746e6540,0x6f507972,0x4f746e69,0x75707475, +0x436f2e74,0x726f6c6f,0x00000030,0x00090005, +0x000000a9,0x746e6540,0x6f507972,0x4f746e69, +0x75707475,0x436f2e74,0x726f6c6f,0x00000031, +0x00090005,0x000000ac,0x746e6540,0x6f507972, +0x4f746e69,0x75707475,0x436f2e74,0x726f6c6f, +0x00000032,0x00090005,0x000000af,0x746e6540, +0x6f507972,0x4f746e69,0x75707475,0x436f2e74, +0x726f6c6f,0x00000033,0x00090005,0x000000b2, +0x746e6540,0x6f507972,0x4f746e69,0x75707475, +0x436f2e74,0x726f6c6f,0x00000034,0x00090005, +0x000000b5,0x746e6540,0x6f507972,0x4f746e69, +0x75707475,0x436f2e74,0x726f6c6f,0x00000035, +0x00090005,0x000000b8,0x746e6540,0x6f507972, +0x4f746e69,0x75707475,0x436f2e74,0x726f6c6f, +0x00000036,0x00090005,0x000000bb,0x746e6540, +0x6f507972,0x4f746e69,0x75707475,0x436f2e74, +0x726f6c6f,0x00000037,0x00050048,0x00000014, +0x00000000,0x00000023,0x00000000,0x00040047, +0x00000015,0x00000006,0x00000010,0x00050048, +0x00000016,0x00000000,0x00000023,0x00000000, +0x00030047,0x00000016,0x00000003,0x00040047, +0x00000018,0x00000022,0x00000002,0x00040047, +0x00000018,0x00000021,0x00000003,0x00040047, +0x00000021,0x00000022,0x00000002,0x00040047, +0x00000021,0x00000021,0x00000004,0x00050048, +0x0000002c,0x00000000,0x00000023,0x00000000, +0x00050048,0x0000002c,0x00000001,0x00000023, +0x00000004,0x00050048,0x0000002c,0x00000002, +0x00000023,0x00000008,0x00040048,0x0000002d, +0x00000000,0x00000004,0x00050048,0x0000002d, +0x00000000,0x00000023,0x00000000,0x00050048, +0x0000002d,0x00000000,0x00000007,0x00000010, +0x00050048,0x0000002d,0x00000001,0x00000023, +0x00000040,0x00050048,0x0000002d,0x00000002, +0x00000023,0x00000050,0x00050048,0x0000002d, +0x00000003,0x00000023,0x00000060,0x00050048, +0x0000002d,0x00000004,0x00000023,0x00000064, +0x00030047,0x0000002d,0x00000002,0x00040047, +0x0000002f,0x00000022,0x00000002,0x00040047, +0x0000002f,0x00000021,0x00000002,0x00040047, +0x00000053,0x00000022,0x00000000,0x00040047, +0x00000053,0x00000021,0x00000000,0x00040047, +0x00000057,0x00000022,0x00000001,0x00040047, +0x00000057,0x00000021,0x00000001,0x00040047, +0x00000086,0x0000000b,0x0000000f,0x00040047, +0x0000008a,0x0000001e,0x00000000,0x00040047, +0x0000008d,0x0000001e,0x00000001,0x00040047, +0x00000091,0x0000001e,0x00000002,0x00040047, +0x00000094,0x0000001e,0x00000003,0x00040047, +0x00000098,0x0000001e,0x00000004,0x00040047, +0x0000009b,0x0000001e,0x00000005,0x00040047, +0x0000009e,0x0000001e,0x00000006,0x00040047, +0x000000a6,0x0000001e,0x00000000,0x00040047, +0x000000a9,0x0000001e,0x00000001,0x00040047, +0x000000ac,0x0000001e,0x00000002,0x00040047, +0x000000af,0x0000001e,0x00000003,0x00040047, +0x000000b2,0x0000001e,0x00000004,0x00040047, +0x000000b5,0x0000001e,0x00000005,0x00040047, +0x000000b8,0x0000001e,0x00000006,0x00040047, +0x000000bb,0x0000001e,0x00000007,0x00020013, +0x00000002,0x00030021,0x00000003,0x00000002, +0x00030016,0x00000006,0x00000020,0x00040017, +0x00000007,0x00000006,0x00000004,0x00040017, +0x00000008,0x00000006,0x00000003,0x00040017, +0x00000009,0x00000006,0x00000002,0x0003001e, +0x00000014,0x00000007,0x0003001d,0x00000015, +0x00000014,0x0003001e,0x00000016,0x00000015, +0x00040020,0x00000017,0x00000002,0x00000016, +0x0004003b,0x00000017,0x00000018,0x00000002, +0x00040015,0x00000019,0x00000020,0x00000001, +0x0004002b,0x00000019,0x0000001a,0x00000000, +0x00040020,0x0000001b,0x00000002,0x00000014, +0x0004003b,0x00000017,0x00000021,0x00000002, +0x00040020,0x00000025,0x00000002,0x00000007, +0x00040018,0x0000002b,0x00000007,0x00000004, +0x0005001e,0x0000002c,0x00000006,0x00000006, +0x00000006,0x0007001e,0x0000002d,0x0000002b, +0x00000008,0x0000002c,0x00000006,0x00000009, +0x00040020,0x0000002e,0x00000002,0x0000002d, +0x0004003b,0x0000002e,0x0000002f,0x00000002, +0x00040020,0x00000030,0x00000002,0x0000002b, +0x0004002b,0x00000019,0x00000035,0x00000001, +0x0004002b,0x00000006,0x00000039,0x3f800000, +0x00040020,0x0000003e,0x00000002,0x00000008, +0x0004002b,0x00000006,0x00000041,0x00000000, +0x00090019,0x00000051,0x00000006,0x00000001, +0x00000000,0x00000000,0x00000000,0x00000001, +0x00000000,0x00040020,0x00000052,0x00000000, +0x00000051,0x0004003b,0x00000052,0x00000053, +0x00000000,0x0002001a,0x00000055,0x00040020, +0x00000056,0x00000000,0x00000055,0x0004003b, +0x00000056,0x00000057,0x00000000,0x0003001b, +0x00000059,0x00000051,0x00040020,0x00000085, +0x00000001,0x00000007,0x0004003b,0x00000085, +0x00000086,0x00000001,0x00040020,0x00000089, +0x00000001,0x00000008,0x0004003b,0x00000089, +0x0000008a,0x00000001,0x0004003b,0x00000089, +0x0000008d,0x00000001,0x00040020,0x00000090, +0x00000001,0x00000006,0x0004003b,0x00000090, +0x00000091,0x00000001,0x0004003b,0x00000085, +0x00000094,0x00000001,0x00040020,0x00000097, +0x00000001,0x00000009,0x0004003b,0x00000097, +0x00000098,0x00000001,0x0004003b,0x00000097, +0x0000009b,0x00000001,0x0004003b,0x00000097, +0x0000009e,0x00000001,0x00040020,0x000000a5, +0x00000003,0x00000007,0x0004003b,0x000000a5, +0x000000a6,0x00000003,0x0004003b,0x000000a5, +0x000000a9,0x00000003,0x0004003b,0x000000a5, +0x000000ac,0x00000003,0x0004003b,0x000000a5, +0x000000af,0x00000003,0x0004003b,0x000000a5, +0x000000b2,0x00000003,0x0004003b,0x000000a5, +0x000000b5,0x00000003,0x0004003b,0x000000a5, +0x000000b8,0x00000003,0x0004003b,0x000000a5, +0x000000bb,0x00000003,0x00050036,0x00000002, +0x00000004,0x00000000,0x00000003,0x000200f8, +0x00000005,0x0004003d,0x00000007,0x00000087, +0x00000086,0x0004003d,0x00000008,0x0000008b, +0x0000008a,0x0004003d,0x00000008,0x0000008e, +0x0000008d,0x0004003d,0x00000006,0x00000092, +0x00000091,0x0004003d,0x00000007,0x00000095, +0x00000094,0x0004003d,0x00000009,0x00000099, +0x00000098,0x0004003d,0x00000009,0x0000009c, +0x0000009b,0x0004003d,0x00000009,0x0000009f, +0x0000009e,0x00060041,0x0000001b,0x000000c1, +0x00000018,0x0000001a,0x0000001a,0x0004003d, +0x00000014,0x000000c2,0x000000c1,0x00050051, +0x00000007,0x000000c3,0x000000c2,0x00000000, +0x00060041,0x0000001b,0x000000c6,0x00000021, +0x0000001a,0x0000001a,0x00050041,0x00000025, +0x000000c8,0x000000c6,0x0000001a,0x0003003e, +0x000000c8,0x000000c3,0x00050041,0x00000030, +0x000000cb,0x0000002f,0x0000001a,0x0004003d, +0x0000002b,0x000000cc,0x000000cb,0x00050090, +0x00000007,0x000000cd,0x00000087,0x000000cc, +0x00050051,0x00000006,0x000000d1,0x0000008b, +0x00000000,0x00050051,0x00000006,0x000000d2, +0x0000008b,0x00000001,0x00050051,0x00000006, +0x000000d3,0x0000008b,0x00000002,0x00070050, +0x00000007,0x000000d4,0x000000d1,0x000000d2, +0x000000d3,0x00000039,0x00050041,0x0000003e, +0x000000d5,0x0000002f,0x00000035,0x0004003d, +0x00000008,0x000000d6,0x000000d5,0x00050051, +0x00000006,0x000000d7,0x000000d6,0x00000000, +0x00050051,0x00000006,0x000000d8,0x000000d6, +0x00000001,0x00050051,0x00000006,0x000000d9, +0x000000d6,0x00000002,0x00070050,0x00000007, +0x000000da,0x000000d7,0x000000d8,0x000000d9, +0x00000041,0x00050081,0x00000007,0x000000db, +0x000000d4,0x000000da,0x00050051,0x00000006, +0x000000df,0x0000008e,0x00000000,0x00050051, +0x00000006,0x000000e0,0x0000008e,0x00000001, +0x00050051,0x00000006,0x000000e1,0x0000008e, +0x00000002,0x00070050,0x00000007,0x000000e2, +0x000000df,0x000000e0,0x000000e1,0x00000039, +0x0004003d,0x00000051,0x000000e4,0x00000053, +0x0004003d,0x00000055,0x000000e5,0x00000057, +0x00050056,0x00000059,0x000000e6,0x000000e4, +0x000000e5,0x00050057,0x00000007,0x000000e9, +0x000000e6,0x00000099,0x0008004f,0x00000008, +0x000000ea,0x000000e9,0x000000e9,0x00000000, +0x00000001,0x00000002,0x00050051,0x00000006, +0x000000ed,0x000000ea,0x00000000,0x00050051, +0x00000006,0x000000ee,0x000000ea,0x00000001, +0x00050051,0x00000006,0x000000ef,0x000000ea, +0x00000002,0x00070050,0x00000007,0x000000f0, +0x000000ed,0x000000ee,0x000000ef,0x00000092, +0x00050051,0x00000006,0x000000f7,0x00000099, +0x00000000,0x00050051,0x00000006,0x000000f8, +0x00000099,0x00000001,0x00070050,0x00000007, +0x000000f9,0x000000f7,0x000000f8,0x00000041, +0x00000041,0x00050051,0x00000006,0x000000fd, +0x0000009c,0x00000000,0x00050051,0x00000006, +0x000000fe,0x0000009c,0x00000001,0x00070050, +0x00000007,0x000000ff,0x000000fd,0x000000fe, +0x00000041,0x00000041,0x00050051,0x00000006, +0x00000103,0x0000009f,0x00000000,0x00050051, +0x00000006,0x00000104,0x0000009f,0x00000001, +0x00070050,0x00000007,0x00000105,0x00000103, +0x00000104,0x00000041,0x00000041,0x0003003e, +0x000000a6,0x000000cd,0x0003003e,0x000000a9, +0x000000db,0x0003003e,0x000000ac,0x000000e2, +0x0003003e,0x000000af,0x000000f0,0x0003003e, +0x000000b2,0x00000095,0x0003003e,0x000000b5, +0x000000f9,0x0003003e,0x000000b8,0x000000ff, +0x0003003e,0x000000bb,0x00000105,0x000100fd, +0x00010038 +}; + +/* SPIRV Disassembly + +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 2 +; Bound: 241 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" %117 %121 %124 %128 %131 %135 %138 %141 %149 %152 %155 %158 %161 %164 %167 %170 + OpExecutionMode %4 OriginUpperLeft + OpSource HLSL 500 + OpName %4 "main" + OpName %10 "PSInput" + OpMemberName %10 0 "Position" + OpMemberName %10 1 "Normal" + OpMemberName %10 2 "Color" + OpMemberName %10 3 "Alpha" + OpMemberName %10 4 "Scaling" + OpMemberName %10 5 "TexCoord0" + OpMemberName %10 6 "TexCoord1" + OpMemberName %10 7 "TexCoord2" + OpName %12 "PSOutput" + OpMemberName %12 0 "oColor0" + OpMemberName %12 1 "oColor1" + OpMemberName %12 2 "oColor2" + OpMemberName %12 3 "oColor3" + OpMemberName %12 4 "oColor4" + OpMemberName %12 5 "oColor5" + OpMemberName %12 6 "oColor6" + OpMemberName %12 7 "oColor7" + OpName %17 "Data" + OpMemberName %17 0 "Element" + OpName %20 "Data" + OpMemberName %20 0 "Element" + OpName %22 "MyBufferIn" + OpMemberName %22 0 "@data" + OpName %24 "MyBufferIn" + OpName %33 "MyBufferOut" + OpName %44 "RGB" + OpMemberName %44 0 "r" + OpMemberName %44 1 "g" + OpMemberName %44 2 "b" + OpName %45 "MyConstants" + OpMemberName %45 0 "XformMatrix" + OpMemberName %45 1 "Scale" + OpMemberName %45 2 "Rgb" + OpMemberName %45 3 "t" + OpMemberName %45 4 "uv" + OpName %47 "MyConstants" + OpName %117 "input.Position" + OpName %121 "input.Normal" + OpName %124 "input.Color" + OpName %128 "input.Alpha" + OpName %131 "input.Scaling" + OpName %135 "input.TexCoord0" + OpName %138 "input.TexCoord1" + OpName %141 "input.TexCoord2" + OpName %149 "@entryPointOutput.oColor0" + OpName %152 "@entryPointOutput.oColor1" + OpName %155 "@entryPointOutput.oColor2" + OpName %158 "@entryPointOutput.oColor3" + OpName %161 "@entryPointOutput.oColor4" + OpName %164 "@entryPointOutput.oColor5" + OpName %167 "@entryPointOutput.oColor6" + OpName %170 "@entryPointOutput.oColor7" + OpMemberDecorate %20 0 Offset 0 + OpDecorate %21 ArrayStride 16 + OpMemberDecorate %22 0 Offset 0 + OpDecorate %22 BufferBlock + OpDecorate %24 DescriptorSet 2 + OpDecorate %24 Binding 3 + OpDecorate %33 DescriptorSet 2 + OpDecorate %33 Binding 4 + OpMemberDecorate %44 0 Offset 0 + OpMemberDecorate %44 1 Offset 4 + OpMemberDecorate %44 2 Offset 8 + OpMemberDecorate %45 0 RowMajor + OpMemberDecorate %45 0 Offset 0 + OpMemberDecorate %45 0 MatrixStride 16 + OpMemberDecorate %45 1 Offset 64 + OpMemberDecorate %45 2 Offset 80 + OpMemberDecorate %45 3 Offset 96 + OpMemberDecorate %45 4 Offset 100 + OpDecorate %45 Block + OpDecorate %47 DescriptorSet 2 + OpDecorate %47 Binding 2 + OpDecorate %117 BuiltIn FragCoord + OpDecorate %121 Location 0 + OpDecorate %124 Location 1 + OpDecorate %128 Location 2 + OpDecorate %131 Location 3 + OpDecorate %135 Location 4 + OpDecorate %138 Location 5 + OpDecorate %141 Location 6 + OpDecorate %149 Location 0 + OpDecorate %152 Location 1 + OpDecorate %155 Location 2 + OpDecorate %158 Location 3 + OpDecorate %161 Location 4 + OpDecorate %164 Location 5 + OpDecorate %167 Location 6 + OpDecorate %170 Location 7 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeFloat 32 + %7 = OpTypeVector %6 4 + %8 = OpTypeVector %6 3 + %9 = OpTypeVector %6 2 + %10 = OpTypeStruct %7 %8 %8 %6 %7 %9 %9 %9 + %12 = OpTypeStruct %7 %7 %7 %7 %7 %7 %7 %7 + %17 = OpTypeStruct %7 + %20 = OpTypeStruct %7 + %21 = OpTypeRuntimeArray %20 + %22 = OpTypeStruct %21 + %23 = OpTypePointer Uniform %22 + %24 = OpVariable %23 Uniform + %25 = OpTypeInt 32 1 + %26 = OpConstant %25 0 + %27 = OpTypePointer Uniform %20 + %33 = OpVariable %23 Uniform + %37 = OpTypePointer Uniform %7 + %43 = OpTypeMatrix %7 4 + %44 = OpTypeStruct %6 %6 %6 + %45 = OpTypeStruct %43 %8 %44 %6 %9 + %46 = OpTypePointer Uniform %45 + %47 = OpVariable %46 Uniform + %48 = OpTypePointer Uniform %43 + %53 = OpConstant %25 1 + %57 = OpConstant %6 1 + %62 = OpTypePointer Uniform %8 + %65 = OpConstant %6 0 + %116 = OpTypePointer Input %7 + %117 = OpVariable %116 Input + %120 = OpTypePointer Input %8 + %121 = OpVariable %120 Input + %124 = OpVariable %120 Input + %127 = OpTypePointer Input %6 + %128 = OpVariable %127 Input + %131 = OpVariable %116 Input + %134 = OpTypePointer Input %9 + %135 = OpVariable %134 Input + %138 = OpVariable %134 Input + %141 = OpVariable %134 Input + %148 = OpTypePointer Output %7 + %149 = OpVariable %148 Output + %152 = OpVariable %148 Output + %155 = OpVariable %148 Output + %158 = OpVariable %148 Output + %161 = OpVariable %148 Output + %164 = OpVariable %148 Output + %167 = OpVariable %148 Output + %170 = OpVariable %148 Output + %4 = OpFunction %2 None %3 + %5 = OpLabel + %118 = OpLoad %7 %117 + %122 = OpLoad %8 %121 + %125 = OpLoad %8 %124 + %129 = OpLoad %6 %128 + %132 = OpLoad %7 %131 + %136 = OpLoad %9 %135 + %139 = OpLoad %9 %138 + %142 = OpLoad %9 %141 + %182 = OpAccessChain %27 %24 %26 %26 + %183 = OpLoad %20 %182 + %184 = OpCompositeExtract %7 %183 0 + %187 = OpAccessChain %27 %33 %26 %26 + %189 = OpAccessChain %37 %187 %26 + OpStore %189 %184 + %192 = OpAccessChain %48 %47 %26 + %193 = OpLoad %43 %192 + %194 = OpVectorTimesMatrix %7 %118 %193 + %198 = OpCompositeExtract %6 %122 0 + %199 = OpCompositeExtract %6 %122 1 + %200 = OpCompositeExtract %6 %122 2 + %201 = OpCompositeConstruct %7 %198 %199 %200 %57 + %202 = OpAccessChain %62 %47 %53 + %203 = OpLoad %8 %202 + %204 = OpCompositeExtract %6 %203 0 + %205 = OpCompositeExtract %6 %203 1 + %206 = OpCompositeExtract %6 %203 2 + %207 = OpCompositeConstruct %7 %204 %205 %206 %65 + %208 = OpFAdd %7 %201 %207 + %212 = OpCompositeExtract %6 %125 0 + %213 = OpCompositeExtract %6 %125 1 + %214 = OpCompositeExtract %6 %125 2 + %215 = OpCompositeConstruct %7 %212 %213 %214 %57 + %219 = OpCompositeConstruct %7 %65 %65 %65 %129 + %226 = OpCompositeExtract %6 %136 0 + %227 = OpCompositeExtract %6 %136 1 + %228 = OpCompositeConstruct %7 %226 %227 %65 %65 + %232 = OpCompositeExtract %6 %139 0 + %233 = OpCompositeExtract %6 %139 1 + %234 = OpCompositeConstruct %7 %232 %233 %65 %65 + %238 = OpCompositeExtract %6 %142 0 + %239 = OpCompositeExtract %6 %142 1 + %240 = OpCompositeConstruct %7 %238 %239 %65 %65 + OpStore %149 %194 + OpStore %152 %208 + OpStore %155 %215 + OpStore %158 %219 + OpStore %161 %132 + OpStore %164 %228 + OpStore %167 %234 + OpStore %170 %240 + OpReturn + OpFunctionEnd + +*/ + +#endif // SAMPLE_SPV_H diff --git a/lib/All/SPIRV-Reflect/include/spirv/unified1/spirv.h b/lib/All/SPIRV-Reflect/include/spirv/unified1/spirv.h new file mode 100644 index 0000000..681082b --- /dev/null +++ b/lib/All/SPIRV-Reflect/include/spirv/unified1/spirv.h @@ -0,0 +1,9518 @@ +/* +** Copyright: 2014-2024 The Khronos Group Inc. +** License: MIT +** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +** KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +** SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +** https://www.khronos.org/registry/ +*/ + +/* +** This header is automatically generated by the same tool that creates +** the Binary Section of the SPIR-V specification. +*/ + +/* +** Enumeration tokens for SPIR-V, in various styles: +** C, C++, C++11, JSON, Lua, Python, C#, D, Beef +** +** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL +** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL +** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL +** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL +** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +** - C# will use enum classes in the Specification class located in the "Spv" namespace, +** e.g.: Spv.Specification.SourceLanguage.GLSL +** - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL +** - Beef will use enum classes in the Specification class located in the "Spv" namespace, +** e.g.: Spv.Specification.SourceLanguage.GLSL +** +** Some tokens act like mask values, which can be OR'd together, +** while others are mutually exclusive. The mask-like ones have +** "Mask" in their name, and a parallel enum that has the shift +** amount (1 << x) for each corresponding enumerant. +*/ + +#ifndef spirv_H +#define spirv_H + +typedef unsigned int SpvId; + +#define SPV_VERSION 0x10600 +#define SPV_REVISION 1 + +static const unsigned int SpvMagicNumber = 0x07230203; +static const unsigned int SpvVersion = 0x00010600; +static const unsigned int SpvRevision = 1; +static const unsigned int SpvOpCodeMask = 0xffff; +static const unsigned int SpvWordCountShift = 16; + +typedef enum SpvSourceLanguage_ { + SpvSourceLanguageUnknown = 0, + SpvSourceLanguageESSL = 1, + SpvSourceLanguageGLSL = 2, + SpvSourceLanguageOpenCL_C = 3, + SpvSourceLanguageOpenCL_CPP = 4, + SpvSourceLanguageHLSL = 5, + SpvSourceLanguageCPP_for_OpenCL = 6, + SpvSourceLanguageSYCL = 7, + SpvSourceLanguageHERO_C = 8, + SpvSourceLanguageNZSL = 9, + SpvSourceLanguageWGSL = 10, + SpvSourceLanguageSlang = 11, + SpvSourceLanguageZig = 12, + SpvSourceLanguageRust = 13, + SpvSourceLanguageMax = 0x7fffffff, +} SpvSourceLanguage; + +typedef enum SpvExecutionModel_ { + SpvExecutionModelVertex = 0, + SpvExecutionModelTessellationControl = 1, + SpvExecutionModelTessellationEvaluation = 2, + SpvExecutionModelGeometry = 3, + SpvExecutionModelFragment = 4, + SpvExecutionModelGLCompute = 5, + SpvExecutionModelKernel = 6, + SpvExecutionModelTaskNV = 5267, + SpvExecutionModelMeshNV = 5268, + SpvExecutionModelRayGenerationKHR = 5313, + SpvExecutionModelRayGenerationNV = 5313, + SpvExecutionModelIntersectionKHR = 5314, + SpvExecutionModelIntersectionNV = 5314, + SpvExecutionModelAnyHitKHR = 5315, + SpvExecutionModelAnyHitNV = 5315, + SpvExecutionModelClosestHitKHR = 5316, + SpvExecutionModelClosestHitNV = 5316, + SpvExecutionModelMissKHR = 5317, + SpvExecutionModelMissNV = 5317, + SpvExecutionModelCallableKHR = 5318, + SpvExecutionModelCallableNV = 5318, + SpvExecutionModelTaskEXT = 5364, + SpvExecutionModelMeshEXT = 5365, + SpvExecutionModelMax = 0x7fffffff, +} SpvExecutionModel; + +typedef enum SpvAddressingModel_ { + SpvAddressingModelLogical = 0, + SpvAddressingModelPhysical32 = 1, + SpvAddressingModelPhysical64 = 2, + SpvAddressingModelPhysicalStorageBuffer64 = 5348, + SpvAddressingModelPhysicalStorageBuffer64EXT = 5348, + SpvAddressingModelMax = 0x7fffffff, +} SpvAddressingModel; + +typedef enum SpvMemoryModel_ { + SpvMemoryModelSimple = 0, + SpvMemoryModelGLSL450 = 1, + SpvMemoryModelOpenCL = 2, + SpvMemoryModelVulkan = 3, + SpvMemoryModelVulkanKHR = 3, + SpvMemoryModelMax = 0x7fffffff, +} SpvMemoryModel; + +typedef enum SpvExecutionMode_ { + SpvExecutionModeInvocations = 0, + SpvExecutionModeSpacingEqual = 1, + SpvExecutionModeSpacingFractionalEven = 2, + SpvExecutionModeSpacingFractionalOdd = 3, + SpvExecutionModeVertexOrderCw = 4, + SpvExecutionModeVertexOrderCcw = 5, + SpvExecutionModePixelCenterInteger = 6, + SpvExecutionModeOriginUpperLeft = 7, + SpvExecutionModeOriginLowerLeft = 8, + SpvExecutionModeEarlyFragmentTests = 9, + SpvExecutionModePointMode = 10, + SpvExecutionModeXfb = 11, + SpvExecutionModeDepthReplacing = 12, + SpvExecutionModeDepthGreater = 14, + SpvExecutionModeDepthLess = 15, + SpvExecutionModeDepthUnchanged = 16, + SpvExecutionModeLocalSize = 17, + SpvExecutionModeLocalSizeHint = 18, + SpvExecutionModeInputPoints = 19, + SpvExecutionModeInputLines = 20, + SpvExecutionModeInputLinesAdjacency = 21, + SpvExecutionModeTriangles = 22, + SpvExecutionModeInputTrianglesAdjacency = 23, + SpvExecutionModeQuads = 24, + SpvExecutionModeIsolines = 25, + SpvExecutionModeOutputVertices = 26, + SpvExecutionModeOutputPoints = 27, + SpvExecutionModeOutputLineStrip = 28, + SpvExecutionModeOutputTriangleStrip = 29, + SpvExecutionModeVecTypeHint = 30, + SpvExecutionModeContractionOff = 31, + SpvExecutionModeInitializer = 33, + SpvExecutionModeFinalizer = 34, + SpvExecutionModeSubgroupSize = 35, + SpvExecutionModeSubgroupsPerWorkgroup = 36, + SpvExecutionModeSubgroupsPerWorkgroupId = 37, + SpvExecutionModeLocalSizeId = 38, + SpvExecutionModeLocalSizeHintId = 39, + SpvExecutionModeNonCoherentColorAttachmentReadEXT = 4169, + SpvExecutionModeNonCoherentDepthAttachmentReadEXT = 4170, + SpvExecutionModeNonCoherentStencilAttachmentReadEXT = 4171, + SpvExecutionModeSubgroupUniformControlFlowKHR = 4421, + SpvExecutionModePostDepthCoverage = 4446, + SpvExecutionModeDenormPreserve = 4459, + SpvExecutionModeDenormFlushToZero = 4460, + SpvExecutionModeSignedZeroInfNanPreserve = 4461, + SpvExecutionModeRoundingModeRTE = 4462, + SpvExecutionModeRoundingModeRTZ = 4463, + SpvExecutionModeNonCoherentTileAttachmentReadQCOM = 4489, + SpvExecutionModeTileShadingRateQCOM = 4490, + SpvExecutionModeEarlyAndLateFragmentTestsAMD = 5017, + SpvExecutionModeStencilRefReplacingEXT = 5027, + SpvExecutionModeCoalescingAMDX = 5069, + SpvExecutionModeIsApiEntryAMDX = 5070, + SpvExecutionModeMaxNodeRecursionAMDX = 5071, + SpvExecutionModeStaticNumWorkgroupsAMDX = 5072, + SpvExecutionModeShaderIndexAMDX = 5073, + SpvExecutionModeMaxNumWorkgroupsAMDX = 5077, + SpvExecutionModeStencilRefUnchangedFrontAMD = 5079, + SpvExecutionModeStencilRefGreaterFrontAMD = 5080, + SpvExecutionModeStencilRefLessFrontAMD = 5081, + SpvExecutionModeStencilRefUnchangedBackAMD = 5082, + SpvExecutionModeStencilRefGreaterBackAMD = 5083, + SpvExecutionModeStencilRefLessBackAMD = 5084, + SpvExecutionModeQuadDerivativesKHR = 5088, + SpvExecutionModeRequireFullQuadsKHR = 5089, + SpvExecutionModeSharesInputWithAMDX = 5102, + SpvExecutionModeOutputLinesEXT = 5269, + SpvExecutionModeOutputLinesNV = 5269, + SpvExecutionModeOutputPrimitivesEXT = 5270, + SpvExecutionModeOutputPrimitivesNV = 5270, + SpvExecutionModeDerivativeGroupQuadsKHR = 5289, + SpvExecutionModeDerivativeGroupQuadsNV = 5289, + SpvExecutionModeDerivativeGroupLinearKHR = 5290, + SpvExecutionModeDerivativeGroupLinearNV = 5290, + SpvExecutionModeOutputTrianglesEXT = 5298, + SpvExecutionModeOutputTrianglesNV = 5298, + SpvExecutionModePixelInterlockOrderedEXT = 5366, + SpvExecutionModePixelInterlockUnorderedEXT = 5367, + SpvExecutionModeSampleInterlockOrderedEXT = 5368, + SpvExecutionModeSampleInterlockUnorderedEXT = 5369, + SpvExecutionModeShadingRateInterlockOrderedEXT = 5370, + SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371, + SpvExecutionModeSharedLocalMemorySizeINTEL = 5618, + SpvExecutionModeRoundingModeRTPINTEL = 5620, + SpvExecutionModeRoundingModeRTNINTEL = 5621, + SpvExecutionModeFloatingPointModeALTINTEL = 5622, + SpvExecutionModeFloatingPointModeIEEEINTEL = 5623, + SpvExecutionModeMaxWorkgroupSizeINTEL = 5893, + SpvExecutionModeMaxWorkDimINTEL = 5894, + SpvExecutionModeNoGlobalOffsetINTEL = 5895, + SpvExecutionModeNumSIMDWorkitemsINTEL = 5896, + SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, + SpvExecutionModeMaximallyReconvergesKHR = 6023, + SpvExecutionModeFPFastMathDefault = 6028, + SpvExecutionModeStreamingInterfaceINTEL = 6154, + SpvExecutionModeRegisterMapInterfaceINTEL = 6160, + SpvExecutionModeNamedBarrierCountINTEL = 6417, + SpvExecutionModeMaximumRegistersINTEL = 6461, + SpvExecutionModeMaximumRegistersIdINTEL = 6462, + SpvExecutionModeNamedMaximumRegistersINTEL = 6463, + SpvExecutionModeMax = 0x7fffffff, +} SpvExecutionMode; + +typedef enum SpvStorageClass_ { + SpvStorageClassUniformConstant = 0, + SpvStorageClassInput = 1, + SpvStorageClassUniform = 2, + SpvStorageClassOutput = 3, + SpvStorageClassWorkgroup = 4, + SpvStorageClassCrossWorkgroup = 5, + SpvStorageClassPrivate = 6, + SpvStorageClassFunction = 7, + SpvStorageClassGeneric = 8, + SpvStorageClassPushConstant = 9, + SpvStorageClassAtomicCounter = 10, + SpvStorageClassImage = 11, + SpvStorageClassStorageBuffer = 12, + SpvStorageClassTileImageEXT = 4172, + SpvStorageClassTileAttachmentQCOM = 4491, + SpvStorageClassNodePayloadAMDX = 5068, + SpvStorageClassCallableDataKHR = 5328, + SpvStorageClassCallableDataNV = 5328, + SpvStorageClassIncomingCallableDataKHR = 5329, + SpvStorageClassIncomingCallableDataNV = 5329, + SpvStorageClassRayPayloadKHR = 5338, + SpvStorageClassRayPayloadNV = 5338, + SpvStorageClassHitAttributeKHR = 5339, + SpvStorageClassHitAttributeNV = 5339, + SpvStorageClassIncomingRayPayloadKHR = 5342, + SpvStorageClassIncomingRayPayloadNV = 5342, + SpvStorageClassShaderRecordBufferKHR = 5343, + SpvStorageClassShaderRecordBufferNV = 5343, + SpvStorageClassPhysicalStorageBuffer = 5349, + SpvStorageClassPhysicalStorageBufferEXT = 5349, + SpvStorageClassHitObjectAttributeNV = 5385, + SpvStorageClassTaskPayloadWorkgroupEXT = 5402, + SpvStorageClassCodeSectionINTEL = 5605, + SpvStorageClassDeviceOnlyINTEL = 5936, + SpvStorageClassHostOnlyINTEL = 5937, + SpvStorageClassMax = 0x7fffffff, +} SpvStorageClass; + +typedef enum SpvDim_ { + SpvDim1D = 0, + SpvDim2D = 1, + SpvDim3D = 2, + SpvDimCube = 3, + SpvDimRect = 4, + SpvDimBuffer = 5, + SpvDimSubpassData = 6, + SpvDimTileImageDataEXT = 4173, + SpvDimMax = 0x7fffffff, +} SpvDim; + +typedef enum SpvSamplerAddressingMode_ { + SpvSamplerAddressingModeNone = 0, + SpvSamplerAddressingModeClampToEdge = 1, + SpvSamplerAddressingModeClamp = 2, + SpvSamplerAddressingModeRepeat = 3, + SpvSamplerAddressingModeRepeatMirrored = 4, + SpvSamplerAddressingModeMax = 0x7fffffff, +} SpvSamplerAddressingMode; + +typedef enum SpvSamplerFilterMode_ { + SpvSamplerFilterModeNearest = 0, + SpvSamplerFilterModeLinear = 1, + SpvSamplerFilterModeMax = 0x7fffffff, +} SpvSamplerFilterMode; + +typedef enum SpvImageFormat_ { + SpvImageFormatUnknown = 0, + SpvImageFormatRgba32f = 1, + SpvImageFormatRgba16f = 2, + SpvImageFormatR32f = 3, + SpvImageFormatRgba8 = 4, + SpvImageFormatRgba8Snorm = 5, + SpvImageFormatRg32f = 6, + SpvImageFormatRg16f = 7, + SpvImageFormatR11fG11fB10f = 8, + SpvImageFormatR16f = 9, + SpvImageFormatRgba16 = 10, + SpvImageFormatRgb10A2 = 11, + SpvImageFormatRg16 = 12, + SpvImageFormatRg8 = 13, + SpvImageFormatR16 = 14, + SpvImageFormatR8 = 15, + SpvImageFormatRgba16Snorm = 16, + SpvImageFormatRg16Snorm = 17, + SpvImageFormatRg8Snorm = 18, + SpvImageFormatR16Snorm = 19, + SpvImageFormatR8Snorm = 20, + SpvImageFormatRgba32i = 21, + SpvImageFormatRgba16i = 22, + SpvImageFormatRgba8i = 23, + SpvImageFormatR32i = 24, + SpvImageFormatRg32i = 25, + SpvImageFormatRg16i = 26, + SpvImageFormatRg8i = 27, + SpvImageFormatR16i = 28, + SpvImageFormatR8i = 29, + SpvImageFormatRgba32ui = 30, + SpvImageFormatRgba16ui = 31, + SpvImageFormatRgba8ui = 32, + SpvImageFormatR32ui = 33, + SpvImageFormatRgb10a2ui = 34, + SpvImageFormatRg32ui = 35, + SpvImageFormatRg16ui = 36, + SpvImageFormatRg8ui = 37, + SpvImageFormatR16ui = 38, + SpvImageFormatR8ui = 39, + SpvImageFormatR64ui = 40, + SpvImageFormatR64i = 41, + SpvImageFormatMax = 0x7fffffff, +} SpvImageFormat; + +typedef enum SpvImageChannelOrder_ { + SpvImageChannelOrderR = 0, + SpvImageChannelOrderA = 1, + SpvImageChannelOrderRG = 2, + SpvImageChannelOrderRA = 3, + SpvImageChannelOrderRGB = 4, + SpvImageChannelOrderRGBA = 5, + SpvImageChannelOrderBGRA = 6, + SpvImageChannelOrderARGB = 7, + SpvImageChannelOrderIntensity = 8, + SpvImageChannelOrderLuminance = 9, + SpvImageChannelOrderRx = 10, + SpvImageChannelOrderRGx = 11, + SpvImageChannelOrderRGBx = 12, + SpvImageChannelOrderDepth = 13, + SpvImageChannelOrderDepthStencil = 14, + SpvImageChannelOrdersRGB = 15, + SpvImageChannelOrdersRGBx = 16, + SpvImageChannelOrdersRGBA = 17, + SpvImageChannelOrdersBGRA = 18, + SpvImageChannelOrderABGR = 19, + SpvImageChannelOrderMax = 0x7fffffff, +} SpvImageChannelOrder; + +typedef enum SpvImageChannelDataType_ { + SpvImageChannelDataTypeSnormInt8 = 0, + SpvImageChannelDataTypeSnormInt16 = 1, + SpvImageChannelDataTypeUnormInt8 = 2, + SpvImageChannelDataTypeUnormInt16 = 3, + SpvImageChannelDataTypeUnormShort565 = 4, + SpvImageChannelDataTypeUnormShort555 = 5, + SpvImageChannelDataTypeUnormInt101010 = 6, + SpvImageChannelDataTypeSignedInt8 = 7, + SpvImageChannelDataTypeSignedInt16 = 8, + SpvImageChannelDataTypeSignedInt32 = 9, + SpvImageChannelDataTypeUnsignedInt8 = 10, + SpvImageChannelDataTypeUnsignedInt16 = 11, + SpvImageChannelDataTypeUnsignedInt32 = 12, + SpvImageChannelDataTypeHalfFloat = 13, + SpvImageChannelDataTypeFloat = 14, + SpvImageChannelDataTypeUnormInt24 = 15, + SpvImageChannelDataTypeUnormInt101010_2 = 16, + SpvImageChannelDataTypeUnormInt10X6EXT = 17, + SpvImageChannelDataTypeUnsignedIntRaw10EXT = 19, + SpvImageChannelDataTypeUnsignedIntRaw12EXT = 20, + SpvImageChannelDataTypeUnormInt2_101010EXT = 21, + SpvImageChannelDataTypeUnsignedInt10X6EXT = 22, + SpvImageChannelDataTypeUnsignedInt12X4EXT = 23, + SpvImageChannelDataTypeUnsignedInt14X2EXT = 24, + SpvImageChannelDataTypeUnormInt12X4EXT = 25, + SpvImageChannelDataTypeUnormInt14X2EXT = 26, + SpvImageChannelDataTypeMax = 0x7fffffff, +} SpvImageChannelDataType; + +typedef enum SpvImageOperandsShift_ { + SpvImageOperandsBiasShift = 0, + SpvImageOperandsLodShift = 1, + SpvImageOperandsGradShift = 2, + SpvImageOperandsConstOffsetShift = 3, + SpvImageOperandsOffsetShift = 4, + SpvImageOperandsConstOffsetsShift = 5, + SpvImageOperandsSampleShift = 6, + SpvImageOperandsMinLodShift = 7, + SpvImageOperandsMakeTexelAvailableShift = 8, + SpvImageOperandsMakeTexelAvailableKHRShift = 8, + SpvImageOperandsMakeTexelVisibleShift = 9, + SpvImageOperandsMakeTexelVisibleKHRShift = 9, + SpvImageOperandsNonPrivateTexelShift = 10, + SpvImageOperandsNonPrivateTexelKHRShift = 10, + SpvImageOperandsVolatileTexelShift = 11, + SpvImageOperandsVolatileTexelKHRShift = 11, + SpvImageOperandsSignExtendShift = 12, + SpvImageOperandsZeroExtendShift = 13, + SpvImageOperandsNontemporalShift = 14, + SpvImageOperandsOffsetsShift = 16, + SpvImageOperandsMax = 0x7fffffff, +} SpvImageOperandsShift; + +typedef enum SpvImageOperandsMask_ { + SpvImageOperandsMaskNone = 0, + SpvImageOperandsBiasMask = 0x00000001, + SpvImageOperandsLodMask = 0x00000002, + SpvImageOperandsGradMask = 0x00000004, + SpvImageOperandsConstOffsetMask = 0x00000008, + SpvImageOperandsOffsetMask = 0x00000010, + SpvImageOperandsConstOffsetsMask = 0x00000020, + SpvImageOperandsSampleMask = 0x00000040, + SpvImageOperandsMinLodMask = 0x00000080, + SpvImageOperandsMakeTexelAvailableMask = 0x00000100, + SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + SpvImageOperandsMakeTexelVisibleMask = 0x00000200, + SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + SpvImageOperandsNonPrivateTexelMask = 0x00000400, + SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400, + SpvImageOperandsVolatileTexelMask = 0x00000800, + SpvImageOperandsVolatileTexelKHRMask = 0x00000800, + SpvImageOperandsSignExtendMask = 0x00001000, + SpvImageOperandsZeroExtendMask = 0x00002000, + SpvImageOperandsNontemporalMask = 0x00004000, + SpvImageOperandsOffsetsMask = 0x00010000, +} SpvImageOperandsMask; + +typedef enum SpvFPFastMathModeShift_ { + SpvFPFastMathModeNotNaNShift = 0, + SpvFPFastMathModeNotInfShift = 1, + SpvFPFastMathModeNSZShift = 2, + SpvFPFastMathModeAllowRecipShift = 3, + SpvFPFastMathModeFastShift = 4, + SpvFPFastMathModeAllowContractShift = 16, + SpvFPFastMathModeAllowContractFastINTELShift = 16, + SpvFPFastMathModeAllowReassocShift = 17, + SpvFPFastMathModeAllowReassocINTELShift = 17, + SpvFPFastMathModeAllowTransformShift = 18, + SpvFPFastMathModeMax = 0x7fffffff, +} SpvFPFastMathModeShift; + +typedef enum SpvFPFastMathModeMask_ { + SpvFPFastMathModeMaskNone = 0, + SpvFPFastMathModeNotNaNMask = 0x00000001, + SpvFPFastMathModeNotInfMask = 0x00000002, + SpvFPFastMathModeNSZMask = 0x00000004, + SpvFPFastMathModeAllowRecipMask = 0x00000008, + SpvFPFastMathModeFastMask = 0x00000010, + SpvFPFastMathModeAllowContractMask = 0x00010000, + SpvFPFastMathModeAllowContractFastINTELMask = 0x00010000, + SpvFPFastMathModeAllowReassocMask = 0x00020000, + SpvFPFastMathModeAllowReassocINTELMask = 0x00020000, + SpvFPFastMathModeAllowTransformMask = 0x00040000, +} SpvFPFastMathModeMask; + +typedef enum SpvFPRoundingMode_ { + SpvFPRoundingModeRTE = 0, + SpvFPRoundingModeRTZ = 1, + SpvFPRoundingModeRTP = 2, + SpvFPRoundingModeRTN = 3, + SpvFPRoundingModeMax = 0x7fffffff, +} SpvFPRoundingMode; + +typedef enum SpvLinkageType_ { + SpvLinkageTypeExport = 0, + SpvLinkageTypeImport = 1, + SpvLinkageTypeLinkOnceODR = 2, + SpvLinkageTypeMax = 0x7fffffff, +} SpvLinkageType; + +typedef enum SpvAccessQualifier_ { + SpvAccessQualifierReadOnly = 0, + SpvAccessQualifierWriteOnly = 1, + SpvAccessQualifierReadWrite = 2, + SpvAccessQualifierMax = 0x7fffffff, +} SpvAccessQualifier; + +typedef enum SpvFunctionParameterAttribute_ { + SpvFunctionParameterAttributeZext = 0, + SpvFunctionParameterAttributeSext = 1, + SpvFunctionParameterAttributeByVal = 2, + SpvFunctionParameterAttributeSret = 3, + SpvFunctionParameterAttributeNoAlias = 4, + SpvFunctionParameterAttributeNoCapture = 5, + SpvFunctionParameterAttributeNoWrite = 6, + SpvFunctionParameterAttributeNoReadWrite = 7, + SpvFunctionParameterAttributeRuntimeAlignedINTEL = 5940, + SpvFunctionParameterAttributeMax = 0x7fffffff, +} SpvFunctionParameterAttribute; + +typedef enum SpvDecoration_ { + SpvDecorationRelaxedPrecision = 0, + SpvDecorationSpecId = 1, + SpvDecorationBlock = 2, + SpvDecorationBufferBlock = 3, + SpvDecorationRowMajor = 4, + SpvDecorationColMajor = 5, + SpvDecorationArrayStride = 6, + SpvDecorationMatrixStride = 7, + SpvDecorationGLSLShared = 8, + SpvDecorationGLSLPacked = 9, + SpvDecorationCPacked = 10, + SpvDecorationBuiltIn = 11, + SpvDecorationNoPerspective = 13, + SpvDecorationFlat = 14, + SpvDecorationPatch = 15, + SpvDecorationCentroid = 16, + SpvDecorationSample = 17, + SpvDecorationInvariant = 18, + SpvDecorationRestrict = 19, + SpvDecorationAliased = 20, + SpvDecorationVolatile = 21, + SpvDecorationConstant = 22, + SpvDecorationCoherent = 23, + SpvDecorationNonWritable = 24, + SpvDecorationNonReadable = 25, + SpvDecorationUniform = 26, + SpvDecorationUniformId = 27, + SpvDecorationSaturatedConversion = 28, + SpvDecorationStream = 29, + SpvDecorationLocation = 30, + SpvDecorationComponent = 31, + SpvDecorationIndex = 32, + SpvDecorationBinding = 33, + SpvDecorationDescriptorSet = 34, + SpvDecorationOffset = 35, + SpvDecorationXfbBuffer = 36, + SpvDecorationXfbStride = 37, + SpvDecorationFuncParamAttr = 38, + SpvDecorationFPRoundingMode = 39, + SpvDecorationFPFastMathMode = 40, + SpvDecorationLinkageAttributes = 41, + SpvDecorationNoContraction = 42, + SpvDecorationInputAttachmentIndex = 43, + SpvDecorationAlignment = 44, + SpvDecorationMaxByteOffset = 45, + SpvDecorationAlignmentId = 46, + SpvDecorationMaxByteOffsetId = 47, + SpvDecorationSaturatedToLargestFloat8NormalConversionEXT = 4216, + SpvDecorationNoSignedWrap = 4469, + SpvDecorationNoUnsignedWrap = 4470, + SpvDecorationWeightTextureQCOM = 4487, + SpvDecorationBlockMatchTextureQCOM = 4488, + SpvDecorationBlockMatchSamplerQCOM = 4499, + SpvDecorationExplicitInterpAMD = 4999, + SpvDecorationNodeSharesPayloadLimitsWithAMDX = 5019, + SpvDecorationNodeMaxPayloadsAMDX = 5020, + SpvDecorationTrackFinishWritingAMDX = 5078, + SpvDecorationPayloadNodeNameAMDX = 5091, + SpvDecorationPayloadNodeBaseIndexAMDX = 5098, + SpvDecorationPayloadNodeSparseArrayAMDX = 5099, + SpvDecorationPayloadNodeArraySizeAMDX = 5100, + SpvDecorationPayloadDispatchIndirectAMDX = 5105, + SpvDecorationOverrideCoverageNV = 5248, + SpvDecorationPassthroughNV = 5250, + SpvDecorationViewportRelativeNV = 5252, + SpvDecorationSecondaryViewportRelativeNV = 5256, + SpvDecorationPerPrimitiveEXT = 5271, + SpvDecorationPerPrimitiveNV = 5271, + SpvDecorationPerViewNV = 5272, + SpvDecorationPerTaskNV = 5273, + SpvDecorationPerVertexKHR = 5285, + SpvDecorationPerVertexNV = 5285, + SpvDecorationNonUniform = 5300, + SpvDecorationNonUniformEXT = 5300, + SpvDecorationRestrictPointer = 5355, + SpvDecorationRestrictPointerEXT = 5355, + SpvDecorationAliasedPointer = 5356, + SpvDecorationAliasedPointerEXT = 5356, + SpvDecorationHitObjectShaderRecordBufferNV = 5386, + SpvDecorationBindlessSamplerNV = 5398, + SpvDecorationBindlessImageNV = 5399, + SpvDecorationBoundSamplerNV = 5400, + SpvDecorationBoundImageNV = 5401, + SpvDecorationSIMTCallINTEL = 5599, + SpvDecorationReferencedIndirectlyINTEL = 5602, + SpvDecorationClobberINTEL = 5607, + SpvDecorationSideEffectsINTEL = 5608, + SpvDecorationVectorComputeVariableINTEL = 5624, + SpvDecorationFuncParamIOKindINTEL = 5625, + SpvDecorationVectorComputeFunctionINTEL = 5626, + SpvDecorationStackCallINTEL = 5627, + SpvDecorationGlobalVariableOffsetINTEL = 5628, + SpvDecorationCounterBuffer = 5634, + SpvDecorationHlslCounterBufferGOOGLE = 5634, + SpvDecorationHlslSemanticGOOGLE = 5635, + SpvDecorationUserSemantic = 5635, + SpvDecorationUserTypeGOOGLE = 5636, + SpvDecorationFunctionRoundingModeINTEL = 5822, + SpvDecorationFunctionDenormModeINTEL = 5823, + SpvDecorationRegisterINTEL = 5825, + SpvDecorationMemoryINTEL = 5826, + SpvDecorationNumbanksINTEL = 5827, + SpvDecorationBankwidthINTEL = 5828, + SpvDecorationMaxPrivateCopiesINTEL = 5829, + SpvDecorationSinglepumpINTEL = 5830, + SpvDecorationDoublepumpINTEL = 5831, + SpvDecorationMaxReplicatesINTEL = 5832, + SpvDecorationSimpleDualPortINTEL = 5833, + SpvDecorationMergeINTEL = 5834, + SpvDecorationBankBitsINTEL = 5835, + SpvDecorationForcePow2DepthINTEL = 5836, + SpvDecorationStridesizeINTEL = 5883, + SpvDecorationWordsizeINTEL = 5884, + SpvDecorationTrueDualPortINTEL = 5885, + SpvDecorationBurstCoalesceINTEL = 5899, + SpvDecorationCacheSizeINTEL = 5900, + SpvDecorationDontStaticallyCoalesceINTEL = 5901, + SpvDecorationPrefetchINTEL = 5902, + SpvDecorationStallEnableINTEL = 5905, + SpvDecorationFuseLoopsInFunctionINTEL = 5907, + SpvDecorationMathOpDSPModeINTEL = 5909, + SpvDecorationAliasScopeINTEL = 5914, + SpvDecorationNoAliasINTEL = 5915, + SpvDecorationInitiationIntervalINTEL = 5917, + SpvDecorationMaxConcurrencyINTEL = 5918, + SpvDecorationPipelineEnableINTEL = 5919, + SpvDecorationBufferLocationINTEL = 5921, + SpvDecorationIOPipeStorageINTEL = 5944, + SpvDecorationFunctionFloatingPointModeINTEL = 6080, + SpvDecorationSingleElementVectorINTEL = 6085, + SpvDecorationVectorComputeCallableFunctionINTEL = 6087, + SpvDecorationMediaBlockIOINTEL = 6140, + SpvDecorationStallFreeINTEL = 6151, + SpvDecorationFPMaxErrorDecorationINTEL = 6170, + SpvDecorationLatencyControlLabelINTEL = 6172, + SpvDecorationLatencyControlConstraintINTEL = 6173, + SpvDecorationConduitKernelArgumentINTEL = 6175, + SpvDecorationRegisterMapKernelArgumentINTEL = 6176, + SpvDecorationMMHostInterfaceAddressWidthINTEL = 6177, + SpvDecorationMMHostInterfaceDataWidthINTEL = 6178, + SpvDecorationMMHostInterfaceLatencyINTEL = 6179, + SpvDecorationMMHostInterfaceReadWriteModeINTEL = 6180, + SpvDecorationMMHostInterfaceMaxBurstINTEL = 6181, + SpvDecorationMMHostInterfaceWaitRequestINTEL = 6182, + SpvDecorationStableKernelArgumentINTEL = 6183, + SpvDecorationHostAccessINTEL = 6188, + SpvDecorationInitModeINTEL = 6190, + SpvDecorationImplementInRegisterMapINTEL = 6191, + SpvDecorationConditionalINTEL = 6247, + SpvDecorationCacheControlLoadINTEL = 6442, + SpvDecorationCacheControlStoreINTEL = 6443, + SpvDecorationMax = 0x7fffffff, +} SpvDecoration; + +typedef enum SpvBuiltIn_ { + SpvBuiltInPosition = 0, + SpvBuiltInPointSize = 1, + SpvBuiltInClipDistance = 3, + SpvBuiltInCullDistance = 4, + SpvBuiltInVertexId = 5, + SpvBuiltInInstanceId = 6, + SpvBuiltInPrimitiveId = 7, + SpvBuiltInInvocationId = 8, + SpvBuiltInLayer = 9, + SpvBuiltInViewportIndex = 10, + SpvBuiltInTessLevelOuter = 11, + SpvBuiltInTessLevelInner = 12, + SpvBuiltInTessCoord = 13, + SpvBuiltInPatchVertices = 14, + SpvBuiltInFragCoord = 15, + SpvBuiltInPointCoord = 16, + SpvBuiltInFrontFacing = 17, + SpvBuiltInSampleId = 18, + SpvBuiltInSamplePosition = 19, + SpvBuiltInSampleMask = 20, + SpvBuiltInFragDepth = 22, + SpvBuiltInHelperInvocation = 23, + SpvBuiltInNumWorkgroups = 24, + SpvBuiltInWorkgroupSize = 25, + SpvBuiltInWorkgroupId = 26, + SpvBuiltInLocalInvocationId = 27, + SpvBuiltInGlobalInvocationId = 28, + SpvBuiltInLocalInvocationIndex = 29, + SpvBuiltInWorkDim = 30, + SpvBuiltInGlobalSize = 31, + SpvBuiltInEnqueuedWorkgroupSize = 32, + SpvBuiltInGlobalOffset = 33, + SpvBuiltInGlobalLinearId = 34, + SpvBuiltInSubgroupSize = 36, + SpvBuiltInSubgroupMaxSize = 37, + SpvBuiltInNumSubgroups = 38, + SpvBuiltInNumEnqueuedSubgroups = 39, + SpvBuiltInSubgroupId = 40, + SpvBuiltInSubgroupLocalInvocationId = 41, + SpvBuiltInVertexIndex = 42, + SpvBuiltInInstanceIndex = 43, + SpvBuiltInCoreIDARM = 4160, + SpvBuiltInCoreCountARM = 4161, + SpvBuiltInCoreMaxIDARM = 4162, + SpvBuiltInWarpIDARM = 4163, + SpvBuiltInWarpMaxIDARM = 4164, + SpvBuiltInSubgroupEqMask = 4416, + SpvBuiltInSubgroupEqMaskKHR = 4416, + SpvBuiltInSubgroupGeMask = 4417, + SpvBuiltInSubgroupGeMaskKHR = 4417, + SpvBuiltInSubgroupGtMask = 4418, + SpvBuiltInSubgroupGtMaskKHR = 4418, + SpvBuiltInSubgroupLeMask = 4419, + SpvBuiltInSubgroupLeMaskKHR = 4419, + SpvBuiltInSubgroupLtMask = 4420, + SpvBuiltInSubgroupLtMaskKHR = 4420, + SpvBuiltInBaseVertex = 4424, + SpvBuiltInBaseInstance = 4425, + SpvBuiltInDrawIndex = 4426, + SpvBuiltInPrimitiveShadingRateKHR = 4432, + SpvBuiltInDeviceIndex = 4438, + SpvBuiltInViewIndex = 4440, + SpvBuiltInShadingRateKHR = 4444, + SpvBuiltInTileOffsetQCOM = 4492, + SpvBuiltInTileDimensionQCOM = 4493, + SpvBuiltInTileApronSizeQCOM = 4494, + SpvBuiltInBaryCoordNoPerspAMD = 4992, + SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, + SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, + SpvBuiltInBaryCoordSmoothAMD = 4995, + SpvBuiltInBaryCoordSmoothCentroidAMD = 4996, + SpvBuiltInBaryCoordSmoothSampleAMD = 4997, + SpvBuiltInBaryCoordPullModelAMD = 4998, + SpvBuiltInFragStencilRefEXT = 5014, + SpvBuiltInRemainingRecursionLevelsAMDX = 5021, + SpvBuiltInShaderIndexAMDX = 5073, + SpvBuiltInViewportMaskNV = 5253, + SpvBuiltInSecondaryPositionNV = 5257, + SpvBuiltInSecondaryViewportMaskNV = 5258, + SpvBuiltInPositionPerViewNV = 5261, + SpvBuiltInViewportMaskPerViewNV = 5262, + SpvBuiltInFullyCoveredEXT = 5264, + SpvBuiltInTaskCountNV = 5274, + SpvBuiltInPrimitiveCountNV = 5275, + SpvBuiltInPrimitiveIndicesNV = 5276, + SpvBuiltInClipDistancePerViewNV = 5277, + SpvBuiltInCullDistancePerViewNV = 5278, + SpvBuiltInLayerPerViewNV = 5279, + SpvBuiltInMeshViewCountNV = 5280, + SpvBuiltInMeshViewIndicesNV = 5281, + SpvBuiltInBaryCoordKHR = 5286, + SpvBuiltInBaryCoordNV = 5286, + SpvBuiltInBaryCoordNoPerspKHR = 5287, + SpvBuiltInBaryCoordNoPerspNV = 5287, + SpvBuiltInFragSizeEXT = 5292, + SpvBuiltInFragmentSizeNV = 5292, + SpvBuiltInFragInvocationCountEXT = 5293, + SpvBuiltInInvocationsPerPixelNV = 5293, + SpvBuiltInPrimitivePointIndicesEXT = 5294, + SpvBuiltInPrimitiveLineIndicesEXT = 5295, + SpvBuiltInPrimitiveTriangleIndicesEXT = 5296, + SpvBuiltInCullPrimitiveEXT = 5299, + SpvBuiltInLaunchIdKHR = 5319, + SpvBuiltInLaunchIdNV = 5319, + SpvBuiltInLaunchSizeKHR = 5320, + SpvBuiltInLaunchSizeNV = 5320, + SpvBuiltInWorldRayOriginKHR = 5321, + SpvBuiltInWorldRayOriginNV = 5321, + SpvBuiltInWorldRayDirectionKHR = 5322, + SpvBuiltInWorldRayDirectionNV = 5322, + SpvBuiltInObjectRayOriginKHR = 5323, + SpvBuiltInObjectRayOriginNV = 5323, + SpvBuiltInObjectRayDirectionKHR = 5324, + SpvBuiltInObjectRayDirectionNV = 5324, + SpvBuiltInRayTminKHR = 5325, + SpvBuiltInRayTminNV = 5325, + SpvBuiltInRayTmaxKHR = 5326, + SpvBuiltInRayTmaxNV = 5326, + SpvBuiltInInstanceCustomIndexKHR = 5327, + SpvBuiltInInstanceCustomIndexNV = 5327, + SpvBuiltInObjectToWorldKHR = 5330, + SpvBuiltInObjectToWorldNV = 5330, + SpvBuiltInWorldToObjectKHR = 5331, + SpvBuiltInWorldToObjectNV = 5331, + SpvBuiltInHitTNV = 5332, + SpvBuiltInHitKindKHR = 5333, + SpvBuiltInHitKindNV = 5333, + SpvBuiltInCurrentRayTimeNV = 5334, + SpvBuiltInHitTriangleVertexPositionsKHR = 5335, + SpvBuiltInHitMicroTriangleVertexPositionsNV = 5337, + SpvBuiltInHitMicroTriangleVertexBarycentricsNV = 5344, + SpvBuiltInIncomingRayFlagsKHR = 5351, + SpvBuiltInIncomingRayFlagsNV = 5351, + SpvBuiltInRayGeometryIndexKHR = 5352, + SpvBuiltInHitIsSphereNV = 5359, + SpvBuiltInHitIsLSSNV = 5360, + SpvBuiltInHitSpherePositionNV = 5361, + SpvBuiltInWarpsPerSMNV = 5374, + SpvBuiltInSMCountNV = 5375, + SpvBuiltInWarpIDNV = 5376, + SpvBuiltInSMIDNV = 5377, + SpvBuiltInHitLSSPositionsNV = 5396, + SpvBuiltInHitKindFrontFacingMicroTriangleNV = 5405, + SpvBuiltInHitKindBackFacingMicroTriangleNV = 5406, + SpvBuiltInHitSphereRadiusNV = 5420, + SpvBuiltInHitLSSRadiiNV = 5421, + SpvBuiltInClusterIDNV = 5436, + SpvBuiltInCullMaskKHR = 6021, + SpvBuiltInMax = 0x7fffffff, +} SpvBuiltIn; + +typedef enum SpvSelectionControlShift_ { + SpvSelectionControlFlattenShift = 0, + SpvSelectionControlDontFlattenShift = 1, + SpvSelectionControlMax = 0x7fffffff, +} SpvSelectionControlShift; + +typedef enum SpvSelectionControlMask_ { + SpvSelectionControlMaskNone = 0, + SpvSelectionControlFlattenMask = 0x00000001, + SpvSelectionControlDontFlattenMask = 0x00000002, +} SpvSelectionControlMask; + +typedef enum SpvLoopControlShift_ { + SpvLoopControlUnrollShift = 0, + SpvLoopControlDontUnrollShift = 1, + SpvLoopControlDependencyInfiniteShift = 2, + SpvLoopControlDependencyLengthShift = 3, + SpvLoopControlMinIterationsShift = 4, + SpvLoopControlMaxIterationsShift = 5, + SpvLoopControlIterationMultipleShift = 6, + SpvLoopControlPeelCountShift = 7, + SpvLoopControlPartialCountShift = 8, + SpvLoopControlInitiationIntervalINTELShift = 16, + SpvLoopControlMaxConcurrencyINTELShift = 17, + SpvLoopControlDependencyArrayINTELShift = 18, + SpvLoopControlPipelineEnableINTELShift = 19, + SpvLoopControlLoopCoalesceINTELShift = 20, + SpvLoopControlMaxInterleavingINTELShift = 21, + SpvLoopControlSpeculatedIterationsINTELShift = 22, + SpvLoopControlNoFusionINTELShift = 23, + SpvLoopControlLoopCountINTELShift = 24, + SpvLoopControlMaxReinvocationDelayINTELShift = 25, + SpvLoopControlMax = 0x7fffffff, +} SpvLoopControlShift; + +typedef enum SpvLoopControlMask_ { + SpvLoopControlMaskNone = 0, + SpvLoopControlUnrollMask = 0x00000001, + SpvLoopControlDontUnrollMask = 0x00000002, + SpvLoopControlDependencyInfiniteMask = 0x00000004, + SpvLoopControlDependencyLengthMask = 0x00000008, + SpvLoopControlMinIterationsMask = 0x00000010, + SpvLoopControlMaxIterationsMask = 0x00000020, + SpvLoopControlIterationMultipleMask = 0x00000040, + SpvLoopControlPeelCountMask = 0x00000080, + SpvLoopControlPartialCountMask = 0x00000100, + SpvLoopControlInitiationIntervalINTELMask = 0x00010000, + SpvLoopControlMaxConcurrencyINTELMask = 0x00020000, + SpvLoopControlDependencyArrayINTELMask = 0x00040000, + SpvLoopControlPipelineEnableINTELMask = 0x00080000, + SpvLoopControlLoopCoalesceINTELMask = 0x00100000, + SpvLoopControlMaxInterleavingINTELMask = 0x00200000, + SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000, + SpvLoopControlNoFusionINTELMask = 0x00800000, + SpvLoopControlLoopCountINTELMask = 0x01000000, + SpvLoopControlMaxReinvocationDelayINTELMask = 0x02000000, +} SpvLoopControlMask; + +typedef enum SpvFunctionControlShift_ { + SpvFunctionControlInlineShift = 0, + SpvFunctionControlDontInlineShift = 1, + SpvFunctionControlPureShift = 2, + SpvFunctionControlConstShift = 3, + SpvFunctionControlOptNoneEXTShift = 16, + SpvFunctionControlOptNoneINTELShift = 16, + SpvFunctionControlMax = 0x7fffffff, +} SpvFunctionControlShift; + +typedef enum SpvFunctionControlMask_ { + SpvFunctionControlMaskNone = 0, + SpvFunctionControlInlineMask = 0x00000001, + SpvFunctionControlDontInlineMask = 0x00000002, + SpvFunctionControlPureMask = 0x00000004, + SpvFunctionControlConstMask = 0x00000008, + SpvFunctionControlOptNoneEXTMask = 0x00010000, + SpvFunctionControlOptNoneINTELMask = 0x00010000, +} SpvFunctionControlMask; + +typedef enum SpvMemorySemanticsShift_ { + SpvMemorySemanticsAcquireShift = 1, + SpvMemorySemanticsReleaseShift = 2, + SpvMemorySemanticsAcquireReleaseShift = 3, + SpvMemorySemanticsSequentiallyConsistentShift = 4, + SpvMemorySemanticsUniformMemoryShift = 6, + SpvMemorySemanticsSubgroupMemoryShift = 7, + SpvMemorySemanticsWorkgroupMemoryShift = 8, + SpvMemorySemanticsCrossWorkgroupMemoryShift = 9, + SpvMemorySemanticsAtomicCounterMemoryShift = 10, + SpvMemorySemanticsImageMemoryShift = 11, + SpvMemorySemanticsOutputMemoryShift = 12, + SpvMemorySemanticsOutputMemoryKHRShift = 12, + SpvMemorySemanticsMakeAvailableShift = 13, + SpvMemorySemanticsMakeAvailableKHRShift = 13, + SpvMemorySemanticsMakeVisibleShift = 14, + SpvMemorySemanticsMakeVisibleKHRShift = 14, + SpvMemorySemanticsVolatileShift = 15, + SpvMemorySemanticsMax = 0x7fffffff, +} SpvMemorySemanticsShift; + +typedef enum SpvMemorySemanticsMask_ { + SpvMemorySemanticsMaskNone = 0, + SpvMemorySemanticsAcquireMask = 0x00000002, + SpvMemorySemanticsReleaseMask = 0x00000004, + SpvMemorySemanticsAcquireReleaseMask = 0x00000008, + SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010, + SpvMemorySemanticsUniformMemoryMask = 0x00000040, + SpvMemorySemanticsSubgroupMemoryMask = 0x00000080, + SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100, + SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400, + SpvMemorySemanticsImageMemoryMask = 0x00000800, + SpvMemorySemanticsOutputMemoryMask = 0x00001000, + SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000, + SpvMemorySemanticsMakeAvailableMask = 0x00002000, + SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000, + SpvMemorySemanticsMakeVisibleMask = 0x00004000, + SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000, + SpvMemorySemanticsVolatileMask = 0x00008000, +} SpvMemorySemanticsMask; + +typedef enum SpvMemoryAccessShift_ { + SpvMemoryAccessVolatileShift = 0, + SpvMemoryAccessAlignedShift = 1, + SpvMemoryAccessNontemporalShift = 2, + SpvMemoryAccessMakePointerAvailableShift = 3, + SpvMemoryAccessMakePointerAvailableKHRShift = 3, + SpvMemoryAccessMakePointerVisibleShift = 4, + SpvMemoryAccessMakePointerVisibleKHRShift = 4, + SpvMemoryAccessNonPrivatePointerShift = 5, + SpvMemoryAccessNonPrivatePointerKHRShift = 5, + SpvMemoryAccessAliasScopeINTELMaskShift = 16, + SpvMemoryAccessNoAliasINTELMaskShift = 17, + SpvMemoryAccessMax = 0x7fffffff, +} SpvMemoryAccessShift; + +typedef enum SpvMemoryAccessMask_ { + SpvMemoryAccessMaskNone = 0, + SpvMemoryAccessVolatileMask = 0x00000001, + SpvMemoryAccessAlignedMask = 0x00000002, + SpvMemoryAccessNontemporalMask = 0x00000004, + SpvMemoryAccessMakePointerAvailableMask = 0x00000008, + SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008, + SpvMemoryAccessMakePointerVisibleMask = 0x00000010, + SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, + SpvMemoryAccessNonPrivatePointerMask = 0x00000020, + SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, + SpvMemoryAccessAliasScopeINTELMaskMask = 0x00010000, + SpvMemoryAccessNoAliasINTELMaskMask = 0x00020000, +} SpvMemoryAccessMask; + +typedef enum SpvScope_ { + SpvScopeCrossDevice = 0, + SpvScopeDevice = 1, + SpvScopeWorkgroup = 2, + SpvScopeSubgroup = 3, + SpvScopeInvocation = 4, + SpvScopeQueueFamily = 5, + SpvScopeQueueFamilyKHR = 5, + SpvScopeShaderCallKHR = 6, + SpvScopeMax = 0x7fffffff, +} SpvScope; + +typedef enum SpvGroupOperation_ { + SpvGroupOperationReduce = 0, + SpvGroupOperationInclusiveScan = 1, + SpvGroupOperationExclusiveScan = 2, + SpvGroupOperationClusteredReduce = 3, + SpvGroupOperationPartitionedReduceNV = 6, + SpvGroupOperationPartitionedInclusiveScanNV = 7, + SpvGroupOperationPartitionedExclusiveScanNV = 8, + SpvGroupOperationMax = 0x7fffffff, +} SpvGroupOperation; + +typedef enum SpvKernelEnqueueFlags_ { + SpvKernelEnqueueFlagsNoWait = 0, + SpvKernelEnqueueFlagsWaitKernel = 1, + SpvKernelEnqueueFlagsWaitWorkGroup = 2, + SpvKernelEnqueueFlagsMax = 0x7fffffff, +} SpvKernelEnqueueFlags; + +typedef enum SpvKernelProfilingInfoShift_ { + SpvKernelProfilingInfoCmdExecTimeShift = 0, + SpvKernelProfilingInfoMax = 0x7fffffff, +} SpvKernelProfilingInfoShift; + +typedef enum SpvKernelProfilingInfoMask_ { + SpvKernelProfilingInfoMaskNone = 0, + SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001, +} SpvKernelProfilingInfoMask; + +typedef enum SpvCapability_ { + SpvCapabilityMatrix = 0, + SpvCapabilityShader = 1, + SpvCapabilityGeometry = 2, + SpvCapabilityTessellation = 3, + SpvCapabilityAddresses = 4, + SpvCapabilityLinkage = 5, + SpvCapabilityKernel = 6, + SpvCapabilityVector16 = 7, + SpvCapabilityFloat16Buffer = 8, + SpvCapabilityFloat16 = 9, + SpvCapabilityFloat64 = 10, + SpvCapabilityInt64 = 11, + SpvCapabilityInt64Atomics = 12, + SpvCapabilityImageBasic = 13, + SpvCapabilityImageReadWrite = 14, + SpvCapabilityImageMipmap = 15, + SpvCapabilityPipes = 17, + SpvCapabilityGroups = 18, + SpvCapabilityDeviceEnqueue = 19, + SpvCapabilityLiteralSampler = 20, + SpvCapabilityAtomicStorage = 21, + SpvCapabilityInt16 = 22, + SpvCapabilityTessellationPointSize = 23, + SpvCapabilityGeometryPointSize = 24, + SpvCapabilityImageGatherExtended = 25, + SpvCapabilityStorageImageMultisample = 27, + SpvCapabilityUniformBufferArrayDynamicIndexing = 28, + SpvCapabilitySampledImageArrayDynamicIndexing = 29, + SpvCapabilityStorageBufferArrayDynamicIndexing = 30, + SpvCapabilityStorageImageArrayDynamicIndexing = 31, + SpvCapabilityClipDistance = 32, + SpvCapabilityCullDistance = 33, + SpvCapabilityImageCubeArray = 34, + SpvCapabilitySampleRateShading = 35, + SpvCapabilityImageRect = 36, + SpvCapabilitySampledRect = 37, + SpvCapabilityGenericPointer = 38, + SpvCapabilityInt8 = 39, + SpvCapabilityInputAttachment = 40, + SpvCapabilitySparseResidency = 41, + SpvCapabilityMinLod = 42, + SpvCapabilitySampled1D = 43, + SpvCapabilityImage1D = 44, + SpvCapabilitySampledCubeArray = 45, + SpvCapabilitySampledBuffer = 46, + SpvCapabilityImageBuffer = 47, + SpvCapabilityImageMSArray = 48, + SpvCapabilityStorageImageExtendedFormats = 49, + SpvCapabilityImageQuery = 50, + SpvCapabilityDerivativeControl = 51, + SpvCapabilityInterpolationFunction = 52, + SpvCapabilityTransformFeedback = 53, + SpvCapabilityGeometryStreams = 54, + SpvCapabilityStorageImageReadWithoutFormat = 55, + SpvCapabilityStorageImageWriteWithoutFormat = 56, + SpvCapabilityMultiViewport = 57, + SpvCapabilitySubgroupDispatch = 58, + SpvCapabilityNamedBarrier = 59, + SpvCapabilityPipeStorage = 60, + SpvCapabilityGroupNonUniform = 61, + SpvCapabilityGroupNonUniformVote = 62, + SpvCapabilityGroupNonUniformArithmetic = 63, + SpvCapabilityGroupNonUniformBallot = 64, + SpvCapabilityGroupNonUniformShuffle = 65, + SpvCapabilityGroupNonUniformShuffleRelative = 66, + SpvCapabilityGroupNonUniformClustered = 67, + SpvCapabilityGroupNonUniformQuad = 68, + SpvCapabilityShaderLayer = 69, + SpvCapabilityShaderViewportIndex = 70, + SpvCapabilityUniformDecoration = 71, + SpvCapabilityCoreBuiltinsARM = 4165, + SpvCapabilityTileImageColorReadAccessEXT = 4166, + SpvCapabilityTileImageDepthReadAccessEXT = 4167, + SpvCapabilityTileImageStencilReadAccessEXT = 4168, + SpvCapabilityTensorsARM = 4174, + SpvCapabilityStorageTensorArrayDynamicIndexingARM = 4175, + SpvCapabilityStorageTensorArrayNonUniformIndexingARM = 4176, + SpvCapabilityGraphARM = 4191, + SpvCapabilityCooperativeMatrixLayoutsARM = 4201, + SpvCapabilityFloat8EXT = 4212, + SpvCapabilityFloat8CooperativeMatrixEXT = 4213, + SpvCapabilityFragmentShadingRateKHR = 4422, + SpvCapabilitySubgroupBallotKHR = 4423, + SpvCapabilityDrawParameters = 4427, + SpvCapabilityWorkgroupMemoryExplicitLayoutKHR = 4428, + SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, + SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, + SpvCapabilitySubgroupVoteKHR = 4431, + SpvCapabilityStorageBuffer16BitAccess = 4433, + SpvCapabilityStorageUniformBufferBlock16 = 4433, + SpvCapabilityStorageUniform16 = 4434, + SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434, + SpvCapabilityStoragePushConstant16 = 4435, + SpvCapabilityStorageInputOutput16 = 4436, + SpvCapabilityDeviceGroup = 4437, + SpvCapabilityMultiView = 4439, + SpvCapabilityVariablePointersStorageBuffer = 4441, + SpvCapabilityVariablePointers = 4442, + SpvCapabilityAtomicStorageOps = 4445, + SpvCapabilitySampleMaskPostDepthCoverage = 4447, + SpvCapabilityStorageBuffer8BitAccess = 4448, + SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449, + SpvCapabilityStoragePushConstant8 = 4450, + SpvCapabilityDenormPreserve = 4464, + SpvCapabilityDenormFlushToZero = 4465, + SpvCapabilitySignedZeroInfNanPreserve = 4466, + SpvCapabilityRoundingModeRTE = 4467, + SpvCapabilityRoundingModeRTZ = 4468, + SpvCapabilityRayQueryProvisionalKHR = 4471, + SpvCapabilityRayQueryKHR = 4472, + SpvCapabilityUntypedPointersKHR = 4473, + SpvCapabilityRayTraversalPrimitiveCullingKHR = 4478, + SpvCapabilityRayTracingKHR = 4479, + SpvCapabilityTextureSampleWeightedQCOM = 4484, + SpvCapabilityTextureBoxFilterQCOM = 4485, + SpvCapabilityTextureBlockMatchQCOM = 4486, + SpvCapabilityTileShadingQCOM = 4495, + SpvCapabilityCooperativeMatrixConversionQCOM = 4496, + SpvCapabilityTextureBlockMatch2QCOM = 4498, + SpvCapabilityFloat16ImageAMD = 5008, + SpvCapabilityImageGatherBiasLodAMD = 5009, + SpvCapabilityFragmentMaskAMD = 5010, + SpvCapabilityStencilExportEXT = 5013, + SpvCapabilityImageReadWriteLodAMD = 5015, + SpvCapabilityInt64ImageEXT = 5016, + SpvCapabilityShaderClockKHR = 5055, + SpvCapabilityShaderEnqueueAMDX = 5067, + SpvCapabilityQuadControlKHR = 5087, + SpvCapabilityInt4TypeINTEL = 5112, + SpvCapabilityInt4CooperativeMatrixINTEL = 5114, + SpvCapabilityBFloat16TypeKHR = 5116, + SpvCapabilityBFloat16DotProductKHR = 5117, + SpvCapabilityBFloat16CooperativeMatrixKHR = 5118, + SpvCapabilitySampleMaskOverrideCoverageNV = 5249, + SpvCapabilityGeometryShaderPassthroughNV = 5251, + SpvCapabilityShaderViewportIndexLayerEXT = 5254, + SpvCapabilityShaderViewportIndexLayerNV = 5254, + SpvCapabilityShaderViewportMaskNV = 5255, + SpvCapabilityShaderStereoViewNV = 5259, + SpvCapabilityPerViewAttributesNV = 5260, + SpvCapabilityFragmentFullyCoveredEXT = 5265, + SpvCapabilityMeshShadingNV = 5266, + SpvCapabilityImageFootprintNV = 5282, + SpvCapabilityMeshShadingEXT = 5283, + SpvCapabilityFragmentBarycentricKHR = 5284, + SpvCapabilityFragmentBarycentricNV = 5284, + SpvCapabilityComputeDerivativeGroupQuadsKHR = 5288, + SpvCapabilityComputeDerivativeGroupQuadsNV = 5288, + SpvCapabilityFragmentDensityEXT = 5291, + SpvCapabilityShadingRateNV = 5291, + SpvCapabilityGroupNonUniformPartitionedNV = 5297, + SpvCapabilityShaderNonUniform = 5301, + SpvCapabilityShaderNonUniformEXT = 5301, + SpvCapabilityRuntimeDescriptorArray = 5302, + SpvCapabilityRuntimeDescriptorArrayEXT = 5302, + SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303, + SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306, + SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + SpvCapabilitySampledImageArrayNonUniformIndexing = 5307, + SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308, + SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + SpvCapabilityStorageImageArrayNonUniformIndexing = 5309, + SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310, + SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + SpvCapabilityRayTracingPositionFetchKHR = 5336, + SpvCapabilityRayTracingNV = 5340, + SpvCapabilityRayTracingMotionBlurNV = 5341, + SpvCapabilityVulkanMemoryModel = 5345, + SpvCapabilityVulkanMemoryModelKHR = 5345, + SpvCapabilityVulkanMemoryModelDeviceScope = 5346, + SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + SpvCapabilityPhysicalStorageBufferAddresses = 5347, + SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, + SpvCapabilityComputeDerivativeGroupLinearKHR = 5350, + SpvCapabilityComputeDerivativeGroupLinearNV = 5350, + SpvCapabilityRayTracingProvisionalKHR = 5353, + SpvCapabilityCooperativeMatrixNV = 5357, + SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, + SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, + SpvCapabilityShaderSMBuiltinsNV = 5373, + SpvCapabilityFragmentShaderPixelInterlockEXT = 5378, + SpvCapabilityDemoteToHelperInvocation = 5379, + SpvCapabilityDemoteToHelperInvocationEXT = 5379, + SpvCapabilityDisplacementMicromapNV = 5380, + SpvCapabilityRayTracingOpacityMicromapEXT = 5381, + SpvCapabilityShaderInvocationReorderNV = 5383, + SpvCapabilityBindlessTextureNV = 5390, + SpvCapabilityRayQueryPositionFetchKHR = 5391, + SpvCapabilityCooperativeVectorNV = 5394, + SpvCapabilityAtomicFloat16VectorNV = 5404, + SpvCapabilityRayTracingDisplacementMicromapNV = 5409, + SpvCapabilityRawAccessChainsNV = 5414, + SpvCapabilityRayTracingSpheresGeometryNV = 5418, + SpvCapabilityRayTracingLinearSweptSpheresGeometryNV = 5419, + SpvCapabilityCooperativeMatrixReductionsNV = 5430, + SpvCapabilityCooperativeMatrixConversionsNV = 5431, + SpvCapabilityCooperativeMatrixPerElementOperationsNV = 5432, + SpvCapabilityCooperativeMatrixTensorAddressingNV = 5433, + SpvCapabilityCooperativeMatrixBlockLoadsNV = 5434, + SpvCapabilityCooperativeVectorTrainingNV = 5435, + SpvCapabilityRayTracingClusterAccelerationStructureNV = 5437, + SpvCapabilityTensorAddressingNV = 5439, + SpvCapabilitySubgroupShuffleINTEL = 5568, + SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, + SpvCapabilitySubgroupImageBlockIOINTEL = 5570, + SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579, + SpvCapabilityRoundToInfinityINTEL = 5582, + SpvCapabilityFloatingPointModeINTEL = 5583, + SpvCapabilityIntegerFunctions2INTEL = 5584, + SpvCapabilityFunctionPointersINTEL = 5603, + SpvCapabilityIndirectReferencesINTEL = 5604, + SpvCapabilityAsmINTEL = 5606, + SpvCapabilityAtomicFloat32MinMaxEXT = 5612, + SpvCapabilityAtomicFloat64MinMaxEXT = 5613, + SpvCapabilityAtomicFloat16MinMaxEXT = 5616, + SpvCapabilityVectorComputeINTEL = 5617, + SpvCapabilityVectorAnyINTEL = 5619, + SpvCapabilityExpectAssumeKHR = 5629, + SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696, + SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + SpvCapabilityVariableLengthArrayINTEL = 5817, + SpvCapabilityFunctionFloatControlINTEL = 5821, + SpvCapabilityFPGAMemoryAttributesINTEL = 5824, + SpvCapabilityFPFastMathModeINTEL = 5837, + SpvCapabilityArbitraryPrecisionIntegersINTEL = 5844, + SpvCapabilityArbitraryPrecisionFloatingPointINTEL = 5845, + SpvCapabilityUnstructuredLoopControlsINTEL = 5886, + SpvCapabilityFPGALoopControlsINTEL = 5888, + SpvCapabilityKernelAttributesINTEL = 5892, + SpvCapabilityFPGAKernelAttributesINTEL = 5897, + SpvCapabilityFPGAMemoryAccessesINTEL = 5898, + SpvCapabilityFPGAClusterAttributesINTEL = 5904, + SpvCapabilityLoopFuseINTEL = 5906, + SpvCapabilityFPGADSPControlINTEL = 5908, + SpvCapabilityMemoryAccessAliasingINTEL = 5910, + SpvCapabilityFPGAInvocationPipeliningAttributesINTEL = 5916, + SpvCapabilityFPGABufferLocationINTEL = 5920, + SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922, + SpvCapabilityUSMStorageClassesINTEL = 5935, + SpvCapabilityRuntimeAlignedAttributeINTEL = 5939, + SpvCapabilityIOPipesINTEL = 5943, + SpvCapabilityBlockingPipesINTEL = 5945, + SpvCapabilityFPGARegINTEL = 5948, + SpvCapabilityDotProductInputAll = 6016, + SpvCapabilityDotProductInputAllKHR = 6016, + SpvCapabilityDotProductInput4x8Bit = 6017, + SpvCapabilityDotProductInput4x8BitKHR = 6017, + SpvCapabilityDotProductInput4x8BitPacked = 6018, + SpvCapabilityDotProductInput4x8BitPackedKHR = 6018, + SpvCapabilityDotProduct = 6019, + SpvCapabilityDotProductKHR = 6019, + SpvCapabilityRayCullMaskKHR = 6020, + SpvCapabilityCooperativeMatrixKHR = 6022, + SpvCapabilityReplicatedCompositesEXT = 6024, + SpvCapabilityBitInstructions = 6025, + SpvCapabilityGroupNonUniformRotateKHR = 6026, + SpvCapabilityFloatControls2 = 6029, + SpvCapabilityAtomicFloat32AddEXT = 6033, + SpvCapabilityAtomicFloat64AddEXT = 6034, + SpvCapabilityLongCompositesINTEL = 6089, + SpvCapabilityOptNoneEXT = 6094, + SpvCapabilityOptNoneINTEL = 6094, + SpvCapabilityAtomicFloat16AddEXT = 6095, + SpvCapabilityDebugInfoModuleINTEL = 6114, + SpvCapabilityBFloat16ConversionINTEL = 6115, + SpvCapabilitySplitBarrierINTEL = 6141, + SpvCapabilityArithmeticFenceEXT = 6144, + SpvCapabilityFPGAClusterAttributesV2INTEL = 6150, + SpvCapabilityFPGAKernelAttributesv2INTEL = 6161, + SpvCapabilityTaskSequenceINTEL = 6162, + SpvCapabilityFPMaxErrorINTEL = 6169, + SpvCapabilityFPGALatencyControlINTEL = 6171, + SpvCapabilityFPGAArgumentInterfacesINTEL = 6174, + SpvCapabilityGlobalVariableHostAccessINTEL = 6187, + SpvCapabilityGlobalVariableFPGADecorationsINTEL = 6189, + SpvCapabilitySubgroupBufferPrefetchINTEL = 6220, + SpvCapabilitySubgroup2DBlockIOINTEL = 6228, + SpvCapabilitySubgroup2DBlockTransformINTEL = 6229, + SpvCapabilitySubgroup2DBlockTransposeINTEL = 6230, + SpvCapabilitySubgroupMatrixMultiplyAccumulateINTEL = 6236, + SpvCapabilityTernaryBitwiseFunctionINTEL = 6241, + SpvCapabilityUntypedVariableLengthArrayINTEL = 6243, + SpvCapabilitySpecConditionalINTEL = 6245, + SpvCapabilityFunctionVariantsINTEL = 6246, + SpvCapabilityGroupUniformArithmeticKHR = 6400, + SpvCapabilityTensorFloat32RoundingINTEL = 6425, + SpvCapabilityMaskedGatherScatterINTEL = 6427, + SpvCapabilityCacheControlsINTEL = 6441, + SpvCapabilityRegisterLimitsINTEL = 6460, + SpvCapabilityBindlessImagesINTEL = 6528, + SpvCapabilityMax = 0x7fffffff, +} SpvCapability; + +typedef enum SpvRayFlagsShift_ { + SpvRayFlagsOpaqueKHRShift = 0, + SpvRayFlagsNoOpaqueKHRShift = 1, + SpvRayFlagsTerminateOnFirstHitKHRShift = 2, + SpvRayFlagsSkipClosestHitShaderKHRShift = 3, + SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, + SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, + SpvRayFlagsCullOpaqueKHRShift = 6, + SpvRayFlagsCullNoOpaqueKHRShift = 7, + SpvRayFlagsSkipBuiltinPrimitivesNVShift = 8, + SpvRayFlagsSkipTrianglesKHRShift = 8, + SpvRayFlagsSkipAABBsKHRShift = 9, + SpvRayFlagsForceOpacityMicromap2StateEXTShift = 10, + SpvRayFlagsMax = 0x7fffffff, +} SpvRayFlagsShift; + +typedef enum SpvRayFlagsMask_ { + SpvRayFlagsMaskNone = 0, + SpvRayFlagsOpaqueKHRMask = 0x00000001, + SpvRayFlagsNoOpaqueKHRMask = 0x00000002, + SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + SpvRayFlagsCullOpaqueKHRMask = 0x00000040, + SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, + SpvRayFlagsSkipBuiltinPrimitivesNVMask = 0x00000100, + SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, + SpvRayFlagsSkipAABBsKHRMask = 0x00000200, + SpvRayFlagsForceOpacityMicromap2StateEXTMask = 0x00000400, +} SpvRayFlagsMask; + +typedef enum SpvRayQueryIntersection_ { + SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + SpvRayQueryIntersectionMax = 0x7fffffff, +} SpvRayQueryIntersection; + +typedef enum SpvRayQueryCommittedIntersectionType_ { + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCommittedIntersectionType; + +typedef enum SpvRayQueryCandidateIntersectionType_ { + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCandidateIntersectionType; + +typedef enum SpvFragmentShadingRateShift_ { + SpvFragmentShadingRateVertical2PixelsShift = 0, + SpvFragmentShadingRateVertical4PixelsShift = 1, + SpvFragmentShadingRateHorizontal2PixelsShift = 2, + SpvFragmentShadingRateHorizontal4PixelsShift = 3, + SpvFragmentShadingRateMax = 0x7fffffff, +} SpvFragmentShadingRateShift; + +typedef enum SpvFragmentShadingRateMask_ { + SpvFragmentShadingRateMaskNone = 0, + SpvFragmentShadingRateVertical2PixelsMask = 0x00000001, + SpvFragmentShadingRateVertical4PixelsMask = 0x00000002, + SpvFragmentShadingRateHorizontal2PixelsMask = 0x00000004, + SpvFragmentShadingRateHorizontal4PixelsMask = 0x00000008, +} SpvFragmentShadingRateMask; + +typedef enum SpvFPDenormMode_ { + SpvFPDenormModePreserve = 0, + SpvFPDenormModeFlushToZero = 1, + SpvFPDenormModeMax = 0x7fffffff, +} SpvFPDenormMode; + +typedef enum SpvFPOperationMode_ { + SpvFPOperationModeIEEE = 0, + SpvFPOperationModeALT = 1, + SpvFPOperationModeMax = 0x7fffffff, +} SpvFPOperationMode; + +typedef enum SpvQuantizationModes_ { + SpvQuantizationModesTRN = 0, + SpvQuantizationModesTRN_ZERO = 1, + SpvQuantizationModesRND = 2, + SpvQuantizationModesRND_ZERO = 3, + SpvQuantizationModesRND_INF = 4, + SpvQuantizationModesRND_MIN_INF = 5, + SpvQuantizationModesRND_CONV = 6, + SpvQuantizationModesRND_CONV_ODD = 7, + SpvQuantizationModesMax = 0x7fffffff, +} SpvQuantizationModes; + +typedef enum SpvOverflowModes_ { + SpvOverflowModesWRAP = 0, + SpvOverflowModesSAT = 1, + SpvOverflowModesSAT_ZERO = 2, + SpvOverflowModesSAT_SYM = 3, + SpvOverflowModesMax = 0x7fffffff, +} SpvOverflowModes; + +typedef enum SpvPackedVectorFormat_ { + SpvPackedVectorFormatPackedVectorFormat4x8Bit = 0, + SpvPackedVectorFormatPackedVectorFormat4x8BitKHR = 0, + SpvPackedVectorFormatMax = 0x7fffffff, +} SpvPackedVectorFormat; + +typedef enum SpvCooperativeMatrixOperandsShift_ { + SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRShift = 0, + SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRShift = 1, + SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRShift = 2, + SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift = 3, + SpvCooperativeMatrixOperandsSaturatingAccumulationKHRShift = 4, + SpvCooperativeMatrixOperandsMax = 0x7fffffff, +} SpvCooperativeMatrixOperandsShift; + +typedef enum SpvCooperativeMatrixOperandsMask_ { + SpvCooperativeMatrixOperandsMaskNone = 0, + SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRMask = 0x00000001, + SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRMask = 0x00000002, + SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRMask = 0x00000004, + SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask = 0x00000008, + SpvCooperativeMatrixOperandsSaturatingAccumulationKHRMask = 0x00000010, +} SpvCooperativeMatrixOperandsMask; + +typedef enum SpvCooperativeMatrixLayout_ { + SpvCooperativeMatrixLayoutRowMajorKHR = 0, + SpvCooperativeMatrixLayoutColumnMajorKHR = 1, + SpvCooperativeMatrixLayoutRowBlockedInterleavedARM = 4202, + SpvCooperativeMatrixLayoutColumnBlockedInterleavedARM = 4203, + SpvCooperativeMatrixLayoutMax = 0x7fffffff, +} SpvCooperativeMatrixLayout; + +typedef enum SpvCooperativeMatrixUse_ { + SpvCooperativeMatrixUseMatrixAKHR = 0, + SpvCooperativeMatrixUseMatrixBKHR = 1, + SpvCooperativeMatrixUseMatrixAccumulatorKHR = 2, + SpvCooperativeMatrixUseMax = 0x7fffffff, +} SpvCooperativeMatrixUse; + +typedef enum SpvCooperativeMatrixReduceShift_ { + SpvCooperativeMatrixReduceRowShift = 0, + SpvCooperativeMatrixReduceColumnShift = 1, + SpvCooperativeMatrixReduce2x2Shift = 2, + SpvCooperativeMatrixReduceMax = 0x7fffffff, +} SpvCooperativeMatrixReduceShift; + +typedef enum SpvCooperativeMatrixReduceMask_ { + SpvCooperativeMatrixReduceMaskNone = 0, + SpvCooperativeMatrixReduceRowMask = 0x00000001, + SpvCooperativeMatrixReduceColumnMask = 0x00000002, + SpvCooperativeMatrixReduce2x2Mask = 0x00000004, +} SpvCooperativeMatrixReduceMask; + +typedef enum SpvTensorClampMode_ { + SpvTensorClampModeUndefined = 0, + SpvTensorClampModeConstant = 1, + SpvTensorClampModeClampToEdge = 2, + SpvTensorClampModeRepeat = 3, + SpvTensorClampModeRepeatMirrored = 4, + SpvTensorClampModeMax = 0x7fffffff, +} SpvTensorClampMode; + +typedef enum SpvTensorAddressingOperandsShift_ { + SpvTensorAddressingOperandsTensorViewShift = 0, + SpvTensorAddressingOperandsDecodeFuncShift = 1, + SpvTensorAddressingOperandsMax = 0x7fffffff, +} SpvTensorAddressingOperandsShift; + +typedef enum SpvTensorAddressingOperandsMask_ { + SpvTensorAddressingOperandsMaskNone = 0, + SpvTensorAddressingOperandsTensorViewMask = 0x00000001, + SpvTensorAddressingOperandsDecodeFuncMask = 0x00000002, +} SpvTensorAddressingOperandsMask; + +typedef enum SpvTensorOperandsShift_ { + SpvTensorOperandsNontemporalARMShift = 0, + SpvTensorOperandsOutOfBoundsValueARMShift = 1, + SpvTensorOperandsMakeElementAvailableARMShift = 2, + SpvTensorOperandsMakeElementVisibleARMShift = 3, + SpvTensorOperandsNonPrivateElementARMShift = 4, + SpvTensorOperandsMax = 0x7fffffff, +} SpvTensorOperandsShift; + +typedef enum SpvTensorOperandsMask_ { + SpvTensorOperandsMaskNone = 0, + SpvTensorOperandsNontemporalARMMask = 0x00000001, + SpvTensorOperandsOutOfBoundsValueARMMask = 0x00000002, + SpvTensorOperandsMakeElementAvailableARMMask = 0x00000004, + SpvTensorOperandsMakeElementVisibleARMMask = 0x00000008, + SpvTensorOperandsNonPrivateElementARMMask = 0x00000010, +} SpvTensorOperandsMask; + +typedef enum SpvInitializationModeQualifier_ { + SpvInitializationModeQualifierInitOnDeviceReprogramINTEL = 0, + SpvInitializationModeQualifierInitOnDeviceResetINTEL = 1, + SpvInitializationModeQualifierMax = 0x7fffffff, +} SpvInitializationModeQualifier; + +typedef enum SpvHostAccessQualifier_ { + SpvHostAccessQualifierNoneINTEL = 0, + SpvHostAccessQualifierReadINTEL = 1, + SpvHostAccessQualifierWriteINTEL = 2, + SpvHostAccessQualifierReadWriteINTEL = 3, + SpvHostAccessQualifierMax = 0x7fffffff, +} SpvHostAccessQualifier; + +typedef enum SpvLoadCacheControl_ { + SpvLoadCacheControlUncachedINTEL = 0, + SpvLoadCacheControlCachedINTEL = 1, + SpvLoadCacheControlStreamingINTEL = 2, + SpvLoadCacheControlInvalidateAfterReadINTEL = 3, + SpvLoadCacheControlConstCachedINTEL = 4, + SpvLoadCacheControlMax = 0x7fffffff, +} SpvLoadCacheControl; + +typedef enum SpvStoreCacheControl_ { + SpvStoreCacheControlUncachedINTEL = 0, + SpvStoreCacheControlWriteThroughINTEL = 1, + SpvStoreCacheControlWriteBackINTEL = 2, + SpvStoreCacheControlStreamingINTEL = 3, + SpvStoreCacheControlMax = 0x7fffffff, +} SpvStoreCacheControl; + +typedef enum SpvNamedMaximumNumberOfRegisters_ { + SpvNamedMaximumNumberOfRegistersAutoINTEL = 0, + SpvNamedMaximumNumberOfRegistersMax = 0x7fffffff, +} SpvNamedMaximumNumberOfRegisters; + +typedef enum SpvMatrixMultiplyAccumulateOperandsShift_ { + SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELShift = 0, + SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELShift = 1, + SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELShift = 2, + SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELShift = 3, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELShift = 4, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELShift = 5, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELShift = 6, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELShift = 7, + SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELShift = 8, + SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELShift = 9, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELShift = 10, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELShift = 11, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELShift = 12, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELShift = 13, + SpvMatrixMultiplyAccumulateOperandsMax = 0x7fffffff, +} SpvMatrixMultiplyAccumulateOperandsShift; + +typedef enum SpvMatrixMultiplyAccumulateOperandsMask_ { + SpvMatrixMultiplyAccumulateOperandsMaskNone = 0, + SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELMask = 0x00000001, + SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELMask = 0x00000002, + SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELMask = 0x00000004, + SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELMask = 0x00000008, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELMask = 0x00000010, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELMask = 0x00000020, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELMask = 0x00000040, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELMask = 0x00000080, + SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELMask = 0x00000100, + SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELMask = 0x00000200, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELMask = 0x00000400, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELMask = 0x00000800, + SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELMask = 0x00001000, + SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELMask = 0x00002000, +} SpvMatrixMultiplyAccumulateOperandsMask; + +typedef enum SpvRawAccessChainOperandsShift_ { + SpvRawAccessChainOperandsRobustnessPerComponentNVShift = 0, + SpvRawAccessChainOperandsRobustnessPerElementNVShift = 1, + SpvRawAccessChainOperandsMax = 0x7fffffff, +} SpvRawAccessChainOperandsShift; + +typedef enum SpvRawAccessChainOperandsMask_ { + SpvRawAccessChainOperandsMaskNone = 0, + SpvRawAccessChainOperandsRobustnessPerComponentNVMask = 0x00000001, + SpvRawAccessChainOperandsRobustnessPerElementNVMask = 0x00000002, +} SpvRawAccessChainOperandsMask; + +typedef enum SpvFPEncoding_ { + SpvFPEncodingBFloat16KHR = 0, + SpvFPEncodingFloat8E4M3EXT = 4214, + SpvFPEncodingFloat8E5M2EXT = 4215, + SpvFPEncodingMax = 0x7fffffff, +} SpvFPEncoding; + +typedef enum SpvCooperativeVectorMatrixLayout_ { + SpvCooperativeVectorMatrixLayoutRowMajorNV = 0, + SpvCooperativeVectorMatrixLayoutColumnMajorNV = 1, + SpvCooperativeVectorMatrixLayoutInferencingOptimalNV = 2, + SpvCooperativeVectorMatrixLayoutTrainingOptimalNV = 3, + SpvCooperativeVectorMatrixLayoutMax = 0x7fffffff, +} SpvCooperativeVectorMatrixLayout; + +typedef enum SpvComponentType_ { + SpvComponentTypeFloat16NV = 0, + SpvComponentTypeFloat32NV = 1, + SpvComponentTypeFloat64NV = 2, + SpvComponentTypeSignedInt8NV = 3, + SpvComponentTypeSignedInt16NV = 4, + SpvComponentTypeSignedInt32NV = 5, + SpvComponentTypeSignedInt64NV = 6, + SpvComponentTypeUnsignedInt8NV = 7, + SpvComponentTypeUnsignedInt16NV = 8, + SpvComponentTypeUnsignedInt32NV = 9, + SpvComponentTypeUnsignedInt64NV = 10, + SpvComponentTypeSignedInt8PackedNV = 1000491000, + SpvComponentTypeUnsignedInt8PackedNV = 1000491001, + SpvComponentTypeFloatE4M3NV = 1000491002, + SpvComponentTypeFloatE5M2NV = 1000491003, + SpvComponentTypeMax = 0x7fffffff, +} SpvComponentType; + +typedef enum SpvOp_ { + SpvOpNop = 0, + SpvOpUndef = 1, + SpvOpSourceContinued = 2, + SpvOpSource = 3, + SpvOpSourceExtension = 4, + SpvOpName = 5, + SpvOpMemberName = 6, + SpvOpString = 7, + SpvOpLine = 8, + SpvOpExtension = 10, + SpvOpExtInstImport = 11, + SpvOpExtInst = 12, + SpvOpMemoryModel = 14, + SpvOpEntryPoint = 15, + SpvOpExecutionMode = 16, + SpvOpCapability = 17, + SpvOpTypeVoid = 19, + SpvOpTypeBool = 20, + SpvOpTypeInt = 21, + SpvOpTypeFloat = 22, + SpvOpTypeVector = 23, + SpvOpTypeMatrix = 24, + SpvOpTypeImage = 25, + SpvOpTypeSampler = 26, + SpvOpTypeSampledImage = 27, + SpvOpTypeArray = 28, + SpvOpTypeRuntimeArray = 29, + SpvOpTypeStruct = 30, + SpvOpTypeOpaque = 31, + SpvOpTypePointer = 32, + SpvOpTypeFunction = 33, + SpvOpTypeEvent = 34, + SpvOpTypeDeviceEvent = 35, + SpvOpTypeReserveId = 36, + SpvOpTypeQueue = 37, + SpvOpTypePipe = 38, + SpvOpTypeForwardPointer = 39, + SpvOpConstantTrue = 41, + SpvOpConstantFalse = 42, + SpvOpConstant = 43, + SpvOpConstantComposite = 44, + SpvOpConstantSampler = 45, + SpvOpConstantNull = 46, + SpvOpSpecConstantTrue = 48, + SpvOpSpecConstantFalse = 49, + SpvOpSpecConstant = 50, + SpvOpSpecConstantComposite = 51, + SpvOpSpecConstantOp = 52, + SpvOpFunction = 54, + SpvOpFunctionParameter = 55, + SpvOpFunctionEnd = 56, + SpvOpFunctionCall = 57, + SpvOpVariable = 59, + SpvOpImageTexelPointer = 60, + SpvOpLoad = 61, + SpvOpStore = 62, + SpvOpCopyMemory = 63, + SpvOpCopyMemorySized = 64, + SpvOpAccessChain = 65, + SpvOpInBoundsAccessChain = 66, + SpvOpPtrAccessChain = 67, + SpvOpArrayLength = 68, + SpvOpGenericPtrMemSemantics = 69, + SpvOpInBoundsPtrAccessChain = 70, + SpvOpDecorate = 71, + SpvOpMemberDecorate = 72, + SpvOpDecorationGroup = 73, + SpvOpGroupDecorate = 74, + SpvOpGroupMemberDecorate = 75, + SpvOpVectorExtractDynamic = 77, + SpvOpVectorInsertDynamic = 78, + SpvOpVectorShuffle = 79, + SpvOpCompositeConstruct = 80, + SpvOpCompositeExtract = 81, + SpvOpCompositeInsert = 82, + SpvOpCopyObject = 83, + SpvOpTranspose = 84, + SpvOpSampledImage = 86, + SpvOpImageSampleImplicitLod = 87, + SpvOpImageSampleExplicitLod = 88, + SpvOpImageSampleDrefImplicitLod = 89, + SpvOpImageSampleDrefExplicitLod = 90, + SpvOpImageSampleProjImplicitLod = 91, + SpvOpImageSampleProjExplicitLod = 92, + SpvOpImageSampleProjDrefImplicitLod = 93, + SpvOpImageSampleProjDrefExplicitLod = 94, + SpvOpImageFetch = 95, + SpvOpImageGather = 96, + SpvOpImageDrefGather = 97, + SpvOpImageRead = 98, + SpvOpImageWrite = 99, + SpvOpImage = 100, + SpvOpImageQueryFormat = 101, + SpvOpImageQueryOrder = 102, + SpvOpImageQuerySizeLod = 103, + SpvOpImageQuerySize = 104, + SpvOpImageQueryLod = 105, + SpvOpImageQueryLevels = 106, + SpvOpImageQuerySamples = 107, + SpvOpConvertFToU = 109, + SpvOpConvertFToS = 110, + SpvOpConvertSToF = 111, + SpvOpConvertUToF = 112, + SpvOpUConvert = 113, + SpvOpSConvert = 114, + SpvOpFConvert = 115, + SpvOpQuantizeToF16 = 116, + SpvOpConvertPtrToU = 117, + SpvOpSatConvertSToU = 118, + SpvOpSatConvertUToS = 119, + SpvOpConvertUToPtr = 120, + SpvOpPtrCastToGeneric = 121, + SpvOpGenericCastToPtr = 122, + SpvOpGenericCastToPtrExplicit = 123, + SpvOpBitcast = 124, + SpvOpSNegate = 126, + SpvOpFNegate = 127, + SpvOpIAdd = 128, + SpvOpFAdd = 129, + SpvOpISub = 130, + SpvOpFSub = 131, + SpvOpIMul = 132, + SpvOpFMul = 133, + SpvOpUDiv = 134, + SpvOpSDiv = 135, + SpvOpFDiv = 136, + SpvOpUMod = 137, + SpvOpSRem = 138, + SpvOpSMod = 139, + SpvOpFRem = 140, + SpvOpFMod = 141, + SpvOpVectorTimesScalar = 142, + SpvOpMatrixTimesScalar = 143, + SpvOpVectorTimesMatrix = 144, + SpvOpMatrixTimesVector = 145, + SpvOpMatrixTimesMatrix = 146, + SpvOpOuterProduct = 147, + SpvOpDot = 148, + SpvOpIAddCarry = 149, + SpvOpISubBorrow = 150, + SpvOpUMulExtended = 151, + SpvOpSMulExtended = 152, + SpvOpAny = 154, + SpvOpAll = 155, + SpvOpIsNan = 156, + SpvOpIsInf = 157, + SpvOpIsFinite = 158, + SpvOpIsNormal = 159, + SpvOpSignBitSet = 160, + SpvOpLessOrGreater = 161, + SpvOpOrdered = 162, + SpvOpUnordered = 163, + SpvOpLogicalEqual = 164, + SpvOpLogicalNotEqual = 165, + SpvOpLogicalOr = 166, + SpvOpLogicalAnd = 167, + SpvOpLogicalNot = 168, + SpvOpSelect = 169, + SpvOpIEqual = 170, + SpvOpINotEqual = 171, + SpvOpUGreaterThan = 172, + SpvOpSGreaterThan = 173, + SpvOpUGreaterThanEqual = 174, + SpvOpSGreaterThanEqual = 175, + SpvOpULessThan = 176, + SpvOpSLessThan = 177, + SpvOpULessThanEqual = 178, + SpvOpSLessThanEqual = 179, + SpvOpFOrdEqual = 180, + SpvOpFUnordEqual = 181, + SpvOpFOrdNotEqual = 182, + SpvOpFUnordNotEqual = 183, + SpvOpFOrdLessThan = 184, + SpvOpFUnordLessThan = 185, + SpvOpFOrdGreaterThan = 186, + SpvOpFUnordGreaterThan = 187, + SpvOpFOrdLessThanEqual = 188, + SpvOpFUnordLessThanEqual = 189, + SpvOpFOrdGreaterThanEqual = 190, + SpvOpFUnordGreaterThanEqual = 191, + SpvOpShiftRightLogical = 194, + SpvOpShiftRightArithmetic = 195, + SpvOpShiftLeftLogical = 196, + SpvOpBitwiseOr = 197, + SpvOpBitwiseXor = 198, + SpvOpBitwiseAnd = 199, + SpvOpNot = 200, + SpvOpBitFieldInsert = 201, + SpvOpBitFieldSExtract = 202, + SpvOpBitFieldUExtract = 203, + SpvOpBitReverse = 204, + SpvOpBitCount = 205, + SpvOpDPdx = 207, + SpvOpDPdy = 208, + SpvOpFwidth = 209, + SpvOpDPdxFine = 210, + SpvOpDPdyFine = 211, + SpvOpFwidthFine = 212, + SpvOpDPdxCoarse = 213, + SpvOpDPdyCoarse = 214, + SpvOpFwidthCoarse = 215, + SpvOpEmitVertex = 218, + SpvOpEndPrimitive = 219, + SpvOpEmitStreamVertex = 220, + SpvOpEndStreamPrimitive = 221, + SpvOpControlBarrier = 224, + SpvOpMemoryBarrier = 225, + SpvOpAtomicLoad = 227, + SpvOpAtomicStore = 228, + SpvOpAtomicExchange = 229, + SpvOpAtomicCompareExchange = 230, + SpvOpAtomicCompareExchangeWeak = 231, + SpvOpAtomicIIncrement = 232, + SpvOpAtomicIDecrement = 233, + SpvOpAtomicIAdd = 234, + SpvOpAtomicISub = 235, + SpvOpAtomicSMin = 236, + SpvOpAtomicUMin = 237, + SpvOpAtomicSMax = 238, + SpvOpAtomicUMax = 239, + SpvOpAtomicAnd = 240, + SpvOpAtomicOr = 241, + SpvOpAtomicXor = 242, + SpvOpPhi = 245, + SpvOpLoopMerge = 246, + SpvOpSelectionMerge = 247, + SpvOpLabel = 248, + SpvOpBranch = 249, + SpvOpBranchConditional = 250, + SpvOpSwitch = 251, + SpvOpKill = 252, + SpvOpReturn = 253, + SpvOpReturnValue = 254, + SpvOpUnreachable = 255, + SpvOpLifetimeStart = 256, + SpvOpLifetimeStop = 257, + SpvOpGroupAsyncCopy = 259, + SpvOpGroupWaitEvents = 260, + SpvOpGroupAll = 261, + SpvOpGroupAny = 262, + SpvOpGroupBroadcast = 263, + SpvOpGroupIAdd = 264, + SpvOpGroupFAdd = 265, + SpvOpGroupFMin = 266, + SpvOpGroupUMin = 267, + SpvOpGroupSMin = 268, + SpvOpGroupFMax = 269, + SpvOpGroupUMax = 270, + SpvOpGroupSMax = 271, + SpvOpReadPipe = 274, + SpvOpWritePipe = 275, + SpvOpReservedReadPipe = 276, + SpvOpReservedWritePipe = 277, + SpvOpReserveReadPipePackets = 278, + SpvOpReserveWritePipePackets = 279, + SpvOpCommitReadPipe = 280, + SpvOpCommitWritePipe = 281, + SpvOpIsValidReserveId = 282, + SpvOpGetNumPipePackets = 283, + SpvOpGetMaxPipePackets = 284, + SpvOpGroupReserveReadPipePackets = 285, + SpvOpGroupReserveWritePipePackets = 286, + SpvOpGroupCommitReadPipe = 287, + SpvOpGroupCommitWritePipe = 288, + SpvOpEnqueueMarker = 291, + SpvOpEnqueueKernel = 292, + SpvOpGetKernelNDrangeSubGroupCount = 293, + SpvOpGetKernelNDrangeMaxSubGroupSize = 294, + SpvOpGetKernelWorkGroupSize = 295, + SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296, + SpvOpRetainEvent = 297, + SpvOpReleaseEvent = 298, + SpvOpCreateUserEvent = 299, + SpvOpIsValidEvent = 300, + SpvOpSetUserEventStatus = 301, + SpvOpCaptureEventProfilingInfo = 302, + SpvOpGetDefaultQueue = 303, + SpvOpBuildNDRange = 304, + SpvOpImageSparseSampleImplicitLod = 305, + SpvOpImageSparseSampleExplicitLod = 306, + SpvOpImageSparseSampleDrefImplicitLod = 307, + SpvOpImageSparseSampleDrefExplicitLod = 308, + SpvOpImageSparseSampleProjImplicitLod = 309, + SpvOpImageSparseSampleProjExplicitLod = 310, + SpvOpImageSparseSampleProjDrefImplicitLod = 311, + SpvOpImageSparseSampleProjDrefExplicitLod = 312, + SpvOpImageSparseFetch = 313, + SpvOpImageSparseGather = 314, + SpvOpImageSparseDrefGather = 315, + SpvOpImageSparseTexelsResident = 316, + SpvOpNoLine = 317, + SpvOpAtomicFlagTestAndSet = 318, + SpvOpAtomicFlagClear = 319, + SpvOpImageSparseRead = 320, + SpvOpSizeOf = 321, + SpvOpTypePipeStorage = 322, + SpvOpConstantPipeStorage = 323, + SpvOpCreatePipeFromPipeStorage = 324, + SpvOpGetKernelLocalSizeForSubgroupCount = 325, + SpvOpGetKernelMaxNumSubgroups = 326, + SpvOpTypeNamedBarrier = 327, + SpvOpNamedBarrierInitialize = 328, + SpvOpMemoryNamedBarrier = 329, + SpvOpModuleProcessed = 330, + SpvOpExecutionModeId = 331, + SpvOpDecorateId = 332, + SpvOpGroupNonUniformElect = 333, + SpvOpGroupNonUniformAll = 334, + SpvOpGroupNonUniformAny = 335, + SpvOpGroupNonUniformAllEqual = 336, + SpvOpGroupNonUniformBroadcast = 337, + SpvOpGroupNonUniformBroadcastFirst = 338, + SpvOpGroupNonUniformBallot = 339, + SpvOpGroupNonUniformInverseBallot = 340, + SpvOpGroupNonUniformBallotBitExtract = 341, + SpvOpGroupNonUniformBallotBitCount = 342, + SpvOpGroupNonUniformBallotFindLSB = 343, + SpvOpGroupNonUniformBallotFindMSB = 344, + SpvOpGroupNonUniformShuffle = 345, + SpvOpGroupNonUniformShuffleXor = 346, + SpvOpGroupNonUniformShuffleUp = 347, + SpvOpGroupNonUniformShuffleDown = 348, + SpvOpGroupNonUniformIAdd = 349, + SpvOpGroupNonUniformFAdd = 350, + SpvOpGroupNonUniformIMul = 351, + SpvOpGroupNonUniformFMul = 352, + SpvOpGroupNonUniformSMin = 353, + SpvOpGroupNonUniformUMin = 354, + SpvOpGroupNonUniformFMin = 355, + SpvOpGroupNonUniformSMax = 356, + SpvOpGroupNonUniformUMax = 357, + SpvOpGroupNonUniformFMax = 358, + SpvOpGroupNonUniformBitwiseAnd = 359, + SpvOpGroupNonUniformBitwiseOr = 360, + SpvOpGroupNonUniformBitwiseXor = 361, + SpvOpGroupNonUniformLogicalAnd = 362, + SpvOpGroupNonUniformLogicalOr = 363, + SpvOpGroupNonUniformLogicalXor = 364, + SpvOpGroupNonUniformQuadBroadcast = 365, + SpvOpGroupNonUniformQuadSwap = 366, + SpvOpCopyLogical = 400, + SpvOpPtrEqual = 401, + SpvOpPtrNotEqual = 402, + SpvOpPtrDiff = 403, + SpvOpColorAttachmentReadEXT = 4160, + SpvOpDepthAttachmentReadEXT = 4161, + SpvOpStencilAttachmentReadEXT = 4162, + SpvOpTypeTensorARM = 4163, + SpvOpTensorReadARM = 4164, + SpvOpTensorWriteARM = 4165, + SpvOpTensorQuerySizeARM = 4166, + SpvOpGraphConstantARM = 4181, + SpvOpGraphEntryPointARM = 4182, + SpvOpGraphARM = 4183, + SpvOpGraphInputARM = 4184, + SpvOpGraphSetOutputARM = 4185, + SpvOpGraphEndARM = 4186, + SpvOpTypeGraphARM = 4190, + SpvOpTerminateInvocation = 4416, + SpvOpTypeUntypedPointerKHR = 4417, + SpvOpUntypedVariableKHR = 4418, + SpvOpUntypedAccessChainKHR = 4419, + SpvOpUntypedInBoundsAccessChainKHR = 4420, + SpvOpSubgroupBallotKHR = 4421, + SpvOpSubgroupFirstInvocationKHR = 4422, + SpvOpUntypedPtrAccessChainKHR = 4423, + SpvOpUntypedInBoundsPtrAccessChainKHR = 4424, + SpvOpUntypedArrayLengthKHR = 4425, + SpvOpUntypedPrefetchKHR = 4426, + SpvOpSubgroupAllKHR = 4428, + SpvOpSubgroupAnyKHR = 4429, + SpvOpSubgroupAllEqualKHR = 4430, + SpvOpGroupNonUniformRotateKHR = 4431, + SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpExtInstWithForwardRefsKHR = 4433, + SpvOpUntypedGroupAsyncCopyKHR = 4434, + SpvOpTraceRayKHR = 4445, + SpvOpExecuteCallableKHR = 4446, + SpvOpConvertUToAccelerationStructureKHR = 4447, + SpvOpIgnoreIntersectionKHR = 4448, + SpvOpTerminateRayKHR = 4449, + SpvOpSDot = 4450, + SpvOpSDotKHR = 4450, + SpvOpUDot = 4451, + SpvOpUDotKHR = 4451, + SpvOpSUDot = 4452, + SpvOpSUDotKHR = 4452, + SpvOpSDotAccSat = 4453, + SpvOpSDotAccSatKHR = 4453, + SpvOpUDotAccSat = 4454, + SpvOpUDotAccSatKHR = 4454, + SpvOpSUDotAccSat = 4455, + SpvOpSUDotAccSatKHR = 4455, + SpvOpTypeCooperativeMatrixKHR = 4456, + SpvOpCooperativeMatrixLoadKHR = 4457, + SpvOpCooperativeMatrixStoreKHR = 4458, + SpvOpCooperativeMatrixMulAddKHR = 4459, + SpvOpCooperativeMatrixLengthKHR = 4460, + SpvOpConstantCompositeReplicateEXT = 4461, + SpvOpSpecConstantCompositeReplicateEXT = 4462, + SpvOpCompositeConstructReplicateEXT = 4463, + SpvOpTypeRayQueryKHR = 4472, + SpvOpRayQueryInitializeKHR = 4473, + SpvOpRayQueryTerminateKHR = 4474, + SpvOpRayQueryGenerateIntersectionKHR = 4475, + SpvOpRayQueryConfirmIntersectionKHR = 4476, + SpvOpRayQueryProceedKHR = 4477, + SpvOpRayQueryGetIntersectionTypeKHR = 4479, + SpvOpImageSampleWeightedQCOM = 4480, + SpvOpImageBoxFilterQCOM = 4481, + SpvOpImageBlockMatchSSDQCOM = 4482, + SpvOpImageBlockMatchSADQCOM = 4483, + SpvOpBitCastArrayQCOM = 4497, + SpvOpImageBlockMatchWindowSSDQCOM = 4500, + SpvOpImageBlockMatchWindowSADQCOM = 4501, + SpvOpImageBlockMatchGatherSSDQCOM = 4502, + SpvOpImageBlockMatchGatherSADQCOM = 4503, + SpvOpCompositeConstructCoopMatQCOM = 4540, + SpvOpCompositeExtractCoopMatQCOM = 4541, + SpvOpExtractSubArrayQCOM = 4542, + SpvOpGroupIAddNonUniformAMD = 5000, + SpvOpGroupFAddNonUniformAMD = 5001, + SpvOpGroupFMinNonUniformAMD = 5002, + SpvOpGroupUMinNonUniformAMD = 5003, + SpvOpGroupSMinNonUniformAMD = 5004, + SpvOpGroupFMaxNonUniformAMD = 5005, + SpvOpGroupUMaxNonUniformAMD = 5006, + SpvOpGroupSMaxNonUniformAMD = 5007, + SpvOpFragmentMaskFetchAMD = 5011, + SpvOpFragmentFetchAMD = 5012, + SpvOpReadClockKHR = 5056, + SpvOpAllocateNodePayloadsAMDX = 5074, + SpvOpEnqueueNodePayloadsAMDX = 5075, + SpvOpTypeNodePayloadArrayAMDX = 5076, + SpvOpFinishWritingNodePayloadAMDX = 5078, + SpvOpNodePayloadArrayLengthAMDX = 5090, + SpvOpIsNodePayloadValidAMDX = 5101, + SpvOpConstantStringAMDX = 5103, + SpvOpSpecConstantStringAMDX = 5104, + SpvOpGroupNonUniformQuadAllKHR = 5110, + SpvOpGroupNonUniformQuadAnyKHR = 5111, + SpvOpHitObjectRecordHitMotionNV = 5249, + SpvOpHitObjectRecordHitWithIndexMotionNV = 5250, + SpvOpHitObjectRecordMissMotionNV = 5251, + SpvOpHitObjectGetWorldToObjectNV = 5252, + SpvOpHitObjectGetObjectToWorldNV = 5253, + SpvOpHitObjectGetObjectRayDirectionNV = 5254, + SpvOpHitObjectGetObjectRayOriginNV = 5255, + SpvOpHitObjectTraceRayMotionNV = 5256, + SpvOpHitObjectGetShaderRecordBufferHandleNV = 5257, + SpvOpHitObjectGetShaderBindingTableRecordIndexNV = 5258, + SpvOpHitObjectRecordEmptyNV = 5259, + SpvOpHitObjectTraceRayNV = 5260, + SpvOpHitObjectRecordHitNV = 5261, + SpvOpHitObjectRecordHitWithIndexNV = 5262, + SpvOpHitObjectRecordMissNV = 5263, + SpvOpHitObjectExecuteShaderNV = 5264, + SpvOpHitObjectGetCurrentTimeNV = 5265, + SpvOpHitObjectGetAttributesNV = 5266, + SpvOpHitObjectGetHitKindNV = 5267, + SpvOpHitObjectGetPrimitiveIndexNV = 5268, + SpvOpHitObjectGetGeometryIndexNV = 5269, + SpvOpHitObjectGetInstanceIdNV = 5270, + SpvOpHitObjectGetInstanceCustomIndexNV = 5271, + SpvOpHitObjectGetWorldRayDirectionNV = 5272, + SpvOpHitObjectGetWorldRayOriginNV = 5273, + SpvOpHitObjectGetRayTMaxNV = 5274, + SpvOpHitObjectGetRayTMinNV = 5275, + SpvOpHitObjectIsEmptyNV = 5276, + SpvOpHitObjectIsHitNV = 5277, + SpvOpHitObjectIsMissNV = 5278, + SpvOpReorderThreadWithHitObjectNV = 5279, + SpvOpReorderThreadWithHintNV = 5280, + SpvOpTypeHitObjectNV = 5281, + SpvOpImageSampleFootprintNV = 5283, + SpvOpTypeCooperativeVectorNV = 5288, + SpvOpCooperativeVectorMatrixMulNV = 5289, + SpvOpCooperativeVectorOuterProductAccumulateNV = 5290, + SpvOpCooperativeVectorReduceSumAccumulateNV = 5291, + SpvOpCooperativeVectorMatrixMulAddNV = 5292, + SpvOpCooperativeMatrixConvertNV = 5293, + SpvOpEmitMeshTasksEXT = 5294, + SpvOpSetMeshOutputsEXT = 5295, + SpvOpGroupNonUniformPartitionNV = 5296, + SpvOpWritePackedPrimitiveIndices4x8NV = 5299, + SpvOpFetchMicroTriangleVertexPositionNV = 5300, + SpvOpFetchMicroTriangleVertexBarycentricNV = 5301, + SpvOpCooperativeVectorLoadNV = 5302, + SpvOpCooperativeVectorStoreNV = 5303, + SpvOpReportIntersectionKHR = 5334, + SpvOpReportIntersectionNV = 5334, + SpvOpIgnoreIntersectionNV = 5335, + SpvOpTerminateRayNV = 5336, + SpvOpTraceNV = 5337, + SpvOpTraceMotionNV = 5338, + SpvOpTraceRayMotionNV = 5339, + SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR = 5340, + SpvOpTypeAccelerationStructureKHR = 5341, + SpvOpTypeAccelerationStructureNV = 5341, + SpvOpExecuteCallableNV = 5344, + SpvOpRayQueryGetClusterIdNV = 5345, + SpvOpRayQueryGetIntersectionClusterIdNV = 5345, + SpvOpHitObjectGetClusterIdNV = 5346, + SpvOpTypeCooperativeMatrixNV = 5358, + SpvOpCooperativeMatrixLoadNV = 5359, + SpvOpCooperativeMatrixStoreNV = 5360, + SpvOpCooperativeMatrixMulAddNV = 5361, + SpvOpCooperativeMatrixLengthNV = 5362, + SpvOpBeginInvocationInterlockEXT = 5364, + SpvOpEndInvocationInterlockEXT = 5365, + SpvOpCooperativeMatrixReduceNV = 5366, + SpvOpCooperativeMatrixLoadTensorNV = 5367, + SpvOpCooperativeMatrixStoreTensorNV = 5368, + SpvOpCooperativeMatrixPerElementOpNV = 5369, + SpvOpTypeTensorLayoutNV = 5370, + SpvOpTypeTensorViewNV = 5371, + SpvOpCreateTensorLayoutNV = 5372, + SpvOpTensorLayoutSetDimensionNV = 5373, + SpvOpTensorLayoutSetStrideNV = 5374, + SpvOpTensorLayoutSliceNV = 5375, + SpvOpTensorLayoutSetClampValueNV = 5376, + SpvOpCreateTensorViewNV = 5377, + SpvOpTensorViewSetDimensionNV = 5378, + SpvOpTensorViewSetStrideNV = 5379, + SpvOpDemoteToHelperInvocation = 5380, + SpvOpDemoteToHelperInvocationEXT = 5380, + SpvOpIsHelperInvocationEXT = 5381, + SpvOpTensorViewSetClipNV = 5382, + SpvOpTensorLayoutSetBlockSizeNV = 5384, + SpvOpCooperativeMatrixTransposeNV = 5390, + SpvOpConvertUToImageNV = 5391, + SpvOpConvertUToSamplerNV = 5392, + SpvOpConvertImageToUNV = 5393, + SpvOpConvertSamplerToUNV = 5394, + SpvOpConvertUToSampledImageNV = 5395, + SpvOpConvertSampledImageToUNV = 5396, + SpvOpSamplerImageAddressingModeNV = 5397, + SpvOpRawAccessChainNV = 5398, + SpvOpRayQueryGetIntersectionSpherePositionNV = 5427, + SpvOpRayQueryGetIntersectionSphereRadiusNV = 5428, + SpvOpRayQueryGetIntersectionLSSPositionsNV = 5429, + SpvOpRayQueryGetIntersectionLSSRadiiNV = 5430, + SpvOpRayQueryGetIntersectionLSSHitValueNV = 5431, + SpvOpHitObjectGetSpherePositionNV = 5432, + SpvOpHitObjectGetSphereRadiusNV = 5433, + SpvOpHitObjectGetLSSPositionsNV = 5434, + SpvOpHitObjectGetLSSRadiiNV = 5435, + SpvOpHitObjectIsSphereHitNV = 5436, + SpvOpHitObjectIsLSSHitNV = 5437, + SpvOpRayQueryIsSphereHitNV = 5438, + SpvOpRayQueryIsLSSHitNV = 5439, + SpvOpSubgroupShuffleINTEL = 5571, + SpvOpSubgroupShuffleDownINTEL = 5572, + SpvOpSubgroupShuffleUpINTEL = 5573, + SpvOpSubgroupShuffleXorINTEL = 5574, + SpvOpSubgroupBlockReadINTEL = 5575, + SpvOpSubgroupBlockWriteINTEL = 5576, + SpvOpSubgroupImageBlockReadINTEL = 5577, + SpvOpSubgroupImageBlockWriteINTEL = 5578, + SpvOpSubgroupImageMediaBlockReadINTEL = 5580, + SpvOpSubgroupImageMediaBlockWriteINTEL = 5581, + SpvOpUCountLeadingZerosINTEL = 5585, + SpvOpUCountTrailingZerosINTEL = 5586, + SpvOpAbsISubINTEL = 5587, + SpvOpAbsUSubINTEL = 5588, + SpvOpIAddSatINTEL = 5589, + SpvOpUAddSatINTEL = 5590, + SpvOpIAverageINTEL = 5591, + SpvOpUAverageINTEL = 5592, + SpvOpIAverageRoundedINTEL = 5593, + SpvOpUAverageRoundedINTEL = 5594, + SpvOpISubSatINTEL = 5595, + SpvOpUSubSatINTEL = 5596, + SpvOpIMul32x16INTEL = 5597, + SpvOpUMul32x16INTEL = 5598, + SpvOpConstantFunctionPointerINTEL = 5600, + SpvOpFunctionPointerCallINTEL = 5601, + SpvOpAsmTargetINTEL = 5609, + SpvOpAsmINTEL = 5610, + SpvOpAsmCallINTEL = 5611, + SpvOpAtomicFMinEXT = 5614, + SpvOpAtomicFMaxEXT = 5615, + SpvOpAssumeTrueKHR = 5630, + SpvOpExpectKHR = 5631, + SpvOpDecorateString = 5632, + SpvOpDecorateStringGOOGLE = 5632, + SpvOpMemberDecorateString = 5633, + SpvOpMemberDecorateStringGOOGLE = 5633, + SpvOpVmeImageINTEL = 5699, + SpvOpTypeVmeImageINTEL = 5700, + SpvOpTypeAvcImePayloadINTEL = 5701, + SpvOpTypeAvcRefPayloadINTEL = 5702, + SpvOpTypeAvcSicPayloadINTEL = 5703, + SpvOpTypeAvcMcePayloadINTEL = 5704, + SpvOpTypeAvcMceResultINTEL = 5705, + SpvOpTypeAvcImeResultINTEL = 5706, + SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710, + SpvOpTypeAvcRefResultINTEL = 5711, + SpvOpTypeAvcSicResultINTEL = 5712, + SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733, + SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735, + SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737, + SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + SpvOpSubgroupAvcImeInitializeINTEL = 5747, + SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749, + SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750, + SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765, + SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776, + SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + SpvOpSubgroupAvcFmeInitializeINTEL = 5781, + SpvOpSubgroupAvcBmeInitializeINTEL = 5782, + SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790, + SpvOpSubgroupAvcSicInitializeINTEL = 5791, + SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792, + SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803, + SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808, + SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + SpvOpVariableLengthArrayINTEL = 5818, + SpvOpSaveMemoryINTEL = 5819, + SpvOpRestoreMemoryINTEL = 5820, + SpvOpArbitraryFloatSinCosPiINTEL = 5840, + SpvOpArbitraryFloatCastINTEL = 5841, + SpvOpArbitraryFloatCastFromIntINTEL = 5842, + SpvOpArbitraryFloatCastToIntINTEL = 5843, + SpvOpArbitraryFloatAddINTEL = 5846, + SpvOpArbitraryFloatSubINTEL = 5847, + SpvOpArbitraryFloatMulINTEL = 5848, + SpvOpArbitraryFloatDivINTEL = 5849, + SpvOpArbitraryFloatGTINTEL = 5850, + SpvOpArbitraryFloatGEINTEL = 5851, + SpvOpArbitraryFloatLTINTEL = 5852, + SpvOpArbitraryFloatLEINTEL = 5853, + SpvOpArbitraryFloatEQINTEL = 5854, + SpvOpArbitraryFloatRecipINTEL = 5855, + SpvOpArbitraryFloatRSqrtINTEL = 5856, + SpvOpArbitraryFloatCbrtINTEL = 5857, + SpvOpArbitraryFloatHypotINTEL = 5858, + SpvOpArbitraryFloatSqrtINTEL = 5859, + SpvOpArbitraryFloatLogINTEL = 5860, + SpvOpArbitraryFloatLog2INTEL = 5861, + SpvOpArbitraryFloatLog10INTEL = 5862, + SpvOpArbitraryFloatLog1pINTEL = 5863, + SpvOpArbitraryFloatExpINTEL = 5864, + SpvOpArbitraryFloatExp2INTEL = 5865, + SpvOpArbitraryFloatExp10INTEL = 5866, + SpvOpArbitraryFloatExpm1INTEL = 5867, + SpvOpArbitraryFloatSinINTEL = 5868, + SpvOpArbitraryFloatCosINTEL = 5869, + SpvOpArbitraryFloatSinCosINTEL = 5870, + SpvOpArbitraryFloatSinPiINTEL = 5871, + SpvOpArbitraryFloatCosPiINTEL = 5872, + SpvOpArbitraryFloatASinINTEL = 5873, + SpvOpArbitraryFloatASinPiINTEL = 5874, + SpvOpArbitraryFloatACosINTEL = 5875, + SpvOpArbitraryFloatACosPiINTEL = 5876, + SpvOpArbitraryFloatATanINTEL = 5877, + SpvOpArbitraryFloatATanPiINTEL = 5878, + SpvOpArbitraryFloatATan2INTEL = 5879, + SpvOpArbitraryFloatPowINTEL = 5880, + SpvOpArbitraryFloatPowRINTEL = 5881, + SpvOpArbitraryFloatPowNINTEL = 5882, + SpvOpLoopControlINTEL = 5887, + SpvOpAliasDomainDeclINTEL = 5911, + SpvOpAliasScopeDeclINTEL = 5912, + SpvOpAliasScopeListDeclINTEL = 5913, + SpvOpFixedSqrtINTEL = 5923, + SpvOpFixedRecipINTEL = 5924, + SpvOpFixedRsqrtINTEL = 5925, + SpvOpFixedSinINTEL = 5926, + SpvOpFixedCosINTEL = 5927, + SpvOpFixedSinCosINTEL = 5928, + SpvOpFixedSinPiINTEL = 5929, + SpvOpFixedCosPiINTEL = 5930, + SpvOpFixedSinCosPiINTEL = 5931, + SpvOpFixedLogINTEL = 5932, + SpvOpFixedExpINTEL = 5933, + SpvOpPtrCastToCrossWorkgroupINTEL = 5934, + SpvOpCrossWorkgroupCastToPtrINTEL = 5938, + SpvOpReadPipeBlockingINTEL = 5946, + SpvOpWritePipeBlockingINTEL = 5947, + SpvOpFPGARegINTEL = 5949, + SpvOpRayQueryGetRayTMinKHR = 6016, + SpvOpRayQueryGetRayFlagsKHR = 6017, + SpvOpRayQueryGetIntersectionTKHR = 6018, + SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, + SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, + SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, + SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, + SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + SpvOpRayQueryGetWorldRayDirectionKHR = 6029, + SpvOpRayQueryGetWorldRayOriginKHR = 6030, + SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, + SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, + SpvOpAtomicFAddEXT = 6035, + SpvOpTypeBufferSurfaceINTEL = 6086, + SpvOpTypeStructContinuedINTEL = 6090, + SpvOpConstantCompositeContinuedINTEL = 6091, + SpvOpSpecConstantCompositeContinuedINTEL = 6092, + SpvOpCompositeConstructContinuedINTEL = 6096, + SpvOpConvertFToBF16INTEL = 6116, + SpvOpConvertBF16ToFINTEL = 6117, + SpvOpControlBarrierArriveINTEL = 6142, + SpvOpControlBarrierWaitINTEL = 6143, + SpvOpArithmeticFenceEXT = 6145, + SpvOpTaskSequenceCreateINTEL = 6163, + SpvOpTaskSequenceAsyncINTEL = 6164, + SpvOpTaskSequenceGetINTEL = 6165, + SpvOpTaskSequenceReleaseINTEL = 6166, + SpvOpTypeTaskSequenceINTEL = 6199, + SpvOpSubgroupBlockPrefetchINTEL = 6221, + SpvOpSubgroup2DBlockLoadINTEL = 6231, + SpvOpSubgroup2DBlockLoadTransformINTEL = 6232, + SpvOpSubgroup2DBlockLoadTransposeINTEL = 6233, + SpvOpSubgroup2DBlockPrefetchINTEL = 6234, + SpvOpSubgroup2DBlockStoreINTEL = 6235, + SpvOpSubgroupMatrixMultiplyAccumulateINTEL = 6237, + SpvOpBitwiseFunctionINTEL = 6242, + SpvOpUntypedVariableLengthArrayINTEL = 6244, + SpvOpConditionalExtensionINTEL = 6248, + SpvOpConditionalEntryPointINTEL = 6249, + SpvOpConditionalCapabilityINTEL = 6250, + SpvOpSpecConstantTargetINTEL = 6251, + SpvOpSpecConstantArchitectureINTEL = 6252, + SpvOpSpecConstantCapabilitiesINTEL = 6253, + SpvOpConditionalCopyObjectINTEL = 6254, + SpvOpGroupIMulKHR = 6401, + SpvOpGroupFMulKHR = 6402, + SpvOpGroupBitwiseAndKHR = 6403, + SpvOpGroupBitwiseOrKHR = 6404, + SpvOpGroupBitwiseXorKHR = 6405, + SpvOpGroupLogicalAndKHR = 6406, + SpvOpGroupLogicalOrKHR = 6407, + SpvOpGroupLogicalXorKHR = 6408, + SpvOpRoundFToTF32INTEL = 6426, + SpvOpMaskedGatherINTEL = 6428, + SpvOpMaskedScatterINTEL = 6429, + SpvOpConvertHandleToImageINTEL = 6529, + SpvOpConvertHandleToSamplerINTEL = 6530, + SpvOpConvertHandleToSampledImageINTEL = 6531, + SpvOpMax = 0x7fffffff, +} SpvOp; + +#ifdef SPV_ENABLE_UTILITY_CODE +#ifndef __cplusplus +#include +#endif +inline void SpvHasResultAndType(SpvOp opcode, bool* hasResult, bool* hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ + break; + case SpvOpNop: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpUndef: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSourceContinued: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSource: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSourceExtension: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpName: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpMemberName: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpString: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpLine: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExtension: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExtInstImport: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpExtInst: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMemoryModel: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEntryPoint: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExecutionMode: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCapability: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeVoid: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeBool: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeInt: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeFloat: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeVector: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeMatrix: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeImage: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeSampler: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeSampledImage: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeArray: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeRuntimeArray: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeStruct: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeOpaque: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypePointer: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeFunction: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeEvent: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeDeviceEvent: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeReserveId: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeQueue: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypePipe: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeForwardPointer: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConstantTrue: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantFalse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstant: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantComposite: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantSampler: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantNull: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantTrue: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantFalse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstant: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantComposite: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantOp: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFunction: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFunctionParameter: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFunctionEnd: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpFunctionCall: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVariable: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageTexelPointer: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLoad: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpStore: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCopyMemory: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCopyMemorySized: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpAccessChain: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpInBoundsAccessChain: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrAccessChain: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArrayLength: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGenericPtrMemSemantics: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpInBoundsPtrAccessChain: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDecorate: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpMemberDecorate: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpDecorationGroup: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpGroupDecorate: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupMemberDecorate: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpVectorExtractDynamic: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVectorInsertDynamic: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVectorShuffle: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeConstruct: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeExtract: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeInsert: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCopyObject: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTranspose: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSampledImage: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleDrefImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleDrefExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleProjImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleProjExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleProjDrefImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleProjDrefExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageFetch: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageGather: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageDrefGather: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageRead: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageWrite: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpImage: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQueryFormat: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQueryOrder: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQuerySizeLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQuerySize: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQueryLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQueryLevels: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageQuerySamples: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertFToU: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertFToS: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertSToF: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertUToF: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUConvert: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSConvert: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFConvert: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpQuantizeToF16: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertPtrToU: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSatConvertSToU: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSatConvertUToS: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertUToPtr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrCastToGeneric: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGenericCastToPtr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGenericCastToPtrExplicit: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitcast: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSNegate: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFNegate: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpISub: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFSub: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIMul: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFMul: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUDiv: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSDiv: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFDiv: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUMod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSRem: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSMod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFRem: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFMod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVectorTimesScalar: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMatrixTimesScalar: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVectorTimesMatrix: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMatrixTimesVector: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMatrixTimesMatrix: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpOuterProduct: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIAddCarry: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpISubBorrow: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUMulExtended: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSMulExtended: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAny: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAll: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsNan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsInf: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsFinite: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsNormal: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSignBitSet: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLessOrGreater: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpOrdered: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUnordered: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLogicalEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLogicalNotEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLogicalOr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLogicalAnd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLogicalNot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSelect: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpINotEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUGreaterThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSGreaterThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUGreaterThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSGreaterThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpULessThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSLessThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpULessThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSLessThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdNotEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordNotEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdLessThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordLessThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdGreaterThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordGreaterThan: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdLessThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordLessThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFOrdGreaterThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFUnordGreaterThanEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpShiftRightLogical: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpShiftRightArithmetic: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpShiftLeftLogical: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitwiseOr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitwiseXor: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitwiseAnd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpNot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitFieldInsert: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitFieldSExtract: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitFieldUExtract: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitReverse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitCount: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdx: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdy: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFwidth: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdxFine: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdyFine: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFwidthFine: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdxCoarse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDPdyCoarse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFwidthCoarse: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpEmitVertex: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEndPrimitive: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEmitStreamVertex: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEndStreamPrimitive: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpControlBarrier: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpMemoryBarrier: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpAtomicLoad: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicStore: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpAtomicExchange: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicCompareExchange: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicCompareExchangeWeak: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicIIncrement: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicIDecrement: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicIAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicISub: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicSMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicUMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicSMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicUMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicAnd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicOr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicXor: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPhi: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLoopMerge: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSelectionMerge: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpLabel: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpBranch: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpBranchConditional: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSwitch: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpKill: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpReturn: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpReturnValue: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpUnreachable: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpLifetimeStart: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpLifetimeStop: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupAsyncCopy: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupWaitEvents: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupAll: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupAny: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupBroadcast: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupIAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupUMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupSMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupUMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupSMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReadPipe: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpWritePipe: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReservedReadPipe: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReservedWritePipe: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReserveReadPipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReserveWritePipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCommitReadPipe: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCommitWritePipe: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpIsValidReserveId: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetNumPipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetMaxPipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupReserveReadPipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupReserveWritePipePackets: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupCommitReadPipe: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupCommitWritePipe: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEnqueueMarker: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpEnqueueKernel: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelNDrangeSubGroupCount: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelNDrangeMaxSubGroupSize: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelWorkGroupSize: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelPreferredWorkGroupSizeMultiple: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRetainEvent: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpReleaseEvent: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCreateUserEvent: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsValidEvent: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSetUserEventStatus: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCaptureEventProfilingInfo: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGetDefaultQueue: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBuildNDRange: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleDrefImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleDrefExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleProjImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleProjExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleProjDrefImplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseSampleProjDrefExplicitLod: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseFetch: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseGather: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseDrefGather: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSparseTexelsResident: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpNoLine: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpAtomicFlagTestAndSet: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicFlagClear: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpImageSparseRead: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSizeOf: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypePipeStorage: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpConstantPipeStorage: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCreatePipeFromPipeStorage: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelLocalSizeForSubgroupCount: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGetKernelMaxNumSubgroups: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeNamedBarrier: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpNamedBarrierInitialize: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMemoryNamedBarrier: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpModuleProcessed: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExecutionModeId: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpDecorateId: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupNonUniformElect: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformAll: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformAny: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformAllEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBroadcast: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBroadcastFirst: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBallot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformInverseBallot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBallotBitExtract: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBallotBitCount: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBallotFindLSB: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBallotFindMSB: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformShuffle: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformShuffleXor: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformShuffleUp: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformShuffleDown: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformIAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformFAdd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformIMul: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformFMul: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformSMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformUMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformFMin: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformSMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformUMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformFMax: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBitwiseAnd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBitwiseOr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformBitwiseXor: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformLogicalAnd: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformLogicalOr: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformLogicalXor: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformQuadBroadcast: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformQuadSwap: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCopyLogical: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrNotEqual: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrDiff: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpColorAttachmentReadEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDepthAttachmentReadEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpStencilAttachmentReadEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeTensorARM: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTensorReadARM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorWriteARM: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTensorQuerySizeARM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGraphConstantARM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGraphEntryPointARM: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGraphARM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGraphInputARM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGraphSetOutputARM: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGraphEndARM: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeGraphARM: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTerminateInvocation: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeUntypedPointerKHR: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpUntypedVariableKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedAccessChainKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedInBoundsAccessChainKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupBallotKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupFirstInvocationKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedPtrAccessChainKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedInBoundsPtrAccessChainKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedArrayLengthKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedPrefetchKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroupAllKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAnyKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAllEqualKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformRotateKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupReadInvocationKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpExtInstWithForwardRefsKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedGroupAsyncCopyKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTraceRayKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExecuteCallableKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConvertUToAccelerationStructureKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIgnoreIntersectionKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTerminateRayKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSDot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUDot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSUDot: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSDotAccSat: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUDotAccSat: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSUDotAccSat: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeCooperativeMatrixKHR: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixLoadKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixStoreKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixMulAddKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixLengthKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantCompositeReplicateEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantCompositeReplicateEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeConstructReplicateEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeRayQueryKHR: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpRayQueryInitializeKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryTerminateKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryGenerateIntersectionKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryConfirmIntersectionKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryProceedKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionTypeKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageSampleWeightedQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBoxFilterQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchSSDQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchSADQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitCastArrayQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchWindowSSDQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchWindowSADQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchGatherSSDQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpImageBlockMatchGatherSADQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeConstructCoopMatQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCompositeExtractCoopMatQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpExtractSubArrayQCOM: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupIAddNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFAddNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFMinNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupUMinNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupSMinNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFMaxNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupUMaxNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupSMaxNonUniformAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFragmentMaskFetchAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFragmentFetchAMD: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReadClockKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAllocateNodePayloadsAMDX: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpEnqueueNodePayloadsAMDX: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeNodePayloadArrayAMDX: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpFinishWritingNodePayloadAMDX: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpNodePayloadArrayLengthAMDX: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIsNodePayloadValidAMDX: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantStringAMDX: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpSpecConstantStringAMDX: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpGroupNonUniformQuadAllKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupNonUniformQuadAnyKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectRecordHitMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectRecordHitWithIndexMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectRecordMissMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectGetWorldToObjectNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetObjectToWorldNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetObjectRayDirectionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetObjectRayOriginNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectTraceRayMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectGetShaderRecordBufferHandleNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetShaderBindingTableRecordIndexNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectRecordEmptyNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectTraceRayNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectRecordHitNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectRecordHitWithIndexNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectRecordMissNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectExecuteShaderNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectGetCurrentTimeNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetAttributesNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpHitObjectGetHitKindNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetPrimitiveIndexNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetGeometryIndexNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetInstanceIdNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetInstanceCustomIndexNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetWorldRayDirectionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetWorldRayOriginNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetRayTMaxNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetRayTMinNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectIsEmptyNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectIsHitNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectIsMissNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReorderThreadWithHitObjectNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpReorderThreadWithHintNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeHitObjectNV: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpImageSampleFootprintNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeCooperativeVectorNV: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpCooperativeVectorMatrixMulNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeVectorOuterProductAccumulateNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeVectorReduceSumAccumulateNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeVectorMatrixMulAddNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixConvertNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpEmitMeshTasksEXT: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSetMeshOutputsEXT: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpGroupNonUniformPartitionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpWritePackedPrimitiveIndices4x8NV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpFetchMicroTriangleVertexPositionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFetchMicroTriangleVertexBarycentricNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeVectorLoadNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeVectorStoreNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpReportIntersectionKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIgnoreIntersectionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTerminateRayNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTraceNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTraceMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTraceRayMotionNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeAccelerationStructureKHR: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpExecuteCallableNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRayQueryGetIntersectionClusterIdNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetClusterIdNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeCooperativeMatrixNV: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixLoadNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixStoreNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixMulAddNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixLengthNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBeginInvocationInterlockEXT: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpEndInvocationInterlockEXT: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixReduceNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixLoadTensorNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixStoreTensorNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCooperativeMatrixPerElementOpNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeTensorLayoutNV: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeTensorViewNV: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpCreateTensorLayoutNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorLayoutSetDimensionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorLayoutSetStrideNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorLayoutSliceNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorLayoutSetClampValueNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCreateTensorViewNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorViewSetDimensionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorViewSetStrideNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDemoteToHelperInvocation: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpIsHelperInvocationEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorViewSetClipNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTensorLayoutSetBlockSizeNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCooperativeMatrixTransposeNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertUToImageNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertUToSamplerNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertImageToUNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertSamplerToUNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertUToSampledImageNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertSampledImageToUNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSamplerImageAddressingModeNV: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpRawAccessChainNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionSpherePositionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionSphereRadiusNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionLSSPositionsNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionLSSRadiiNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionLSSHitValueNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetSpherePositionNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetSphereRadiusNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetLSSPositionsNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectGetLSSRadiiNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectIsSphereHitNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpHitObjectIsLSSHitNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryIsSphereHitNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryIsLSSHitNV: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupShuffleINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupShuffleDownINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupShuffleUpINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupShuffleXorINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupBlockReadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupBlockWriteINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroupImageBlockReadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupImageBlockWriteINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroupImageMediaBlockReadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupImageMediaBlockWriteINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpUCountLeadingZerosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUCountTrailingZerosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAbsISubINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAbsUSubINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIAddSatINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUAddSatINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIAverageINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUAverageINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIAverageRoundedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUAverageRoundedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpISubSatINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUSubSatINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpIMul32x16INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUMul32x16INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConstantFunctionPointerINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFunctionPointerCallINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAsmTargetINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpAsmINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAsmCallINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicFMinEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicFMaxEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAssumeTrueKHR: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpExpectKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpDecorateString: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpMemberDecorateString: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpVmeImageINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeVmeImageINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImePayloadINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcRefPayloadINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcSicPayloadINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcMcePayloadINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcMceResultINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImeResultINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcImeDualReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcRefResultINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeAvcSicResultINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToImeResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToRefResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceConvertToSicResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeInitializeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetDualReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeRefWindowSizeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeSetWeightedSadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeConvertToMceResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetBorderReachedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcFmeInitializeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcBmeInitializeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcRefConvertToMceResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicInitializeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicConfigureSkcINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicEvaluateIpeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicConvertToMceResultINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpVariableLengthArrayINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSaveMemoryINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRestoreMemoryINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpArbitraryFloatSinCosPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCastINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCastFromIntINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCastToIntINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatAddINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatSubINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatMulINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatDivINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatGTINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatGEINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLTINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLEINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatEQINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatRecipINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatRSqrtINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCbrtINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatHypotINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatSqrtINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLogINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLog2INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLog10INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatLog1pINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatExpINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatExp2INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatExp10INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatExpm1INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatSinINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatSinCosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatSinPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatCosPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatASinINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatASinPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatACosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatACosPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatATanINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatATanPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatATan2INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatPowINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatPowRINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpArbitraryFloatPowNINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpLoopControlINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpAliasDomainDeclINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpAliasScopeDeclINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpAliasScopeListDeclINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpFixedSqrtINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedRecipINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedRsqrtINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedSinINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedCosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedSinCosINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedSinPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedCosPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedSinCosPiINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedLogINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFixedExpINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpPtrCastToCrossWorkgroupINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpCrossWorkgroupCastToPtrINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpReadPipeBlockingINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpWritePipeBlockingINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpFPGARegINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetRayTMinKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetRayFlagsKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionTKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetWorldRayDirectionKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetWorldRayOriginKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpAtomicFAddEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTypeBufferSurfaceINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpTypeStructContinuedINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConstantCompositeContinuedINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSpecConstantCompositeContinuedINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpCompositeConstructContinuedINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertFToBF16INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertBF16ToFINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpControlBarrierArriveINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpControlBarrierWaitINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpArithmeticFenceEXT: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTaskSequenceCreateINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTaskSequenceAsyncINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTaskSequenceGetINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpTaskSequenceReleaseINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpTypeTaskSequenceINTEL: + *hasResult = true; + *hasResultType = false; + break; + case SpvOpSubgroupBlockPrefetchINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroup2DBlockLoadINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroup2DBlockLoadTransformINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroup2DBlockLoadTransposeINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroup2DBlockPrefetchINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroup2DBlockStoreINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSubgroupMatrixMultiplyAccumulateINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpBitwiseFunctionINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpUntypedVariableLengthArrayINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConditionalExtensionINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConditionalEntryPointINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConditionalCapabilityINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpSpecConstantTargetINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantArchitectureINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpSpecConstantCapabilitiesINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConditionalCopyObjectINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupIMulKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupFMulKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupBitwiseAndKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupBitwiseOrKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupBitwiseXorKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupLogicalAndKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupLogicalOrKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpGroupLogicalXorKHR: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpRoundFToTF32INTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMaskedGatherINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpMaskedScatterINTEL: + *hasResult = false; + *hasResultType = false; + break; + case SpvOpConvertHandleToImageINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertHandleToSamplerINTEL: + *hasResult = true; + *hasResultType = true; + break; + case SpvOpConvertHandleToSampledImageINTEL: + *hasResult = true; + *hasResultType = true; + break; + } +} +inline const char* SpvSourceLanguageToString(SpvSourceLanguage value) { + switch (value) { + case SpvSourceLanguageUnknown: + return "Unknown"; + case SpvSourceLanguageESSL: + return "ESSL"; + case SpvSourceLanguageGLSL: + return "GLSL"; + case SpvSourceLanguageOpenCL_C: + return "OpenCL_C"; + case SpvSourceLanguageOpenCL_CPP: + return "OpenCL_CPP"; + case SpvSourceLanguageHLSL: + return "HLSL"; + case SpvSourceLanguageCPP_for_OpenCL: + return "CPP_for_OpenCL"; + case SpvSourceLanguageSYCL: + return "SYCL"; + case SpvSourceLanguageHERO_C: + return "HERO_C"; + case SpvSourceLanguageNZSL: + return "NZSL"; + case SpvSourceLanguageWGSL: + return "WGSL"; + case SpvSourceLanguageSlang: + return "Slang"; + case SpvSourceLanguageZig: + return "Zig"; + case SpvSourceLanguageRust: + return "Rust"; + default: + return "Unknown"; + } +} + +inline const char* SpvExecutionModelToString(SpvExecutionModel value) { + switch (value) { + case SpvExecutionModelVertex: + return "Vertex"; + case SpvExecutionModelTessellationControl: + return "TessellationControl"; + case SpvExecutionModelTessellationEvaluation: + return "TessellationEvaluation"; + case SpvExecutionModelGeometry: + return "Geometry"; + case SpvExecutionModelFragment: + return "Fragment"; + case SpvExecutionModelGLCompute: + return "GLCompute"; + case SpvExecutionModelKernel: + return "Kernel"; + case SpvExecutionModelTaskNV: + return "TaskNV"; + case SpvExecutionModelMeshNV: + return "MeshNV"; + case SpvExecutionModelRayGenerationKHR: + return "RayGenerationKHR"; + case SpvExecutionModelIntersectionKHR: + return "IntersectionKHR"; + case SpvExecutionModelAnyHitKHR: + return "AnyHitKHR"; + case SpvExecutionModelClosestHitKHR: + return "ClosestHitKHR"; + case SpvExecutionModelMissKHR: + return "MissKHR"; + case SpvExecutionModelCallableKHR: + return "CallableKHR"; + case SpvExecutionModelTaskEXT: + return "TaskEXT"; + case SpvExecutionModelMeshEXT: + return "MeshEXT"; + default: + return "Unknown"; + } +} + +inline const char* SpvAddressingModelToString(SpvAddressingModel value) { + switch (value) { + case SpvAddressingModelLogical: + return "Logical"; + case SpvAddressingModelPhysical32: + return "Physical32"; + case SpvAddressingModelPhysical64: + return "Physical64"; + case SpvAddressingModelPhysicalStorageBuffer64: + return "PhysicalStorageBuffer64"; + default: + return "Unknown"; + } +} + +inline const char* SpvMemoryModelToString(SpvMemoryModel value) { + switch (value) { + case SpvMemoryModelSimple: + return "Simple"; + case SpvMemoryModelGLSL450: + return "GLSL450"; + case SpvMemoryModelOpenCL: + return "OpenCL"; + case SpvMemoryModelVulkan: + return "Vulkan"; + default: + return "Unknown"; + } +} + +inline const char* SpvExecutionModeToString(SpvExecutionMode value) { + switch (value) { + case SpvExecutionModeInvocations: + return "Invocations"; + case SpvExecutionModeSpacingEqual: + return "SpacingEqual"; + case SpvExecutionModeSpacingFractionalEven: + return "SpacingFractionalEven"; + case SpvExecutionModeSpacingFractionalOdd: + return "SpacingFractionalOdd"; + case SpvExecutionModeVertexOrderCw: + return "VertexOrderCw"; + case SpvExecutionModeVertexOrderCcw: + return "VertexOrderCcw"; + case SpvExecutionModePixelCenterInteger: + return "PixelCenterInteger"; + case SpvExecutionModeOriginUpperLeft: + return "OriginUpperLeft"; + case SpvExecutionModeOriginLowerLeft: + return "OriginLowerLeft"; + case SpvExecutionModeEarlyFragmentTests: + return "EarlyFragmentTests"; + case SpvExecutionModePointMode: + return "PointMode"; + case SpvExecutionModeXfb: + return "Xfb"; + case SpvExecutionModeDepthReplacing: + return "DepthReplacing"; + case SpvExecutionModeDepthGreater: + return "DepthGreater"; + case SpvExecutionModeDepthLess: + return "DepthLess"; + case SpvExecutionModeDepthUnchanged: + return "DepthUnchanged"; + case SpvExecutionModeLocalSize: + return "LocalSize"; + case SpvExecutionModeLocalSizeHint: + return "LocalSizeHint"; + case SpvExecutionModeInputPoints: + return "InputPoints"; + case SpvExecutionModeInputLines: + return "InputLines"; + case SpvExecutionModeInputLinesAdjacency: + return "InputLinesAdjacency"; + case SpvExecutionModeTriangles: + return "Triangles"; + case SpvExecutionModeInputTrianglesAdjacency: + return "InputTrianglesAdjacency"; + case SpvExecutionModeQuads: + return "Quads"; + case SpvExecutionModeIsolines: + return "Isolines"; + case SpvExecutionModeOutputVertices: + return "OutputVertices"; + case SpvExecutionModeOutputPoints: + return "OutputPoints"; + case SpvExecutionModeOutputLineStrip: + return "OutputLineStrip"; + case SpvExecutionModeOutputTriangleStrip: + return "OutputTriangleStrip"; + case SpvExecutionModeVecTypeHint: + return "VecTypeHint"; + case SpvExecutionModeContractionOff: + return "ContractionOff"; + case SpvExecutionModeInitializer: + return "Initializer"; + case SpvExecutionModeFinalizer: + return "Finalizer"; + case SpvExecutionModeSubgroupSize: + return "SubgroupSize"; + case SpvExecutionModeSubgroupsPerWorkgroup: + return "SubgroupsPerWorkgroup"; + case SpvExecutionModeSubgroupsPerWorkgroupId: + return "SubgroupsPerWorkgroupId"; + case SpvExecutionModeLocalSizeId: + return "LocalSizeId"; + case SpvExecutionModeLocalSizeHintId: + return "LocalSizeHintId"; + case SpvExecutionModeNonCoherentColorAttachmentReadEXT: + return "NonCoherentColorAttachmentReadEXT"; + case SpvExecutionModeNonCoherentDepthAttachmentReadEXT: + return "NonCoherentDepthAttachmentReadEXT"; + case SpvExecutionModeNonCoherentStencilAttachmentReadEXT: + return "NonCoherentStencilAttachmentReadEXT"; + case SpvExecutionModeSubgroupUniformControlFlowKHR: + return "SubgroupUniformControlFlowKHR"; + case SpvExecutionModePostDepthCoverage: + return "PostDepthCoverage"; + case SpvExecutionModeDenormPreserve: + return "DenormPreserve"; + case SpvExecutionModeDenormFlushToZero: + return "DenormFlushToZero"; + case SpvExecutionModeSignedZeroInfNanPreserve: + return "SignedZeroInfNanPreserve"; + case SpvExecutionModeRoundingModeRTE: + return "RoundingModeRTE"; + case SpvExecutionModeRoundingModeRTZ: + return "RoundingModeRTZ"; + case SpvExecutionModeNonCoherentTileAttachmentReadQCOM: + return "NonCoherentTileAttachmentReadQCOM"; + case SpvExecutionModeTileShadingRateQCOM: + return "TileShadingRateQCOM"; + case SpvExecutionModeEarlyAndLateFragmentTestsAMD: + return "EarlyAndLateFragmentTestsAMD"; + case SpvExecutionModeStencilRefReplacingEXT: + return "StencilRefReplacingEXT"; + case SpvExecutionModeCoalescingAMDX: + return "CoalescingAMDX"; + case SpvExecutionModeIsApiEntryAMDX: + return "IsApiEntryAMDX"; + case SpvExecutionModeMaxNodeRecursionAMDX: + return "MaxNodeRecursionAMDX"; + case SpvExecutionModeStaticNumWorkgroupsAMDX: + return "StaticNumWorkgroupsAMDX"; + case SpvExecutionModeShaderIndexAMDX: + return "ShaderIndexAMDX"; + case SpvExecutionModeMaxNumWorkgroupsAMDX: + return "MaxNumWorkgroupsAMDX"; + case SpvExecutionModeStencilRefUnchangedFrontAMD: + return "StencilRefUnchangedFrontAMD"; + case SpvExecutionModeStencilRefGreaterFrontAMD: + return "StencilRefGreaterFrontAMD"; + case SpvExecutionModeStencilRefLessFrontAMD: + return "StencilRefLessFrontAMD"; + case SpvExecutionModeStencilRefUnchangedBackAMD: + return "StencilRefUnchangedBackAMD"; + case SpvExecutionModeStencilRefGreaterBackAMD: + return "StencilRefGreaterBackAMD"; + case SpvExecutionModeStencilRefLessBackAMD: + return "StencilRefLessBackAMD"; + case SpvExecutionModeQuadDerivativesKHR: + return "QuadDerivativesKHR"; + case SpvExecutionModeRequireFullQuadsKHR: + return "RequireFullQuadsKHR"; + case SpvExecutionModeSharesInputWithAMDX: + return "SharesInputWithAMDX"; + case SpvExecutionModeOutputLinesEXT: + return "OutputLinesEXT"; + case SpvExecutionModeOutputPrimitivesEXT: + return "OutputPrimitivesEXT"; + case SpvExecutionModeDerivativeGroupQuadsKHR: + return "DerivativeGroupQuadsKHR"; + case SpvExecutionModeDerivativeGroupLinearKHR: + return "DerivativeGroupLinearKHR"; + case SpvExecutionModeOutputTrianglesEXT: + return "OutputTrianglesEXT"; + case SpvExecutionModePixelInterlockOrderedEXT: + return "PixelInterlockOrderedEXT"; + case SpvExecutionModePixelInterlockUnorderedEXT: + return "PixelInterlockUnorderedEXT"; + case SpvExecutionModeSampleInterlockOrderedEXT: + return "SampleInterlockOrderedEXT"; + case SpvExecutionModeSampleInterlockUnorderedEXT: + return "SampleInterlockUnorderedEXT"; + case SpvExecutionModeShadingRateInterlockOrderedEXT: + return "ShadingRateInterlockOrderedEXT"; + case SpvExecutionModeShadingRateInterlockUnorderedEXT: + return "ShadingRateInterlockUnorderedEXT"; + case SpvExecutionModeSharedLocalMemorySizeINTEL: + return "SharedLocalMemorySizeINTEL"; + case SpvExecutionModeRoundingModeRTPINTEL: + return "RoundingModeRTPINTEL"; + case SpvExecutionModeRoundingModeRTNINTEL: + return "RoundingModeRTNINTEL"; + case SpvExecutionModeFloatingPointModeALTINTEL: + return "FloatingPointModeALTINTEL"; + case SpvExecutionModeFloatingPointModeIEEEINTEL: + return "FloatingPointModeIEEEINTEL"; + case SpvExecutionModeMaxWorkgroupSizeINTEL: + return "MaxWorkgroupSizeINTEL"; + case SpvExecutionModeMaxWorkDimINTEL: + return "MaxWorkDimINTEL"; + case SpvExecutionModeNoGlobalOffsetINTEL: + return "NoGlobalOffsetINTEL"; + case SpvExecutionModeNumSIMDWorkitemsINTEL: + return "NumSIMDWorkitemsINTEL"; + case SpvExecutionModeSchedulerTargetFmaxMhzINTEL: + return "SchedulerTargetFmaxMhzINTEL"; + case SpvExecutionModeMaximallyReconvergesKHR: + return "MaximallyReconvergesKHR"; + case SpvExecutionModeFPFastMathDefault: + return "FPFastMathDefault"; + case SpvExecutionModeStreamingInterfaceINTEL: + return "StreamingInterfaceINTEL"; + case SpvExecutionModeRegisterMapInterfaceINTEL: + return "RegisterMapInterfaceINTEL"; + case SpvExecutionModeNamedBarrierCountINTEL: + return "NamedBarrierCountINTEL"; + case SpvExecutionModeMaximumRegistersINTEL: + return "MaximumRegistersINTEL"; + case SpvExecutionModeMaximumRegistersIdINTEL: + return "MaximumRegistersIdINTEL"; + case SpvExecutionModeNamedMaximumRegistersINTEL: + return "NamedMaximumRegistersINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvStorageClassToString(SpvStorageClass value) { + switch (value) { + case SpvStorageClassUniformConstant: + return "UniformConstant"; + case SpvStorageClassInput: + return "Input"; + case SpvStorageClassUniform: + return "Uniform"; + case SpvStorageClassOutput: + return "Output"; + case SpvStorageClassWorkgroup: + return "Workgroup"; + case SpvStorageClassCrossWorkgroup: + return "CrossWorkgroup"; + case SpvStorageClassPrivate: + return "Private"; + case SpvStorageClassFunction: + return "Function"; + case SpvStorageClassGeneric: + return "Generic"; + case SpvStorageClassPushConstant: + return "PushConstant"; + case SpvStorageClassAtomicCounter: + return "AtomicCounter"; + case SpvStorageClassImage: + return "Image"; + case SpvStorageClassStorageBuffer: + return "StorageBuffer"; + case SpvStorageClassTileImageEXT: + return "TileImageEXT"; + case SpvStorageClassTileAttachmentQCOM: + return "TileAttachmentQCOM"; + case SpvStorageClassNodePayloadAMDX: + return "NodePayloadAMDX"; + case SpvStorageClassCallableDataKHR: + return "CallableDataKHR"; + case SpvStorageClassIncomingCallableDataKHR: + return "IncomingCallableDataKHR"; + case SpvStorageClassRayPayloadKHR: + return "RayPayloadKHR"; + case SpvStorageClassHitAttributeKHR: + return "HitAttributeKHR"; + case SpvStorageClassIncomingRayPayloadKHR: + return "IncomingRayPayloadKHR"; + case SpvStorageClassShaderRecordBufferKHR: + return "ShaderRecordBufferKHR"; + case SpvStorageClassPhysicalStorageBuffer: + return "PhysicalStorageBuffer"; + case SpvStorageClassHitObjectAttributeNV: + return "HitObjectAttributeNV"; + case SpvStorageClassTaskPayloadWorkgroupEXT: + return "TaskPayloadWorkgroupEXT"; + case SpvStorageClassCodeSectionINTEL: + return "CodeSectionINTEL"; + case SpvStorageClassDeviceOnlyINTEL: + return "DeviceOnlyINTEL"; + case SpvStorageClassHostOnlyINTEL: + return "HostOnlyINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvDimToString(SpvDim value) { + switch (value) { + case SpvDim1D: + return "1D"; + case SpvDim2D: + return "2D"; + case SpvDim3D: + return "3D"; + case SpvDimCube: + return "Cube"; + case SpvDimRect: + return "Rect"; + case SpvDimBuffer: + return "Buffer"; + case SpvDimSubpassData: + return "SubpassData"; + case SpvDimTileImageDataEXT: + return "TileImageDataEXT"; + default: + return "Unknown"; + } +} + +inline const char* SpvSamplerAddressingModeToString(SpvSamplerAddressingMode value) { + switch (value) { + case SpvSamplerAddressingModeNone: + return "None"; + case SpvSamplerAddressingModeClampToEdge: + return "ClampToEdge"; + case SpvSamplerAddressingModeClamp: + return "Clamp"; + case SpvSamplerAddressingModeRepeat: + return "Repeat"; + case SpvSamplerAddressingModeRepeatMirrored: + return "RepeatMirrored"; + default: + return "Unknown"; + } +} + +inline const char* SpvSamplerFilterModeToString(SpvSamplerFilterMode value) { + switch (value) { + case SpvSamplerFilterModeNearest: + return "Nearest"; + case SpvSamplerFilterModeLinear: + return "Linear"; + default: + return "Unknown"; + } +} + +inline const char* SpvImageFormatToString(SpvImageFormat value) { + switch (value) { + case SpvImageFormatUnknown: + return "Unknown"; + case SpvImageFormatRgba32f: + return "Rgba32f"; + case SpvImageFormatRgba16f: + return "Rgba16f"; + case SpvImageFormatR32f: + return "R32f"; + case SpvImageFormatRgba8: + return "Rgba8"; + case SpvImageFormatRgba8Snorm: + return "Rgba8Snorm"; + case SpvImageFormatRg32f: + return "Rg32f"; + case SpvImageFormatRg16f: + return "Rg16f"; + case SpvImageFormatR11fG11fB10f: + return "R11fG11fB10f"; + case SpvImageFormatR16f: + return "R16f"; + case SpvImageFormatRgba16: + return "Rgba16"; + case SpvImageFormatRgb10A2: + return "Rgb10A2"; + case SpvImageFormatRg16: + return "Rg16"; + case SpvImageFormatRg8: + return "Rg8"; + case SpvImageFormatR16: + return "R16"; + case SpvImageFormatR8: + return "R8"; + case SpvImageFormatRgba16Snorm: + return "Rgba16Snorm"; + case SpvImageFormatRg16Snorm: + return "Rg16Snorm"; + case SpvImageFormatRg8Snorm: + return "Rg8Snorm"; + case SpvImageFormatR16Snorm: + return "R16Snorm"; + case SpvImageFormatR8Snorm: + return "R8Snorm"; + case SpvImageFormatRgba32i: + return "Rgba32i"; + case SpvImageFormatRgba16i: + return "Rgba16i"; + case SpvImageFormatRgba8i: + return "Rgba8i"; + case SpvImageFormatR32i: + return "R32i"; + case SpvImageFormatRg32i: + return "Rg32i"; + case SpvImageFormatRg16i: + return "Rg16i"; + case SpvImageFormatRg8i: + return "Rg8i"; + case SpvImageFormatR16i: + return "R16i"; + case SpvImageFormatR8i: + return "R8i"; + case SpvImageFormatRgba32ui: + return "Rgba32ui"; + case SpvImageFormatRgba16ui: + return "Rgba16ui"; + case SpvImageFormatRgba8ui: + return "Rgba8ui"; + case SpvImageFormatR32ui: + return "R32ui"; + case SpvImageFormatRgb10a2ui: + return "Rgb10a2ui"; + case SpvImageFormatRg32ui: + return "Rg32ui"; + case SpvImageFormatRg16ui: + return "Rg16ui"; + case SpvImageFormatRg8ui: + return "Rg8ui"; + case SpvImageFormatR16ui: + return "R16ui"; + case SpvImageFormatR8ui: + return "R8ui"; + case SpvImageFormatR64ui: + return "R64ui"; + case SpvImageFormatR64i: + return "R64i"; + default: + return "Unknown"; + } +} + +inline const char* SpvImageChannelOrderToString(SpvImageChannelOrder value) { + switch (value) { + case SpvImageChannelOrderR: + return "R"; + case SpvImageChannelOrderA: + return "A"; + case SpvImageChannelOrderRG: + return "RG"; + case SpvImageChannelOrderRA: + return "RA"; + case SpvImageChannelOrderRGB: + return "RGB"; + case SpvImageChannelOrderRGBA: + return "RGBA"; + case SpvImageChannelOrderBGRA: + return "BGRA"; + case SpvImageChannelOrderARGB: + return "ARGB"; + case SpvImageChannelOrderIntensity: + return "Intensity"; + case SpvImageChannelOrderLuminance: + return "Luminance"; + case SpvImageChannelOrderRx: + return "Rx"; + case SpvImageChannelOrderRGx: + return "RGx"; + case SpvImageChannelOrderRGBx: + return "RGBx"; + case SpvImageChannelOrderDepth: + return "Depth"; + case SpvImageChannelOrderDepthStencil: + return "DepthStencil"; + case SpvImageChannelOrdersRGB: + return "sRGB"; + case SpvImageChannelOrdersRGBx: + return "sRGBx"; + case SpvImageChannelOrdersRGBA: + return "sRGBA"; + case SpvImageChannelOrdersBGRA: + return "sBGRA"; + case SpvImageChannelOrderABGR: + return "ABGR"; + default: + return "Unknown"; + } +} + +inline const char* SpvImageChannelDataTypeToString(SpvImageChannelDataType value) { + switch (value) { + case SpvImageChannelDataTypeSnormInt8: + return "SnormInt8"; + case SpvImageChannelDataTypeSnormInt16: + return "SnormInt16"; + case SpvImageChannelDataTypeUnormInt8: + return "UnormInt8"; + case SpvImageChannelDataTypeUnormInt16: + return "UnormInt16"; + case SpvImageChannelDataTypeUnormShort565: + return "UnormShort565"; + case SpvImageChannelDataTypeUnormShort555: + return "UnormShort555"; + case SpvImageChannelDataTypeUnormInt101010: + return "UnormInt101010"; + case SpvImageChannelDataTypeSignedInt8: + return "SignedInt8"; + case SpvImageChannelDataTypeSignedInt16: + return "SignedInt16"; + case SpvImageChannelDataTypeSignedInt32: + return "SignedInt32"; + case SpvImageChannelDataTypeUnsignedInt8: + return "UnsignedInt8"; + case SpvImageChannelDataTypeUnsignedInt16: + return "UnsignedInt16"; + case SpvImageChannelDataTypeUnsignedInt32: + return "UnsignedInt32"; + case SpvImageChannelDataTypeHalfFloat: + return "HalfFloat"; + case SpvImageChannelDataTypeFloat: + return "Float"; + case SpvImageChannelDataTypeUnormInt24: + return "UnormInt24"; + case SpvImageChannelDataTypeUnormInt101010_2: + return "UnormInt101010_2"; + case SpvImageChannelDataTypeUnormInt10X6EXT: + return "UnormInt10X6EXT"; + case SpvImageChannelDataTypeUnsignedIntRaw10EXT: + return "UnsignedIntRaw10EXT"; + case SpvImageChannelDataTypeUnsignedIntRaw12EXT: + return "UnsignedIntRaw12EXT"; + case SpvImageChannelDataTypeUnormInt2_101010EXT: + return "UnormInt2_101010EXT"; + case SpvImageChannelDataTypeUnsignedInt10X6EXT: + return "UnsignedInt10X6EXT"; + case SpvImageChannelDataTypeUnsignedInt12X4EXT: + return "UnsignedInt12X4EXT"; + case SpvImageChannelDataTypeUnsignedInt14X2EXT: + return "UnsignedInt14X2EXT"; + case SpvImageChannelDataTypeUnormInt12X4EXT: + return "UnormInt12X4EXT"; + case SpvImageChannelDataTypeUnormInt14X2EXT: + return "UnormInt14X2EXT"; + default: + return "Unknown"; + } +} + +inline const char* SpvFPRoundingModeToString(SpvFPRoundingMode value) { + switch (value) { + case SpvFPRoundingModeRTE: + return "RTE"; + case SpvFPRoundingModeRTZ: + return "RTZ"; + case SpvFPRoundingModeRTP: + return "RTP"; + case SpvFPRoundingModeRTN: + return "RTN"; + default: + return "Unknown"; + } +} + +inline const char* SpvLinkageTypeToString(SpvLinkageType value) { + switch (value) { + case SpvLinkageTypeExport: + return "Export"; + case SpvLinkageTypeImport: + return "Import"; + case SpvLinkageTypeLinkOnceODR: + return "LinkOnceODR"; + default: + return "Unknown"; + } +} + +inline const char* SpvAccessQualifierToString(SpvAccessQualifier value) { + switch (value) { + case SpvAccessQualifierReadOnly: + return "ReadOnly"; + case SpvAccessQualifierWriteOnly: + return "WriteOnly"; + case SpvAccessQualifierReadWrite: + return "ReadWrite"; + default: + return "Unknown"; + } +} + +inline const char* SpvFunctionParameterAttributeToString(SpvFunctionParameterAttribute value) { + switch (value) { + case SpvFunctionParameterAttributeZext: + return "Zext"; + case SpvFunctionParameterAttributeSext: + return "Sext"; + case SpvFunctionParameterAttributeByVal: + return "ByVal"; + case SpvFunctionParameterAttributeSret: + return "Sret"; + case SpvFunctionParameterAttributeNoAlias: + return "NoAlias"; + case SpvFunctionParameterAttributeNoCapture: + return "NoCapture"; + case SpvFunctionParameterAttributeNoWrite: + return "NoWrite"; + case SpvFunctionParameterAttributeNoReadWrite: + return "NoReadWrite"; + case SpvFunctionParameterAttributeRuntimeAlignedINTEL: + return "RuntimeAlignedINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvDecorationToString(SpvDecoration value) { + switch (value) { + case SpvDecorationRelaxedPrecision: + return "RelaxedPrecision"; + case SpvDecorationSpecId: + return "SpecId"; + case SpvDecorationBlock: + return "Block"; + case SpvDecorationBufferBlock: + return "BufferBlock"; + case SpvDecorationRowMajor: + return "RowMajor"; + case SpvDecorationColMajor: + return "ColMajor"; + case SpvDecorationArrayStride: + return "ArrayStride"; + case SpvDecorationMatrixStride: + return "MatrixStride"; + case SpvDecorationGLSLShared: + return "GLSLShared"; + case SpvDecorationGLSLPacked: + return "GLSLPacked"; + case SpvDecorationCPacked: + return "CPacked"; + case SpvDecorationBuiltIn: + return "BuiltIn"; + case SpvDecorationNoPerspective: + return "NoPerspective"; + case SpvDecorationFlat: + return "Flat"; + case SpvDecorationPatch: + return "Patch"; + case SpvDecorationCentroid: + return "Centroid"; + case SpvDecorationSample: + return "Sample"; + case SpvDecorationInvariant: + return "Invariant"; + case SpvDecorationRestrict: + return "Restrict"; + case SpvDecorationAliased: + return "Aliased"; + case SpvDecorationVolatile: + return "Volatile"; + case SpvDecorationConstant: + return "Constant"; + case SpvDecorationCoherent: + return "Coherent"; + case SpvDecorationNonWritable: + return "NonWritable"; + case SpvDecorationNonReadable: + return "NonReadable"; + case SpvDecorationUniform: + return "Uniform"; + case SpvDecorationUniformId: + return "UniformId"; + case SpvDecorationSaturatedConversion: + return "SaturatedConversion"; + case SpvDecorationStream: + return "Stream"; + case SpvDecorationLocation: + return "Location"; + case SpvDecorationComponent: + return "Component"; + case SpvDecorationIndex: + return "Index"; + case SpvDecorationBinding: + return "Binding"; + case SpvDecorationDescriptorSet: + return "DescriptorSet"; + case SpvDecorationOffset: + return "Offset"; + case SpvDecorationXfbBuffer: + return "XfbBuffer"; + case SpvDecorationXfbStride: + return "XfbStride"; + case SpvDecorationFuncParamAttr: + return "FuncParamAttr"; + case SpvDecorationFPRoundingMode: + return "FPRoundingMode"; + case SpvDecorationFPFastMathMode: + return "FPFastMathMode"; + case SpvDecorationLinkageAttributes: + return "LinkageAttributes"; + case SpvDecorationNoContraction: + return "NoContraction"; + case SpvDecorationInputAttachmentIndex: + return "InputAttachmentIndex"; + case SpvDecorationAlignment: + return "Alignment"; + case SpvDecorationMaxByteOffset: + return "MaxByteOffset"; + case SpvDecorationAlignmentId: + return "AlignmentId"; + case SpvDecorationMaxByteOffsetId: + return "MaxByteOffsetId"; + case SpvDecorationSaturatedToLargestFloat8NormalConversionEXT: + return "SaturatedToLargestFloat8NormalConversionEXT"; + case SpvDecorationNoSignedWrap: + return "NoSignedWrap"; + case SpvDecorationNoUnsignedWrap: + return "NoUnsignedWrap"; + case SpvDecorationWeightTextureQCOM: + return "WeightTextureQCOM"; + case SpvDecorationBlockMatchTextureQCOM: + return "BlockMatchTextureQCOM"; + case SpvDecorationBlockMatchSamplerQCOM: + return "BlockMatchSamplerQCOM"; + case SpvDecorationExplicitInterpAMD: + return "ExplicitInterpAMD"; + case SpvDecorationNodeSharesPayloadLimitsWithAMDX: + return "NodeSharesPayloadLimitsWithAMDX"; + case SpvDecorationNodeMaxPayloadsAMDX: + return "NodeMaxPayloadsAMDX"; + case SpvDecorationTrackFinishWritingAMDX: + return "TrackFinishWritingAMDX"; + case SpvDecorationPayloadNodeNameAMDX: + return "PayloadNodeNameAMDX"; + case SpvDecorationPayloadNodeBaseIndexAMDX: + return "PayloadNodeBaseIndexAMDX"; + case SpvDecorationPayloadNodeSparseArrayAMDX: + return "PayloadNodeSparseArrayAMDX"; + case SpvDecorationPayloadNodeArraySizeAMDX: + return "PayloadNodeArraySizeAMDX"; + case SpvDecorationPayloadDispatchIndirectAMDX: + return "PayloadDispatchIndirectAMDX"; + case SpvDecorationOverrideCoverageNV: + return "OverrideCoverageNV"; + case SpvDecorationPassthroughNV: + return "PassthroughNV"; + case SpvDecorationViewportRelativeNV: + return "ViewportRelativeNV"; + case SpvDecorationSecondaryViewportRelativeNV: + return "SecondaryViewportRelativeNV"; + case SpvDecorationPerPrimitiveEXT: + return "PerPrimitiveEXT"; + case SpvDecorationPerViewNV: + return "PerViewNV"; + case SpvDecorationPerTaskNV: + return "PerTaskNV"; + case SpvDecorationPerVertexKHR: + return "PerVertexKHR"; + case SpvDecorationNonUniform: + return "NonUniform"; + case SpvDecorationRestrictPointer: + return "RestrictPointer"; + case SpvDecorationAliasedPointer: + return "AliasedPointer"; + case SpvDecorationHitObjectShaderRecordBufferNV: + return "HitObjectShaderRecordBufferNV"; + case SpvDecorationBindlessSamplerNV: + return "BindlessSamplerNV"; + case SpvDecorationBindlessImageNV: + return "BindlessImageNV"; + case SpvDecorationBoundSamplerNV: + return "BoundSamplerNV"; + case SpvDecorationBoundImageNV: + return "BoundImageNV"; + case SpvDecorationSIMTCallINTEL: + return "SIMTCallINTEL"; + case SpvDecorationReferencedIndirectlyINTEL: + return "ReferencedIndirectlyINTEL"; + case SpvDecorationClobberINTEL: + return "ClobberINTEL"; + case SpvDecorationSideEffectsINTEL: + return "SideEffectsINTEL"; + case SpvDecorationVectorComputeVariableINTEL: + return "VectorComputeVariableINTEL"; + case SpvDecorationFuncParamIOKindINTEL: + return "FuncParamIOKindINTEL"; + case SpvDecorationVectorComputeFunctionINTEL: + return "VectorComputeFunctionINTEL"; + case SpvDecorationStackCallINTEL: + return "StackCallINTEL"; + case SpvDecorationGlobalVariableOffsetINTEL: + return "GlobalVariableOffsetINTEL"; + case SpvDecorationCounterBuffer: + return "CounterBuffer"; + case SpvDecorationHlslSemanticGOOGLE: + return "HlslSemanticGOOGLE"; + case SpvDecorationUserTypeGOOGLE: + return "UserTypeGOOGLE"; + case SpvDecorationFunctionRoundingModeINTEL: + return "FunctionRoundingModeINTEL"; + case SpvDecorationFunctionDenormModeINTEL: + return "FunctionDenormModeINTEL"; + case SpvDecorationRegisterINTEL: + return "RegisterINTEL"; + case SpvDecorationMemoryINTEL: + return "MemoryINTEL"; + case SpvDecorationNumbanksINTEL: + return "NumbanksINTEL"; + case SpvDecorationBankwidthINTEL: + return "BankwidthINTEL"; + case SpvDecorationMaxPrivateCopiesINTEL: + return "MaxPrivateCopiesINTEL"; + case SpvDecorationSinglepumpINTEL: + return "SinglepumpINTEL"; + case SpvDecorationDoublepumpINTEL: + return "DoublepumpINTEL"; + case SpvDecorationMaxReplicatesINTEL: + return "MaxReplicatesINTEL"; + case SpvDecorationSimpleDualPortINTEL: + return "SimpleDualPortINTEL"; + case SpvDecorationMergeINTEL: + return "MergeINTEL"; + case SpvDecorationBankBitsINTEL: + return "BankBitsINTEL"; + case SpvDecorationForcePow2DepthINTEL: + return "ForcePow2DepthINTEL"; + case SpvDecorationStridesizeINTEL: + return "StridesizeINTEL"; + case SpvDecorationWordsizeINTEL: + return "WordsizeINTEL"; + case SpvDecorationTrueDualPortINTEL: + return "TrueDualPortINTEL"; + case SpvDecorationBurstCoalesceINTEL: + return "BurstCoalesceINTEL"; + case SpvDecorationCacheSizeINTEL: + return "CacheSizeINTEL"; + case SpvDecorationDontStaticallyCoalesceINTEL: + return "DontStaticallyCoalesceINTEL"; + case SpvDecorationPrefetchINTEL: + return "PrefetchINTEL"; + case SpvDecorationStallEnableINTEL: + return "StallEnableINTEL"; + case SpvDecorationFuseLoopsInFunctionINTEL: + return "FuseLoopsInFunctionINTEL"; + case SpvDecorationMathOpDSPModeINTEL: + return "MathOpDSPModeINTEL"; + case SpvDecorationAliasScopeINTEL: + return "AliasScopeINTEL"; + case SpvDecorationNoAliasINTEL: + return "NoAliasINTEL"; + case SpvDecorationInitiationIntervalINTEL: + return "InitiationIntervalINTEL"; + case SpvDecorationMaxConcurrencyINTEL: + return "MaxConcurrencyINTEL"; + case SpvDecorationPipelineEnableINTEL: + return "PipelineEnableINTEL"; + case SpvDecorationBufferLocationINTEL: + return "BufferLocationINTEL"; + case SpvDecorationIOPipeStorageINTEL: + return "IOPipeStorageINTEL"; + case SpvDecorationFunctionFloatingPointModeINTEL: + return "FunctionFloatingPointModeINTEL"; + case SpvDecorationSingleElementVectorINTEL: + return "SingleElementVectorINTEL"; + case SpvDecorationVectorComputeCallableFunctionINTEL: + return "VectorComputeCallableFunctionINTEL"; + case SpvDecorationMediaBlockIOINTEL: + return "MediaBlockIOINTEL"; + case SpvDecorationStallFreeINTEL: + return "StallFreeINTEL"; + case SpvDecorationFPMaxErrorDecorationINTEL: + return "FPMaxErrorDecorationINTEL"; + case SpvDecorationLatencyControlLabelINTEL: + return "LatencyControlLabelINTEL"; + case SpvDecorationLatencyControlConstraintINTEL: + return "LatencyControlConstraintINTEL"; + case SpvDecorationConduitKernelArgumentINTEL: + return "ConduitKernelArgumentINTEL"; + case SpvDecorationRegisterMapKernelArgumentINTEL: + return "RegisterMapKernelArgumentINTEL"; + case SpvDecorationMMHostInterfaceAddressWidthINTEL: + return "MMHostInterfaceAddressWidthINTEL"; + case SpvDecorationMMHostInterfaceDataWidthINTEL: + return "MMHostInterfaceDataWidthINTEL"; + case SpvDecorationMMHostInterfaceLatencyINTEL: + return "MMHostInterfaceLatencyINTEL"; + case SpvDecorationMMHostInterfaceReadWriteModeINTEL: + return "MMHostInterfaceReadWriteModeINTEL"; + case SpvDecorationMMHostInterfaceMaxBurstINTEL: + return "MMHostInterfaceMaxBurstINTEL"; + case SpvDecorationMMHostInterfaceWaitRequestINTEL: + return "MMHostInterfaceWaitRequestINTEL"; + case SpvDecorationStableKernelArgumentINTEL: + return "StableKernelArgumentINTEL"; + case SpvDecorationHostAccessINTEL: + return "HostAccessINTEL"; + case SpvDecorationInitModeINTEL: + return "InitModeINTEL"; + case SpvDecorationImplementInRegisterMapINTEL: + return "ImplementInRegisterMapINTEL"; + case SpvDecorationConditionalINTEL: + return "ConditionalINTEL"; + case SpvDecorationCacheControlLoadINTEL: + return "CacheControlLoadINTEL"; + case SpvDecorationCacheControlStoreINTEL: + return "CacheControlStoreINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvBuiltInToString(SpvBuiltIn value) { + switch (value) { + case SpvBuiltInPosition: + return "Position"; + case SpvBuiltInPointSize: + return "PointSize"; + case SpvBuiltInClipDistance: + return "ClipDistance"; + case SpvBuiltInCullDistance: + return "CullDistance"; + case SpvBuiltInVertexId: + return "VertexId"; + case SpvBuiltInInstanceId: + return "InstanceId"; + case SpvBuiltInPrimitiveId: + return "PrimitiveId"; + case SpvBuiltInInvocationId: + return "InvocationId"; + case SpvBuiltInLayer: + return "Layer"; + case SpvBuiltInViewportIndex: + return "ViewportIndex"; + case SpvBuiltInTessLevelOuter: + return "TessLevelOuter"; + case SpvBuiltInTessLevelInner: + return "TessLevelInner"; + case SpvBuiltInTessCoord: + return "TessCoord"; + case SpvBuiltInPatchVertices: + return "PatchVertices"; + case SpvBuiltInFragCoord: + return "FragCoord"; + case SpvBuiltInPointCoord: + return "PointCoord"; + case SpvBuiltInFrontFacing: + return "FrontFacing"; + case SpvBuiltInSampleId: + return "SampleId"; + case SpvBuiltInSamplePosition: + return "SamplePosition"; + case SpvBuiltInSampleMask: + return "SampleMask"; + case SpvBuiltInFragDepth: + return "FragDepth"; + case SpvBuiltInHelperInvocation: + return "HelperInvocation"; + case SpvBuiltInNumWorkgroups: + return "NumWorkgroups"; + case SpvBuiltInWorkgroupSize: + return "WorkgroupSize"; + case SpvBuiltInWorkgroupId: + return "WorkgroupId"; + case SpvBuiltInLocalInvocationId: + return "LocalInvocationId"; + case SpvBuiltInGlobalInvocationId: + return "GlobalInvocationId"; + case SpvBuiltInLocalInvocationIndex: + return "LocalInvocationIndex"; + case SpvBuiltInWorkDim: + return "WorkDim"; + case SpvBuiltInGlobalSize: + return "GlobalSize"; + case SpvBuiltInEnqueuedWorkgroupSize: + return "EnqueuedWorkgroupSize"; + case SpvBuiltInGlobalOffset: + return "GlobalOffset"; + case SpvBuiltInGlobalLinearId: + return "GlobalLinearId"; + case SpvBuiltInSubgroupSize: + return "SubgroupSize"; + case SpvBuiltInSubgroupMaxSize: + return "SubgroupMaxSize"; + case SpvBuiltInNumSubgroups: + return "NumSubgroups"; + case SpvBuiltInNumEnqueuedSubgroups: + return "NumEnqueuedSubgroups"; + case SpvBuiltInSubgroupId: + return "SubgroupId"; + case SpvBuiltInSubgroupLocalInvocationId: + return "SubgroupLocalInvocationId"; + case SpvBuiltInVertexIndex: + return "VertexIndex"; + case SpvBuiltInInstanceIndex: + return "InstanceIndex"; + case SpvBuiltInCoreIDARM: + return "CoreIDARM"; + case SpvBuiltInCoreCountARM: + return "CoreCountARM"; + case SpvBuiltInCoreMaxIDARM: + return "CoreMaxIDARM"; + case SpvBuiltInWarpIDARM: + return "WarpIDARM"; + case SpvBuiltInWarpMaxIDARM: + return "WarpMaxIDARM"; + case SpvBuiltInSubgroupEqMask: + return "SubgroupEqMask"; + case SpvBuiltInSubgroupGeMask: + return "SubgroupGeMask"; + case SpvBuiltInSubgroupGtMask: + return "SubgroupGtMask"; + case SpvBuiltInSubgroupLeMask: + return "SubgroupLeMask"; + case SpvBuiltInSubgroupLtMask: + return "SubgroupLtMask"; + case SpvBuiltInBaseVertex: + return "BaseVertex"; + case SpvBuiltInBaseInstance: + return "BaseInstance"; + case SpvBuiltInDrawIndex: + return "DrawIndex"; + case SpvBuiltInPrimitiveShadingRateKHR: + return "PrimitiveShadingRateKHR"; + case SpvBuiltInDeviceIndex: + return "DeviceIndex"; + case SpvBuiltInViewIndex: + return "ViewIndex"; + case SpvBuiltInShadingRateKHR: + return "ShadingRateKHR"; + case SpvBuiltInTileOffsetQCOM: + return "TileOffsetQCOM"; + case SpvBuiltInTileDimensionQCOM: + return "TileDimensionQCOM"; + case SpvBuiltInTileApronSizeQCOM: + return "TileApronSizeQCOM"; + case SpvBuiltInBaryCoordNoPerspAMD: + return "BaryCoordNoPerspAMD"; + case SpvBuiltInBaryCoordNoPerspCentroidAMD: + return "BaryCoordNoPerspCentroidAMD"; + case SpvBuiltInBaryCoordNoPerspSampleAMD: + return "BaryCoordNoPerspSampleAMD"; + case SpvBuiltInBaryCoordSmoothAMD: + return "BaryCoordSmoothAMD"; + case SpvBuiltInBaryCoordSmoothCentroidAMD: + return "BaryCoordSmoothCentroidAMD"; + case SpvBuiltInBaryCoordSmoothSampleAMD: + return "BaryCoordSmoothSampleAMD"; + case SpvBuiltInBaryCoordPullModelAMD: + return "BaryCoordPullModelAMD"; + case SpvBuiltInFragStencilRefEXT: + return "FragStencilRefEXT"; + case SpvBuiltInRemainingRecursionLevelsAMDX: + return "RemainingRecursionLevelsAMDX"; + case SpvBuiltInShaderIndexAMDX: + return "ShaderIndexAMDX"; + case SpvBuiltInViewportMaskNV: + return "ViewportMaskNV"; + case SpvBuiltInSecondaryPositionNV: + return "SecondaryPositionNV"; + case SpvBuiltInSecondaryViewportMaskNV: + return "SecondaryViewportMaskNV"; + case SpvBuiltInPositionPerViewNV: + return "PositionPerViewNV"; + case SpvBuiltInViewportMaskPerViewNV: + return "ViewportMaskPerViewNV"; + case SpvBuiltInFullyCoveredEXT: + return "FullyCoveredEXT"; + case SpvBuiltInTaskCountNV: + return "TaskCountNV"; + case SpvBuiltInPrimitiveCountNV: + return "PrimitiveCountNV"; + case SpvBuiltInPrimitiveIndicesNV: + return "PrimitiveIndicesNV"; + case SpvBuiltInClipDistancePerViewNV: + return "ClipDistancePerViewNV"; + case SpvBuiltInCullDistancePerViewNV: + return "CullDistancePerViewNV"; + case SpvBuiltInLayerPerViewNV: + return "LayerPerViewNV"; + case SpvBuiltInMeshViewCountNV: + return "MeshViewCountNV"; + case SpvBuiltInMeshViewIndicesNV: + return "MeshViewIndicesNV"; + case SpvBuiltInBaryCoordKHR: + return "BaryCoordKHR"; + case SpvBuiltInBaryCoordNoPerspKHR: + return "BaryCoordNoPerspKHR"; + case SpvBuiltInFragSizeEXT: + return "FragSizeEXT"; + case SpvBuiltInFragInvocationCountEXT: + return "FragInvocationCountEXT"; + case SpvBuiltInPrimitivePointIndicesEXT: + return "PrimitivePointIndicesEXT"; + case SpvBuiltInPrimitiveLineIndicesEXT: + return "PrimitiveLineIndicesEXT"; + case SpvBuiltInPrimitiveTriangleIndicesEXT: + return "PrimitiveTriangleIndicesEXT"; + case SpvBuiltInCullPrimitiveEXT: + return "CullPrimitiveEXT"; + case SpvBuiltInLaunchIdKHR: + return "LaunchIdKHR"; + case SpvBuiltInLaunchSizeKHR: + return "LaunchSizeKHR"; + case SpvBuiltInWorldRayOriginKHR: + return "WorldRayOriginKHR"; + case SpvBuiltInWorldRayDirectionKHR: + return "WorldRayDirectionKHR"; + case SpvBuiltInObjectRayOriginKHR: + return "ObjectRayOriginKHR"; + case SpvBuiltInObjectRayDirectionKHR: + return "ObjectRayDirectionKHR"; + case SpvBuiltInRayTminKHR: + return "RayTminKHR"; + case SpvBuiltInRayTmaxKHR: + return "RayTmaxKHR"; + case SpvBuiltInInstanceCustomIndexKHR: + return "InstanceCustomIndexKHR"; + case SpvBuiltInObjectToWorldKHR: + return "ObjectToWorldKHR"; + case SpvBuiltInWorldToObjectKHR: + return "WorldToObjectKHR"; + case SpvBuiltInHitTNV: + return "HitTNV"; + case SpvBuiltInHitKindKHR: + return "HitKindKHR"; + case SpvBuiltInCurrentRayTimeNV: + return "CurrentRayTimeNV"; + case SpvBuiltInHitTriangleVertexPositionsKHR: + return "HitTriangleVertexPositionsKHR"; + case SpvBuiltInHitMicroTriangleVertexPositionsNV: + return "HitMicroTriangleVertexPositionsNV"; + case SpvBuiltInHitMicroTriangleVertexBarycentricsNV: + return "HitMicroTriangleVertexBarycentricsNV"; + case SpvBuiltInIncomingRayFlagsKHR: + return "IncomingRayFlagsKHR"; + case SpvBuiltInRayGeometryIndexKHR: + return "RayGeometryIndexKHR"; + case SpvBuiltInHitIsSphereNV: + return "HitIsSphereNV"; + case SpvBuiltInHitIsLSSNV: + return "HitIsLSSNV"; + case SpvBuiltInHitSpherePositionNV: + return "HitSpherePositionNV"; + case SpvBuiltInWarpsPerSMNV: + return "WarpsPerSMNV"; + case SpvBuiltInSMCountNV: + return "SMCountNV"; + case SpvBuiltInWarpIDNV: + return "WarpIDNV"; + case SpvBuiltInSMIDNV: + return "SMIDNV"; + case SpvBuiltInHitLSSPositionsNV: + return "HitLSSPositionsNV"; + case SpvBuiltInHitKindFrontFacingMicroTriangleNV: + return "HitKindFrontFacingMicroTriangleNV"; + case SpvBuiltInHitKindBackFacingMicroTriangleNV: + return "HitKindBackFacingMicroTriangleNV"; + case SpvBuiltInHitSphereRadiusNV: + return "HitSphereRadiusNV"; + case SpvBuiltInHitLSSRadiiNV: + return "HitLSSRadiiNV"; + case SpvBuiltInClusterIDNV: + return "ClusterIDNV"; + case SpvBuiltInCullMaskKHR: + return "CullMaskKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvScopeToString(SpvScope value) { + switch (value) { + case SpvScopeCrossDevice: + return "CrossDevice"; + case SpvScopeDevice: + return "Device"; + case SpvScopeWorkgroup: + return "Workgroup"; + case SpvScopeSubgroup: + return "Subgroup"; + case SpvScopeInvocation: + return "Invocation"; + case SpvScopeQueueFamily: + return "QueueFamily"; + case SpvScopeShaderCallKHR: + return "ShaderCallKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvGroupOperationToString(SpvGroupOperation value) { + switch (value) { + case SpvGroupOperationReduce: + return "Reduce"; + case SpvGroupOperationInclusiveScan: + return "InclusiveScan"; + case SpvGroupOperationExclusiveScan: + return "ExclusiveScan"; + case SpvGroupOperationClusteredReduce: + return "ClusteredReduce"; + case SpvGroupOperationPartitionedReduceNV: + return "PartitionedReduceNV"; + case SpvGroupOperationPartitionedInclusiveScanNV: + return "PartitionedInclusiveScanNV"; + case SpvGroupOperationPartitionedExclusiveScanNV: + return "PartitionedExclusiveScanNV"; + default: + return "Unknown"; + } +} + +inline const char* SpvKernelEnqueueFlagsToString(SpvKernelEnqueueFlags value) { + switch (value) { + case SpvKernelEnqueueFlagsNoWait: + return "NoWait"; + case SpvKernelEnqueueFlagsWaitKernel: + return "WaitKernel"; + case SpvKernelEnqueueFlagsWaitWorkGroup: + return "WaitWorkGroup"; + default: + return "Unknown"; + } +} + +inline const char* SpvCapabilityToString(SpvCapability value) { + switch (value) { + case SpvCapabilityMatrix: + return "Matrix"; + case SpvCapabilityShader: + return "Shader"; + case SpvCapabilityGeometry: + return "Geometry"; + case SpvCapabilityTessellation: + return "Tessellation"; + case SpvCapabilityAddresses: + return "Addresses"; + case SpvCapabilityLinkage: + return "Linkage"; + case SpvCapabilityKernel: + return "Kernel"; + case SpvCapabilityVector16: + return "Vector16"; + case SpvCapabilityFloat16Buffer: + return "Float16Buffer"; + case SpvCapabilityFloat16: + return "Float16"; + case SpvCapabilityFloat64: + return "Float64"; + case SpvCapabilityInt64: + return "Int64"; + case SpvCapabilityInt64Atomics: + return "Int64Atomics"; + case SpvCapabilityImageBasic: + return "ImageBasic"; + case SpvCapabilityImageReadWrite: + return "ImageReadWrite"; + case SpvCapabilityImageMipmap: + return "ImageMipmap"; + case SpvCapabilityPipes: + return "Pipes"; + case SpvCapabilityGroups: + return "Groups"; + case SpvCapabilityDeviceEnqueue: + return "DeviceEnqueue"; + case SpvCapabilityLiteralSampler: + return "LiteralSampler"; + case SpvCapabilityAtomicStorage: + return "AtomicStorage"; + case SpvCapabilityInt16: + return "Int16"; + case SpvCapabilityTessellationPointSize: + return "TessellationPointSize"; + case SpvCapabilityGeometryPointSize: + return "GeometryPointSize"; + case SpvCapabilityImageGatherExtended: + return "ImageGatherExtended"; + case SpvCapabilityStorageImageMultisample: + return "StorageImageMultisample"; + case SpvCapabilityUniformBufferArrayDynamicIndexing: + return "UniformBufferArrayDynamicIndexing"; + case SpvCapabilitySampledImageArrayDynamicIndexing: + return "SampledImageArrayDynamicIndexing"; + case SpvCapabilityStorageBufferArrayDynamicIndexing: + return "StorageBufferArrayDynamicIndexing"; + case SpvCapabilityStorageImageArrayDynamicIndexing: + return "StorageImageArrayDynamicIndexing"; + case SpvCapabilityClipDistance: + return "ClipDistance"; + case SpvCapabilityCullDistance: + return "CullDistance"; + case SpvCapabilityImageCubeArray: + return "ImageCubeArray"; + case SpvCapabilitySampleRateShading: + return "SampleRateShading"; + case SpvCapabilityImageRect: + return "ImageRect"; + case SpvCapabilitySampledRect: + return "SampledRect"; + case SpvCapabilityGenericPointer: + return "GenericPointer"; + case SpvCapabilityInt8: + return "Int8"; + case SpvCapabilityInputAttachment: + return "InputAttachment"; + case SpvCapabilitySparseResidency: + return "SparseResidency"; + case SpvCapabilityMinLod: + return "MinLod"; + case SpvCapabilitySampled1D: + return "Sampled1D"; + case SpvCapabilityImage1D: + return "Image1D"; + case SpvCapabilitySampledCubeArray: + return "SampledCubeArray"; + case SpvCapabilitySampledBuffer: + return "SampledBuffer"; + case SpvCapabilityImageBuffer: + return "ImageBuffer"; + case SpvCapabilityImageMSArray: + return "ImageMSArray"; + case SpvCapabilityStorageImageExtendedFormats: + return "StorageImageExtendedFormats"; + case SpvCapabilityImageQuery: + return "ImageQuery"; + case SpvCapabilityDerivativeControl: + return "DerivativeControl"; + case SpvCapabilityInterpolationFunction: + return "InterpolationFunction"; + case SpvCapabilityTransformFeedback: + return "TransformFeedback"; + case SpvCapabilityGeometryStreams: + return "GeometryStreams"; + case SpvCapabilityStorageImageReadWithoutFormat: + return "StorageImageReadWithoutFormat"; + case SpvCapabilityStorageImageWriteWithoutFormat: + return "StorageImageWriteWithoutFormat"; + case SpvCapabilityMultiViewport: + return "MultiViewport"; + case SpvCapabilitySubgroupDispatch: + return "SubgroupDispatch"; + case SpvCapabilityNamedBarrier: + return "NamedBarrier"; + case SpvCapabilityPipeStorage: + return "PipeStorage"; + case SpvCapabilityGroupNonUniform: + return "GroupNonUniform"; + case SpvCapabilityGroupNonUniformVote: + return "GroupNonUniformVote"; + case SpvCapabilityGroupNonUniformArithmetic: + return "GroupNonUniformArithmetic"; + case SpvCapabilityGroupNonUniformBallot: + return "GroupNonUniformBallot"; + case SpvCapabilityGroupNonUniformShuffle: + return "GroupNonUniformShuffle"; + case SpvCapabilityGroupNonUniformShuffleRelative: + return "GroupNonUniformShuffleRelative"; + case SpvCapabilityGroupNonUniformClustered: + return "GroupNonUniformClustered"; + case SpvCapabilityGroupNonUniformQuad: + return "GroupNonUniformQuad"; + case SpvCapabilityShaderLayer: + return "ShaderLayer"; + case SpvCapabilityShaderViewportIndex: + return "ShaderViewportIndex"; + case SpvCapabilityUniformDecoration: + return "UniformDecoration"; + case SpvCapabilityCoreBuiltinsARM: + return "CoreBuiltinsARM"; + case SpvCapabilityTileImageColorReadAccessEXT: + return "TileImageColorReadAccessEXT"; + case SpvCapabilityTileImageDepthReadAccessEXT: + return "TileImageDepthReadAccessEXT"; + case SpvCapabilityTileImageStencilReadAccessEXT: + return "TileImageStencilReadAccessEXT"; + case SpvCapabilityTensorsARM: + return "TensorsARM"; + case SpvCapabilityStorageTensorArrayDynamicIndexingARM: + return "StorageTensorArrayDynamicIndexingARM"; + case SpvCapabilityStorageTensorArrayNonUniformIndexingARM: + return "StorageTensorArrayNonUniformIndexingARM"; + case SpvCapabilityGraphARM: + return "GraphARM"; + case SpvCapabilityCooperativeMatrixLayoutsARM: + return "CooperativeMatrixLayoutsARM"; + case SpvCapabilityFloat8EXT: + return "Float8EXT"; + case SpvCapabilityFloat8CooperativeMatrixEXT: + return "Float8CooperativeMatrixEXT"; + case SpvCapabilityFragmentShadingRateKHR: + return "FragmentShadingRateKHR"; + case SpvCapabilitySubgroupBallotKHR: + return "SubgroupBallotKHR"; + case SpvCapabilityDrawParameters: + return "DrawParameters"; + case SpvCapabilityWorkgroupMemoryExplicitLayoutKHR: + return "WorkgroupMemoryExplicitLayoutKHR"; + case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: + return "WorkgroupMemoryExplicitLayout8BitAccessKHR"; + case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: + return "WorkgroupMemoryExplicitLayout16BitAccessKHR"; + case SpvCapabilitySubgroupVoteKHR: + return "SubgroupVoteKHR"; + case SpvCapabilityStorageBuffer16BitAccess: + return "StorageBuffer16BitAccess"; + case SpvCapabilityStorageUniform16: + return "StorageUniform16"; + case SpvCapabilityStoragePushConstant16: + return "StoragePushConstant16"; + case SpvCapabilityStorageInputOutput16: + return "StorageInputOutput16"; + case SpvCapabilityDeviceGroup: + return "DeviceGroup"; + case SpvCapabilityMultiView: + return "MultiView"; + case SpvCapabilityVariablePointersStorageBuffer: + return "VariablePointersStorageBuffer"; + case SpvCapabilityVariablePointers: + return "VariablePointers"; + case SpvCapabilityAtomicStorageOps: + return "AtomicStorageOps"; + case SpvCapabilitySampleMaskPostDepthCoverage: + return "SampleMaskPostDepthCoverage"; + case SpvCapabilityStorageBuffer8BitAccess: + return "StorageBuffer8BitAccess"; + case SpvCapabilityUniformAndStorageBuffer8BitAccess: + return "UniformAndStorageBuffer8BitAccess"; + case SpvCapabilityStoragePushConstant8: + return "StoragePushConstant8"; + case SpvCapabilityDenormPreserve: + return "DenormPreserve"; + case SpvCapabilityDenormFlushToZero: + return "DenormFlushToZero"; + case SpvCapabilitySignedZeroInfNanPreserve: + return "SignedZeroInfNanPreserve"; + case SpvCapabilityRoundingModeRTE: + return "RoundingModeRTE"; + case SpvCapabilityRoundingModeRTZ: + return "RoundingModeRTZ"; + case SpvCapabilityRayQueryProvisionalKHR: + return "RayQueryProvisionalKHR"; + case SpvCapabilityRayQueryKHR: + return "RayQueryKHR"; + case SpvCapabilityUntypedPointersKHR: + return "UntypedPointersKHR"; + case SpvCapabilityRayTraversalPrimitiveCullingKHR: + return "RayTraversalPrimitiveCullingKHR"; + case SpvCapabilityRayTracingKHR: + return "RayTracingKHR"; + case SpvCapabilityTextureSampleWeightedQCOM: + return "TextureSampleWeightedQCOM"; + case SpvCapabilityTextureBoxFilterQCOM: + return "TextureBoxFilterQCOM"; + case SpvCapabilityTextureBlockMatchQCOM: + return "TextureBlockMatchQCOM"; + case SpvCapabilityTileShadingQCOM: + return "TileShadingQCOM"; + case SpvCapabilityCooperativeMatrixConversionQCOM: + return "CooperativeMatrixConversionQCOM"; + case SpvCapabilityTextureBlockMatch2QCOM: + return "TextureBlockMatch2QCOM"; + case SpvCapabilityFloat16ImageAMD: + return "Float16ImageAMD"; + case SpvCapabilityImageGatherBiasLodAMD: + return "ImageGatherBiasLodAMD"; + case SpvCapabilityFragmentMaskAMD: + return "FragmentMaskAMD"; + case SpvCapabilityStencilExportEXT: + return "StencilExportEXT"; + case SpvCapabilityImageReadWriteLodAMD: + return "ImageReadWriteLodAMD"; + case SpvCapabilityInt64ImageEXT: + return "Int64ImageEXT"; + case SpvCapabilityShaderClockKHR: + return "ShaderClockKHR"; + case SpvCapabilityShaderEnqueueAMDX: + return "ShaderEnqueueAMDX"; + case SpvCapabilityQuadControlKHR: + return "QuadControlKHR"; + case SpvCapabilityInt4TypeINTEL: + return "Int4TypeINTEL"; + case SpvCapabilityInt4CooperativeMatrixINTEL: + return "Int4CooperativeMatrixINTEL"; + case SpvCapabilityBFloat16TypeKHR: + return "BFloat16TypeKHR"; + case SpvCapabilityBFloat16DotProductKHR: + return "BFloat16DotProductKHR"; + case SpvCapabilityBFloat16CooperativeMatrixKHR: + return "BFloat16CooperativeMatrixKHR"; + case SpvCapabilitySampleMaskOverrideCoverageNV: + return "SampleMaskOverrideCoverageNV"; + case SpvCapabilityGeometryShaderPassthroughNV: + return "GeometryShaderPassthroughNV"; + case SpvCapabilityShaderViewportIndexLayerEXT: + return "ShaderViewportIndexLayerEXT"; + case SpvCapabilityShaderViewportMaskNV: + return "ShaderViewportMaskNV"; + case SpvCapabilityShaderStereoViewNV: + return "ShaderStereoViewNV"; + case SpvCapabilityPerViewAttributesNV: + return "PerViewAttributesNV"; + case SpvCapabilityFragmentFullyCoveredEXT: + return "FragmentFullyCoveredEXT"; + case SpvCapabilityMeshShadingNV: + return "MeshShadingNV"; + case SpvCapabilityImageFootprintNV: + return "ImageFootprintNV"; + case SpvCapabilityMeshShadingEXT: + return "MeshShadingEXT"; + case SpvCapabilityFragmentBarycentricKHR: + return "FragmentBarycentricKHR"; + case SpvCapabilityComputeDerivativeGroupQuadsKHR: + return "ComputeDerivativeGroupQuadsKHR"; + case SpvCapabilityFragmentDensityEXT: + return "FragmentDensityEXT"; + case SpvCapabilityGroupNonUniformPartitionedNV: + return "GroupNonUniformPartitionedNV"; + case SpvCapabilityShaderNonUniform: + return "ShaderNonUniform"; + case SpvCapabilityRuntimeDescriptorArray: + return "RuntimeDescriptorArray"; + case SpvCapabilityInputAttachmentArrayDynamicIndexing: + return "InputAttachmentArrayDynamicIndexing"; + case SpvCapabilityUniformTexelBufferArrayDynamicIndexing: + return "UniformTexelBufferArrayDynamicIndexing"; + case SpvCapabilityStorageTexelBufferArrayDynamicIndexing: + return "StorageTexelBufferArrayDynamicIndexing"; + case SpvCapabilityUniformBufferArrayNonUniformIndexing: + return "UniformBufferArrayNonUniformIndexing"; + case SpvCapabilitySampledImageArrayNonUniformIndexing: + return "SampledImageArrayNonUniformIndexing"; + case SpvCapabilityStorageBufferArrayNonUniformIndexing: + return "StorageBufferArrayNonUniformIndexing"; + case SpvCapabilityStorageImageArrayNonUniformIndexing: + return "StorageImageArrayNonUniformIndexing"; + case SpvCapabilityInputAttachmentArrayNonUniformIndexing: + return "InputAttachmentArrayNonUniformIndexing"; + case SpvCapabilityUniformTexelBufferArrayNonUniformIndexing: + return "UniformTexelBufferArrayNonUniformIndexing"; + case SpvCapabilityStorageTexelBufferArrayNonUniformIndexing: + return "StorageTexelBufferArrayNonUniformIndexing"; + case SpvCapabilityRayTracingPositionFetchKHR: + return "RayTracingPositionFetchKHR"; + case SpvCapabilityRayTracingNV: + return "RayTracingNV"; + case SpvCapabilityRayTracingMotionBlurNV: + return "RayTracingMotionBlurNV"; + case SpvCapabilityVulkanMemoryModel: + return "VulkanMemoryModel"; + case SpvCapabilityVulkanMemoryModelDeviceScope: + return "VulkanMemoryModelDeviceScope"; + case SpvCapabilityPhysicalStorageBufferAddresses: + return "PhysicalStorageBufferAddresses"; + case SpvCapabilityComputeDerivativeGroupLinearKHR: + return "ComputeDerivativeGroupLinearKHR"; + case SpvCapabilityRayTracingProvisionalKHR: + return "RayTracingProvisionalKHR"; + case SpvCapabilityCooperativeMatrixNV: + return "CooperativeMatrixNV"; + case SpvCapabilityFragmentShaderSampleInterlockEXT: + return "FragmentShaderSampleInterlockEXT"; + case SpvCapabilityFragmentShaderShadingRateInterlockEXT: + return "FragmentShaderShadingRateInterlockEXT"; + case SpvCapabilityShaderSMBuiltinsNV: + return "ShaderSMBuiltinsNV"; + case SpvCapabilityFragmentShaderPixelInterlockEXT: + return "FragmentShaderPixelInterlockEXT"; + case SpvCapabilityDemoteToHelperInvocation: + return "DemoteToHelperInvocation"; + case SpvCapabilityDisplacementMicromapNV: + return "DisplacementMicromapNV"; + case SpvCapabilityRayTracingOpacityMicromapEXT: + return "RayTracingOpacityMicromapEXT"; + case SpvCapabilityShaderInvocationReorderNV: + return "ShaderInvocationReorderNV"; + case SpvCapabilityBindlessTextureNV: + return "BindlessTextureNV"; + case SpvCapabilityRayQueryPositionFetchKHR: + return "RayQueryPositionFetchKHR"; + case SpvCapabilityCooperativeVectorNV: + return "CooperativeVectorNV"; + case SpvCapabilityAtomicFloat16VectorNV: + return "AtomicFloat16VectorNV"; + case SpvCapabilityRayTracingDisplacementMicromapNV: + return "RayTracingDisplacementMicromapNV"; + case SpvCapabilityRawAccessChainsNV: + return "RawAccessChainsNV"; + case SpvCapabilityRayTracingSpheresGeometryNV: + return "RayTracingSpheresGeometryNV"; + case SpvCapabilityRayTracingLinearSweptSpheresGeometryNV: + return "RayTracingLinearSweptSpheresGeometryNV"; + case SpvCapabilityCooperativeMatrixReductionsNV: + return "CooperativeMatrixReductionsNV"; + case SpvCapabilityCooperativeMatrixConversionsNV: + return "CooperativeMatrixConversionsNV"; + case SpvCapabilityCooperativeMatrixPerElementOperationsNV: + return "CooperativeMatrixPerElementOperationsNV"; + case SpvCapabilityCooperativeMatrixTensorAddressingNV: + return "CooperativeMatrixTensorAddressingNV"; + case SpvCapabilityCooperativeMatrixBlockLoadsNV: + return "CooperativeMatrixBlockLoadsNV"; + case SpvCapabilityCooperativeVectorTrainingNV: + return "CooperativeVectorTrainingNV"; + case SpvCapabilityRayTracingClusterAccelerationStructureNV: + return "RayTracingClusterAccelerationStructureNV"; + case SpvCapabilityTensorAddressingNV: + return "TensorAddressingNV"; + case SpvCapabilitySubgroupShuffleINTEL: + return "SubgroupShuffleINTEL"; + case SpvCapabilitySubgroupBufferBlockIOINTEL: + return "SubgroupBufferBlockIOINTEL"; + case SpvCapabilitySubgroupImageBlockIOINTEL: + return "SubgroupImageBlockIOINTEL"; + case SpvCapabilitySubgroupImageMediaBlockIOINTEL: + return "SubgroupImageMediaBlockIOINTEL"; + case SpvCapabilityRoundToInfinityINTEL: + return "RoundToInfinityINTEL"; + case SpvCapabilityFloatingPointModeINTEL: + return "FloatingPointModeINTEL"; + case SpvCapabilityIntegerFunctions2INTEL: + return "IntegerFunctions2INTEL"; + case SpvCapabilityFunctionPointersINTEL: + return "FunctionPointersINTEL"; + case SpvCapabilityIndirectReferencesINTEL: + return "IndirectReferencesINTEL"; + case SpvCapabilityAsmINTEL: + return "AsmINTEL"; + case SpvCapabilityAtomicFloat32MinMaxEXT: + return "AtomicFloat32MinMaxEXT"; + case SpvCapabilityAtomicFloat64MinMaxEXT: + return "AtomicFloat64MinMaxEXT"; + case SpvCapabilityAtomicFloat16MinMaxEXT: + return "AtomicFloat16MinMaxEXT"; + case SpvCapabilityVectorComputeINTEL: + return "VectorComputeINTEL"; + case SpvCapabilityVectorAnyINTEL: + return "VectorAnyINTEL"; + case SpvCapabilityExpectAssumeKHR: + return "ExpectAssumeKHR"; + case SpvCapabilitySubgroupAvcMotionEstimationINTEL: + return "SubgroupAvcMotionEstimationINTEL"; + case SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL: + return "SubgroupAvcMotionEstimationIntraINTEL"; + case SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL: + return "SubgroupAvcMotionEstimationChromaINTEL"; + case SpvCapabilityVariableLengthArrayINTEL: + return "VariableLengthArrayINTEL"; + case SpvCapabilityFunctionFloatControlINTEL: + return "FunctionFloatControlINTEL"; + case SpvCapabilityFPGAMemoryAttributesINTEL: + return "FPGAMemoryAttributesINTEL"; + case SpvCapabilityFPFastMathModeINTEL: + return "FPFastMathModeINTEL"; + case SpvCapabilityArbitraryPrecisionIntegersINTEL: + return "ArbitraryPrecisionIntegersINTEL"; + case SpvCapabilityArbitraryPrecisionFloatingPointINTEL: + return "ArbitraryPrecisionFloatingPointINTEL"; + case SpvCapabilityUnstructuredLoopControlsINTEL: + return "UnstructuredLoopControlsINTEL"; + case SpvCapabilityFPGALoopControlsINTEL: + return "FPGALoopControlsINTEL"; + case SpvCapabilityKernelAttributesINTEL: + return "KernelAttributesINTEL"; + case SpvCapabilityFPGAKernelAttributesINTEL: + return "FPGAKernelAttributesINTEL"; + case SpvCapabilityFPGAMemoryAccessesINTEL: + return "FPGAMemoryAccessesINTEL"; + case SpvCapabilityFPGAClusterAttributesINTEL: + return "FPGAClusterAttributesINTEL"; + case SpvCapabilityLoopFuseINTEL: + return "LoopFuseINTEL"; + case SpvCapabilityFPGADSPControlINTEL: + return "FPGADSPControlINTEL"; + case SpvCapabilityMemoryAccessAliasingINTEL: + return "MemoryAccessAliasingINTEL"; + case SpvCapabilityFPGAInvocationPipeliningAttributesINTEL: + return "FPGAInvocationPipeliningAttributesINTEL"; + case SpvCapabilityFPGABufferLocationINTEL: + return "FPGABufferLocationINTEL"; + case SpvCapabilityArbitraryPrecisionFixedPointINTEL: + return "ArbitraryPrecisionFixedPointINTEL"; + case SpvCapabilityUSMStorageClassesINTEL: + return "USMStorageClassesINTEL"; + case SpvCapabilityRuntimeAlignedAttributeINTEL: + return "RuntimeAlignedAttributeINTEL"; + case SpvCapabilityIOPipesINTEL: + return "IOPipesINTEL"; + case SpvCapabilityBlockingPipesINTEL: + return "BlockingPipesINTEL"; + case SpvCapabilityFPGARegINTEL: + return "FPGARegINTEL"; + case SpvCapabilityDotProductInputAll: + return "DotProductInputAll"; + case SpvCapabilityDotProductInput4x8Bit: + return "DotProductInput4x8Bit"; + case SpvCapabilityDotProductInput4x8BitPacked: + return "DotProductInput4x8BitPacked"; + case SpvCapabilityDotProduct: + return "DotProduct"; + case SpvCapabilityRayCullMaskKHR: + return "RayCullMaskKHR"; + case SpvCapabilityCooperativeMatrixKHR: + return "CooperativeMatrixKHR"; + case SpvCapabilityReplicatedCompositesEXT: + return "ReplicatedCompositesEXT"; + case SpvCapabilityBitInstructions: + return "BitInstructions"; + case SpvCapabilityGroupNonUniformRotateKHR: + return "GroupNonUniformRotateKHR"; + case SpvCapabilityFloatControls2: + return "FloatControls2"; + case SpvCapabilityAtomicFloat32AddEXT: + return "AtomicFloat32AddEXT"; + case SpvCapabilityAtomicFloat64AddEXT: + return "AtomicFloat64AddEXT"; + case SpvCapabilityLongCompositesINTEL: + return "LongCompositesINTEL"; + case SpvCapabilityOptNoneEXT: + return "OptNoneEXT"; + case SpvCapabilityAtomicFloat16AddEXT: + return "AtomicFloat16AddEXT"; + case SpvCapabilityDebugInfoModuleINTEL: + return "DebugInfoModuleINTEL"; + case SpvCapabilityBFloat16ConversionINTEL: + return "BFloat16ConversionINTEL"; + case SpvCapabilitySplitBarrierINTEL: + return "SplitBarrierINTEL"; + case SpvCapabilityArithmeticFenceEXT: + return "ArithmeticFenceEXT"; + case SpvCapabilityFPGAClusterAttributesV2INTEL: + return "FPGAClusterAttributesV2INTEL"; + case SpvCapabilityFPGAKernelAttributesv2INTEL: + return "FPGAKernelAttributesv2INTEL"; + case SpvCapabilityTaskSequenceINTEL: + return "TaskSequenceINTEL"; + case SpvCapabilityFPMaxErrorINTEL: + return "FPMaxErrorINTEL"; + case SpvCapabilityFPGALatencyControlINTEL: + return "FPGALatencyControlINTEL"; + case SpvCapabilityFPGAArgumentInterfacesINTEL: + return "FPGAArgumentInterfacesINTEL"; + case SpvCapabilityGlobalVariableHostAccessINTEL: + return "GlobalVariableHostAccessINTEL"; + case SpvCapabilityGlobalVariableFPGADecorationsINTEL: + return "GlobalVariableFPGADecorationsINTEL"; + case SpvCapabilitySubgroupBufferPrefetchINTEL: + return "SubgroupBufferPrefetchINTEL"; + case SpvCapabilitySubgroup2DBlockIOINTEL: + return "Subgroup2DBlockIOINTEL"; + case SpvCapabilitySubgroup2DBlockTransformINTEL: + return "Subgroup2DBlockTransformINTEL"; + case SpvCapabilitySubgroup2DBlockTransposeINTEL: + return "Subgroup2DBlockTransposeINTEL"; + case SpvCapabilitySubgroupMatrixMultiplyAccumulateINTEL: + return "SubgroupMatrixMultiplyAccumulateINTEL"; + case SpvCapabilityTernaryBitwiseFunctionINTEL: + return "TernaryBitwiseFunctionINTEL"; + case SpvCapabilityUntypedVariableLengthArrayINTEL: + return "UntypedVariableLengthArrayINTEL"; + case SpvCapabilitySpecConditionalINTEL: + return "SpecConditionalINTEL"; + case SpvCapabilityFunctionVariantsINTEL: + return "FunctionVariantsINTEL"; + case SpvCapabilityGroupUniformArithmeticKHR: + return "GroupUniformArithmeticKHR"; + case SpvCapabilityTensorFloat32RoundingINTEL: + return "TensorFloat32RoundingINTEL"; + case SpvCapabilityMaskedGatherScatterINTEL: + return "MaskedGatherScatterINTEL"; + case SpvCapabilityCacheControlsINTEL: + return "CacheControlsINTEL"; + case SpvCapabilityRegisterLimitsINTEL: + return "RegisterLimitsINTEL"; + case SpvCapabilityBindlessImagesINTEL: + return "BindlessImagesINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvRayQueryIntersectionToString(SpvRayQueryIntersection value) { + switch (value) { + case SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR: + return "RayQueryCandidateIntersectionKHR"; + case SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR: + return "RayQueryCommittedIntersectionKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvRayQueryCommittedIntersectionTypeToString(SpvRayQueryCommittedIntersectionType value) { + switch (value) { + case SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR: + return "RayQueryCommittedIntersectionNoneKHR"; + case SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR: + return "RayQueryCommittedIntersectionTriangleKHR"; + case SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR: + return "RayQueryCommittedIntersectionGeneratedKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvRayQueryCandidateIntersectionTypeToString(SpvRayQueryCandidateIntersectionType value) { + switch (value) { + case SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR: + return "RayQueryCandidateIntersectionTriangleKHR"; + case SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR: + return "RayQueryCandidateIntersectionAABBKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvFPDenormModeToString(SpvFPDenormMode value) { + switch (value) { + case SpvFPDenormModePreserve: + return "Preserve"; + case SpvFPDenormModeFlushToZero: + return "FlushToZero"; + default: + return "Unknown"; + } +} + +inline const char* SpvFPOperationModeToString(SpvFPOperationMode value) { + switch (value) { + case SpvFPOperationModeIEEE: + return "IEEE"; + case SpvFPOperationModeALT: + return "ALT"; + default: + return "Unknown"; + } +} + +inline const char* SpvQuantizationModesToString(SpvQuantizationModes value) { + switch (value) { + case SpvQuantizationModesTRN: + return "TRN"; + case SpvQuantizationModesTRN_ZERO: + return "TRN_ZERO"; + case SpvQuantizationModesRND: + return "RND"; + case SpvQuantizationModesRND_ZERO: + return "RND_ZERO"; + case SpvQuantizationModesRND_INF: + return "RND_INF"; + case SpvQuantizationModesRND_MIN_INF: + return "RND_MIN_INF"; + case SpvQuantizationModesRND_CONV: + return "RND_CONV"; + case SpvQuantizationModesRND_CONV_ODD: + return "RND_CONV_ODD"; + default: + return "Unknown"; + } +} + +inline const char* SpvOverflowModesToString(SpvOverflowModes value) { + switch (value) { + case SpvOverflowModesWRAP: + return "WRAP"; + case SpvOverflowModesSAT: + return "SAT"; + case SpvOverflowModesSAT_ZERO: + return "SAT_ZERO"; + case SpvOverflowModesSAT_SYM: + return "SAT_SYM"; + default: + return "Unknown"; + } +} + +inline const char* SpvPackedVectorFormatToString(SpvPackedVectorFormat value) { + switch (value) { + case SpvPackedVectorFormatPackedVectorFormat4x8Bit: + return "PackedVectorFormat4x8Bit"; + default: + return "Unknown"; + } +} + +inline const char* SpvCooperativeMatrixLayoutToString(SpvCooperativeMatrixLayout value) { + switch (value) { + case SpvCooperativeMatrixLayoutRowMajorKHR: + return "RowMajorKHR"; + case SpvCooperativeMatrixLayoutColumnMajorKHR: + return "ColumnMajorKHR"; + case SpvCooperativeMatrixLayoutRowBlockedInterleavedARM: + return "RowBlockedInterleavedARM"; + case SpvCooperativeMatrixLayoutColumnBlockedInterleavedARM: + return "ColumnBlockedInterleavedARM"; + default: + return "Unknown"; + } +} + +inline const char* SpvCooperativeMatrixUseToString(SpvCooperativeMatrixUse value) { + switch (value) { + case SpvCooperativeMatrixUseMatrixAKHR: + return "MatrixAKHR"; + case SpvCooperativeMatrixUseMatrixBKHR: + return "MatrixBKHR"; + case SpvCooperativeMatrixUseMatrixAccumulatorKHR: + return "MatrixAccumulatorKHR"; + default: + return "Unknown"; + } +} + +inline const char* SpvTensorClampModeToString(SpvTensorClampMode value) { + switch (value) { + case SpvTensorClampModeUndefined: + return "Undefined"; + case SpvTensorClampModeConstant: + return "Constant"; + case SpvTensorClampModeClampToEdge: + return "ClampToEdge"; + case SpvTensorClampModeRepeat: + return "Repeat"; + case SpvTensorClampModeRepeatMirrored: + return "RepeatMirrored"; + default: + return "Unknown"; + } +} + +inline const char* SpvInitializationModeQualifierToString(SpvInitializationModeQualifier value) { + switch (value) { + case SpvInitializationModeQualifierInitOnDeviceReprogramINTEL: + return "InitOnDeviceReprogramINTEL"; + case SpvInitializationModeQualifierInitOnDeviceResetINTEL: + return "InitOnDeviceResetINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvHostAccessQualifierToString(SpvHostAccessQualifier value) { + switch (value) { + case SpvHostAccessQualifierNoneINTEL: + return "NoneINTEL"; + case SpvHostAccessQualifierReadINTEL: + return "ReadINTEL"; + case SpvHostAccessQualifierWriteINTEL: + return "WriteINTEL"; + case SpvHostAccessQualifierReadWriteINTEL: + return "ReadWriteINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvLoadCacheControlToString(SpvLoadCacheControl value) { + switch (value) { + case SpvLoadCacheControlUncachedINTEL: + return "UncachedINTEL"; + case SpvLoadCacheControlCachedINTEL: + return "CachedINTEL"; + case SpvLoadCacheControlStreamingINTEL: + return "StreamingINTEL"; + case SpvLoadCacheControlInvalidateAfterReadINTEL: + return "InvalidateAfterReadINTEL"; + case SpvLoadCacheControlConstCachedINTEL: + return "ConstCachedINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvStoreCacheControlToString(SpvStoreCacheControl value) { + switch (value) { + case SpvStoreCacheControlUncachedINTEL: + return "UncachedINTEL"; + case SpvStoreCacheControlWriteThroughINTEL: + return "WriteThroughINTEL"; + case SpvStoreCacheControlWriteBackINTEL: + return "WriteBackINTEL"; + case SpvStoreCacheControlStreamingINTEL: + return "StreamingINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvNamedMaximumNumberOfRegistersToString(SpvNamedMaximumNumberOfRegisters value) { + switch (value) { + case SpvNamedMaximumNumberOfRegistersAutoINTEL: + return "AutoINTEL"; + default: + return "Unknown"; + } +} + +inline const char* SpvFPEncodingToString(SpvFPEncoding value) { + switch (value) { + case SpvFPEncodingBFloat16KHR: + return "BFloat16KHR"; + case SpvFPEncodingFloat8E4M3EXT: + return "Float8E4M3EXT"; + case SpvFPEncodingFloat8E5M2EXT: + return "Float8E5M2EXT"; + default: + return "Unknown"; + } +} + +inline const char* SpvCooperativeVectorMatrixLayoutToString(SpvCooperativeVectorMatrixLayout value) { + switch (value) { + case SpvCooperativeVectorMatrixLayoutRowMajorNV: + return "RowMajorNV"; + case SpvCooperativeVectorMatrixLayoutColumnMajorNV: + return "ColumnMajorNV"; + case SpvCooperativeVectorMatrixLayoutInferencingOptimalNV: + return "InferencingOptimalNV"; + case SpvCooperativeVectorMatrixLayoutTrainingOptimalNV: + return "TrainingOptimalNV"; + default: + return "Unknown"; + } +} + +inline const char* SpvComponentTypeToString(SpvComponentType value) { + switch (value) { + case SpvComponentTypeFloat16NV: + return "Float16NV"; + case SpvComponentTypeFloat32NV: + return "Float32NV"; + case SpvComponentTypeFloat64NV: + return "Float64NV"; + case SpvComponentTypeSignedInt8NV: + return "SignedInt8NV"; + case SpvComponentTypeSignedInt16NV: + return "SignedInt16NV"; + case SpvComponentTypeSignedInt32NV: + return "SignedInt32NV"; + case SpvComponentTypeSignedInt64NV: + return "SignedInt64NV"; + case SpvComponentTypeUnsignedInt8NV: + return "UnsignedInt8NV"; + case SpvComponentTypeUnsignedInt16NV: + return "UnsignedInt16NV"; + case SpvComponentTypeUnsignedInt32NV: + return "UnsignedInt32NV"; + case SpvComponentTypeUnsignedInt64NV: + return "UnsignedInt64NV"; + case SpvComponentTypeSignedInt8PackedNV: + return "SignedInt8PackedNV"; + case SpvComponentTypeUnsignedInt8PackedNV: + return "UnsignedInt8PackedNV"; + case SpvComponentTypeFloatE4M3NV: + return "FloatE4M3NV"; + case SpvComponentTypeFloatE5M2NV: + return "FloatE5M2NV"; + default: + return "Unknown"; + } +} + +inline const char* SpvOpToString(SpvOp value) { + switch (value) { + case SpvOpNop: + return "OpNop"; + case SpvOpUndef: + return "OpUndef"; + case SpvOpSourceContinued: + return "OpSourceContinued"; + case SpvOpSource: + return "OpSource"; + case SpvOpSourceExtension: + return "OpSourceExtension"; + case SpvOpName: + return "OpName"; + case SpvOpMemberName: + return "OpMemberName"; + case SpvOpString: + return "OpString"; + case SpvOpLine: + return "OpLine"; + case SpvOpExtension: + return "OpExtension"; + case SpvOpExtInstImport: + return "OpExtInstImport"; + case SpvOpExtInst: + return "OpExtInst"; + case SpvOpMemoryModel: + return "OpMemoryModel"; + case SpvOpEntryPoint: + return "OpEntryPoint"; + case SpvOpExecutionMode: + return "OpExecutionMode"; + case SpvOpCapability: + return "OpCapability"; + case SpvOpTypeVoid: + return "OpTypeVoid"; + case SpvOpTypeBool: + return "OpTypeBool"; + case SpvOpTypeInt: + return "OpTypeInt"; + case SpvOpTypeFloat: + return "OpTypeFloat"; + case SpvOpTypeVector: + return "OpTypeVector"; + case SpvOpTypeMatrix: + return "OpTypeMatrix"; + case SpvOpTypeImage: + return "OpTypeImage"; + case SpvOpTypeSampler: + return "OpTypeSampler"; + case SpvOpTypeSampledImage: + return "OpTypeSampledImage"; + case SpvOpTypeArray: + return "OpTypeArray"; + case SpvOpTypeRuntimeArray: + return "OpTypeRuntimeArray"; + case SpvOpTypeStruct: + return "OpTypeStruct"; + case SpvOpTypeOpaque: + return "OpTypeOpaque"; + case SpvOpTypePointer: + return "OpTypePointer"; + case SpvOpTypeFunction: + return "OpTypeFunction"; + case SpvOpTypeEvent: + return "OpTypeEvent"; + case SpvOpTypeDeviceEvent: + return "OpTypeDeviceEvent"; + case SpvOpTypeReserveId: + return "OpTypeReserveId"; + case SpvOpTypeQueue: + return "OpTypeQueue"; + case SpvOpTypePipe: + return "OpTypePipe"; + case SpvOpTypeForwardPointer: + return "OpTypeForwardPointer"; + case SpvOpConstantTrue: + return "OpConstantTrue"; + case SpvOpConstantFalse: + return "OpConstantFalse"; + case SpvOpConstant: + return "OpConstant"; + case SpvOpConstantComposite: + return "OpConstantComposite"; + case SpvOpConstantSampler: + return "OpConstantSampler"; + case SpvOpConstantNull: + return "OpConstantNull"; + case SpvOpSpecConstantTrue: + return "OpSpecConstantTrue"; + case SpvOpSpecConstantFalse: + return "OpSpecConstantFalse"; + case SpvOpSpecConstant: + return "OpSpecConstant"; + case SpvOpSpecConstantComposite: + return "OpSpecConstantComposite"; + case SpvOpSpecConstantOp: + return "OpSpecConstantOp"; + case SpvOpFunction: + return "OpFunction"; + case SpvOpFunctionParameter: + return "OpFunctionParameter"; + case SpvOpFunctionEnd: + return "OpFunctionEnd"; + case SpvOpFunctionCall: + return "OpFunctionCall"; + case SpvOpVariable: + return "OpVariable"; + case SpvOpImageTexelPointer: + return "OpImageTexelPointer"; + case SpvOpLoad: + return "OpLoad"; + case SpvOpStore: + return "OpStore"; + case SpvOpCopyMemory: + return "OpCopyMemory"; + case SpvOpCopyMemorySized: + return "OpCopyMemorySized"; + case SpvOpAccessChain: + return "OpAccessChain"; + case SpvOpInBoundsAccessChain: + return "OpInBoundsAccessChain"; + case SpvOpPtrAccessChain: + return "OpPtrAccessChain"; + case SpvOpArrayLength: + return "OpArrayLength"; + case SpvOpGenericPtrMemSemantics: + return "OpGenericPtrMemSemantics"; + case SpvOpInBoundsPtrAccessChain: + return "OpInBoundsPtrAccessChain"; + case SpvOpDecorate: + return "OpDecorate"; + case SpvOpMemberDecorate: + return "OpMemberDecorate"; + case SpvOpDecorationGroup: + return "OpDecorationGroup"; + case SpvOpGroupDecorate: + return "OpGroupDecorate"; + case SpvOpGroupMemberDecorate: + return "OpGroupMemberDecorate"; + case SpvOpVectorExtractDynamic: + return "OpVectorExtractDynamic"; + case SpvOpVectorInsertDynamic: + return "OpVectorInsertDynamic"; + case SpvOpVectorShuffle: + return "OpVectorShuffle"; + case SpvOpCompositeConstruct: + return "OpCompositeConstruct"; + case SpvOpCompositeExtract: + return "OpCompositeExtract"; + case SpvOpCompositeInsert: + return "OpCompositeInsert"; + case SpvOpCopyObject: + return "OpCopyObject"; + case SpvOpTranspose: + return "OpTranspose"; + case SpvOpSampledImage: + return "OpSampledImage"; + case SpvOpImageSampleImplicitLod: + return "OpImageSampleImplicitLod"; + case SpvOpImageSampleExplicitLod: + return "OpImageSampleExplicitLod"; + case SpvOpImageSampleDrefImplicitLod: + return "OpImageSampleDrefImplicitLod"; + case SpvOpImageSampleDrefExplicitLod: + return "OpImageSampleDrefExplicitLod"; + case SpvOpImageSampleProjImplicitLod: + return "OpImageSampleProjImplicitLod"; + case SpvOpImageSampleProjExplicitLod: + return "OpImageSampleProjExplicitLod"; + case SpvOpImageSampleProjDrefImplicitLod: + return "OpImageSampleProjDrefImplicitLod"; + case SpvOpImageSampleProjDrefExplicitLod: + return "OpImageSampleProjDrefExplicitLod"; + case SpvOpImageFetch: + return "OpImageFetch"; + case SpvOpImageGather: + return "OpImageGather"; + case SpvOpImageDrefGather: + return "OpImageDrefGather"; + case SpvOpImageRead: + return "OpImageRead"; + case SpvOpImageWrite: + return "OpImageWrite"; + case SpvOpImage: + return "OpImage"; + case SpvOpImageQueryFormat: + return "OpImageQueryFormat"; + case SpvOpImageQueryOrder: + return "OpImageQueryOrder"; + case SpvOpImageQuerySizeLod: + return "OpImageQuerySizeLod"; + case SpvOpImageQuerySize: + return "OpImageQuerySize"; + case SpvOpImageQueryLod: + return "OpImageQueryLod"; + case SpvOpImageQueryLevels: + return "OpImageQueryLevels"; + case SpvOpImageQuerySamples: + return "OpImageQuerySamples"; + case SpvOpConvertFToU: + return "OpConvertFToU"; + case SpvOpConvertFToS: + return "OpConvertFToS"; + case SpvOpConvertSToF: + return "OpConvertSToF"; + case SpvOpConvertUToF: + return "OpConvertUToF"; + case SpvOpUConvert: + return "OpUConvert"; + case SpvOpSConvert: + return "OpSConvert"; + case SpvOpFConvert: + return "OpFConvert"; + case SpvOpQuantizeToF16: + return "OpQuantizeToF16"; + case SpvOpConvertPtrToU: + return "OpConvertPtrToU"; + case SpvOpSatConvertSToU: + return "OpSatConvertSToU"; + case SpvOpSatConvertUToS: + return "OpSatConvertUToS"; + case SpvOpConvertUToPtr: + return "OpConvertUToPtr"; + case SpvOpPtrCastToGeneric: + return "OpPtrCastToGeneric"; + case SpvOpGenericCastToPtr: + return "OpGenericCastToPtr"; + case SpvOpGenericCastToPtrExplicit: + return "OpGenericCastToPtrExplicit"; + case SpvOpBitcast: + return "OpBitcast"; + case SpvOpSNegate: + return "OpSNegate"; + case SpvOpFNegate: + return "OpFNegate"; + case SpvOpIAdd: + return "OpIAdd"; + case SpvOpFAdd: + return "OpFAdd"; + case SpvOpISub: + return "OpISub"; + case SpvOpFSub: + return "OpFSub"; + case SpvOpIMul: + return "OpIMul"; + case SpvOpFMul: + return "OpFMul"; + case SpvOpUDiv: + return "OpUDiv"; + case SpvOpSDiv: + return "OpSDiv"; + case SpvOpFDiv: + return "OpFDiv"; + case SpvOpUMod: + return "OpUMod"; + case SpvOpSRem: + return "OpSRem"; + case SpvOpSMod: + return "OpSMod"; + case SpvOpFRem: + return "OpFRem"; + case SpvOpFMod: + return "OpFMod"; + case SpvOpVectorTimesScalar: + return "OpVectorTimesScalar"; + case SpvOpMatrixTimesScalar: + return "OpMatrixTimesScalar"; + case SpvOpVectorTimesMatrix: + return "OpVectorTimesMatrix"; + case SpvOpMatrixTimesVector: + return "OpMatrixTimesVector"; + case SpvOpMatrixTimesMatrix: + return "OpMatrixTimesMatrix"; + case SpvOpOuterProduct: + return "OpOuterProduct"; + case SpvOpDot: + return "OpDot"; + case SpvOpIAddCarry: + return "OpIAddCarry"; + case SpvOpISubBorrow: + return "OpISubBorrow"; + case SpvOpUMulExtended: + return "OpUMulExtended"; + case SpvOpSMulExtended: + return "OpSMulExtended"; + case SpvOpAny: + return "OpAny"; + case SpvOpAll: + return "OpAll"; + case SpvOpIsNan: + return "OpIsNan"; + case SpvOpIsInf: + return "OpIsInf"; + case SpvOpIsFinite: + return "OpIsFinite"; + case SpvOpIsNormal: + return "OpIsNormal"; + case SpvOpSignBitSet: + return "OpSignBitSet"; + case SpvOpLessOrGreater: + return "OpLessOrGreater"; + case SpvOpOrdered: + return "OpOrdered"; + case SpvOpUnordered: + return "OpUnordered"; + case SpvOpLogicalEqual: + return "OpLogicalEqual"; + case SpvOpLogicalNotEqual: + return "OpLogicalNotEqual"; + case SpvOpLogicalOr: + return "OpLogicalOr"; + case SpvOpLogicalAnd: + return "OpLogicalAnd"; + case SpvOpLogicalNot: + return "OpLogicalNot"; + case SpvOpSelect: + return "OpSelect"; + case SpvOpIEqual: + return "OpIEqual"; + case SpvOpINotEqual: + return "OpINotEqual"; + case SpvOpUGreaterThan: + return "OpUGreaterThan"; + case SpvOpSGreaterThan: + return "OpSGreaterThan"; + case SpvOpUGreaterThanEqual: + return "OpUGreaterThanEqual"; + case SpvOpSGreaterThanEqual: + return "OpSGreaterThanEqual"; + case SpvOpULessThan: + return "OpULessThan"; + case SpvOpSLessThan: + return "OpSLessThan"; + case SpvOpULessThanEqual: + return "OpULessThanEqual"; + case SpvOpSLessThanEqual: + return "OpSLessThanEqual"; + case SpvOpFOrdEqual: + return "OpFOrdEqual"; + case SpvOpFUnordEqual: + return "OpFUnordEqual"; + case SpvOpFOrdNotEqual: + return "OpFOrdNotEqual"; + case SpvOpFUnordNotEqual: + return "OpFUnordNotEqual"; + case SpvOpFOrdLessThan: + return "OpFOrdLessThan"; + case SpvOpFUnordLessThan: + return "OpFUnordLessThan"; + case SpvOpFOrdGreaterThan: + return "OpFOrdGreaterThan"; + case SpvOpFUnordGreaterThan: + return "OpFUnordGreaterThan"; + case SpvOpFOrdLessThanEqual: + return "OpFOrdLessThanEqual"; + case SpvOpFUnordLessThanEqual: + return "OpFUnordLessThanEqual"; + case SpvOpFOrdGreaterThanEqual: + return "OpFOrdGreaterThanEqual"; + case SpvOpFUnordGreaterThanEqual: + return "OpFUnordGreaterThanEqual"; + case SpvOpShiftRightLogical: + return "OpShiftRightLogical"; + case SpvOpShiftRightArithmetic: + return "OpShiftRightArithmetic"; + case SpvOpShiftLeftLogical: + return "OpShiftLeftLogical"; + case SpvOpBitwiseOr: + return "OpBitwiseOr"; + case SpvOpBitwiseXor: + return "OpBitwiseXor"; + case SpvOpBitwiseAnd: + return "OpBitwiseAnd"; + case SpvOpNot: + return "OpNot"; + case SpvOpBitFieldInsert: + return "OpBitFieldInsert"; + case SpvOpBitFieldSExtract: + return "OpBitFieldSExtract"; + case SpvOpBitFieldUExtract: + return "OpBitFieldUExtract"; + case SpvOpBitReverse: + return "OpBitReverse"; + case SpvOpBitCount: + return "OpBitCount"; + case SpvOpDPdx: + return "OpDPdx"; + case SpvOpDPdy: + return "OpDPdy"; + case SpvOpFwidth: + return "OpFwidth"; + case SpvOpDPdxFine: + return "OpDPdxFine"; + case SpvOpDPdyFine: + return "OpDPdyFine"; + case SpvOpFwidthFine: + return "OpFwidthFine"; + case SpvOpDPdxCoarse: + return "OpDPdxCoarse"; + case SpvOpDPdyCoarse: + return "OpDPdyCoarse"; + case SpvOpFwidthCoarse: + return "OpFwidthCoarse"; + case SpvOpEmitVertex: + return "OpEmitVertex"; + case SpvOpEndPrimitive: + return "OpEndPrimitive"; + case SpvOpEmitStreamVertex: + return "OpEmitStreamVertex"; + case SpvOpEndStreamPrimitive: + return "OpEndStreamPrimitive"; + case SpvOpControlBarrier: + return "OpControlBarrier"; + case SpvOpMemoryBarrier: + return "OpMemoryBarrier"; + case SpvOpAtomicLoad: + return "OpAtomicLoad"; + case SpvOpAtomicStore: + return "OpAtomicStore"; + case SpvOpAtomicExchange: + return "OpAtomicExchange"; + case SpvOpAtomicCompareExchange: + return "OpAtomicCompareExchange"; + case SpvOpAtomicCompareExchangeWeak: + return "OpAtomicCompareExchangeWeak"; + case SpvOpAtomicIIncrement: + return "OpAtomicIIncrement"; + case SpvOpAtomicIDecrement: + return "OpAtomicIDecrement"; + case SpvOpAtomicIAdd: + return "OpAtomicIAdd"; + case SpvOpAtomicISub: + return "OpAtomicISub"; + case SpvOpAtomicSMin: + return "OpAtomicSMin"; + case SpvOpAtomicUMin: + return "OpAtomicUMin"; + case SpvOpAtomicSMax: + return "OpAtomicSMax"; + case SpvOpAtomicUMax: + return "OpAtomicUMax"; + case SpvOpAtomicAnd: + return "OpAtomicAnd"; + case SpvOpAtomicOr: + return "OpAtomicOr"; + case SpvOpAtomicXor: + return "OpAtomicXor"; + case SpvOpPhi: + return "OpPhi"; + case SpvOpLoopMerge: + return "OpLoopMerge"; + case SpvOpSelectionMerge: + return "OpSelectionMerge"; + case SpvOpLabel: + return "OpLabel"; + case SpvOpBranch: + return "OpBranch"; + case SpvOpBranchConditional: + return "OpBranchConditional"; + case SpvOpSwitch: + return "OpSwitch"; + case SpvOpKill: + return "OpKill"; + case SpvOpReturn: + return "OpReturn"; + case SpvOpReturnValue: + return "OpReturnValue"; + case SpvOpUnreachable: + return "OpUnreachable"; + case SpvOpLifetimeStart: + return "OpLifetimeStart"; + case SpvOpLifetimeStop: + return "OpLifetimeStop"; + case SpvOpGroupAsyncCopy: + return "OpGroupAsyncCopy"; + case SpvOpGroupWaitEvents: + return "OpGroupWaitEvents"; + case SpvOpGroupAll: + return "OpGroupAll"; + case SpvOpGroupAny: + return "OpGroupAny"; + case SpvOpGroupBroadcast: + return "OpGroupBroadcast"; + case SpvOpGroupIAdd: + return "OpGroupIAdd"; + case SpvOpGroupFAdd: + return "OpGroupFAdd"; + case SpvOpGroupFMin: + return "OpGroupFMin"; + case SpvOpGroupUMin: + return "OpGroupUMin"; + case SpvOpGroupSMin: + return "OpGroupSMin"; + case SpvOpGroupFMax: + return "OpGroupFMax"; + case SpvOpGroupUMax: + return "OpGroupUMax"; + case SpvOpGroupSMax: + return "OpGroupSMax"; + case SpvOpReadPipe: + return "OpReadPipe"; + case SpvOpWritePipe: + return "OpWritePipe"; + case SpvOpReservedReadPipe: + return "OpReservedReadPipe"; + case SpvOpReservedWritePipe: + return "OpReservedWritePipe"; + case SpvOpReserveReadPipePackets: + return "OpReserveReadPipePackets"; + case SpvOpReserveWritePipePackets: + return "OpReserveWritePipePackets"; + case SpvOpCommitReadPipe: + return "OpCommitReadPipe"; + case SpvOpCommitWritePipe: + return "OpCommitWritePipe"; + case SpvOpIsValidReserveId: + return "OpIsValidReserveId"; + case SpvOpGetNumPipePackets: + return "OpGetNumPipePackets"; + case SpvOpGetMaxPipePackets: + return "OpGetMaxPipePackets"; + case SpvOpGroupReserveReadPipePackets: + return "OpGroupReserveReadPipePackets"; + case SpvOpGroupReserveWritePipePackets: + return "OpGroupReserveWritePipePackets"; + case SpvOpGroupCommitReadPipe: + return "OpGroupCommitReadPipe"; + case SpvOpGroupCommitWritePipe: + return "OpGroupCommitWritePipe"; + case SpvOpEnqueueMarker: + return "OpEnqueueMarker"; + case SpvOpEnqueueKernel: + return "OpEnqueueKernel"; + case SpvOpGetKernelNDrangeSubGroupCount: + return "OpGetKernelNDrangeSubGroupCount"; + case SpvOpGetKernelNDrangeMaxSubGroupSize: + return "OpGetKernelNDrangeMaxSubGroupSize"; + case SpvOpGetKernelWorkGroupSize: + return "OpGetKernelWorkGroupSize"; + case SpvOpGetKernelPreferredWorkGroupSizeMultiple: + return "OpGetKernelPreferredWorkGroupSizeMultiple"; + case SpvOpRetainEvent: + return "OpRetainEvent"; + case SpvOpReleaseEvent: + return "OpReleaseEvent"; + case SpvOpCreateUserEvent: + return "OpCreateUserEvent"; + case SpvOpIsValidEvent: + return "OpIsValidEvent"; + case SpvOpSetUserEventStatus: + return "OpSetUserEventStatus"; + case SpvOpCaptureEventProfilingInfo: + return "OpCaptureEventProfilingInfo"; + case SpvOpGetDefaultQueue: + return "OpGetDefaultQueue"; + case SpvOpBuildNDRange: + return "OpBuildNDRange"; + case SpvOpImageSparseSampleImplicitLod: + return "OpImageSparseSampleImplicitLod"; + case SpvOpImageSparseSampleExplicitLod: + return "OpImageSparseSampleExplicitLod"; + case SpvOpImageSparseSampleDrefImplicitLod: + return "OpImageSparseSampleDrefImplicitLod"; + case SpvOpImageSparseSampleDrefExplicitLod: + return "OpImageSparseSampleDrefExplicitLod"; + case SpvOpImageSparseSampleProjImplicitLod: + return "OpImageSparseSampleProjImplicitLod"; + case SpvOpImageSparseSampleProjExplicitLod: + return "OpImageSparseSampleProjExplicitLod"; + case SpvOpImageSparseSampleProjDrefImplicitLod: + return "OpImageSparseSampleProjDrefImplicitLod"; + case SpvOpImageSparseSampleProjDrefExplicitLod: + return "OpImageSparseSampleProjDrefExplicitLod"; + case SpvOpImageSparseFetch: + return "OpImageSparseFetch"; + case SpvOpImageSparseGather: + return "OpImageSparseGather"; + case SpvOpImageSparseDrefGather: + return "OpImageSparseDrefGather"; + case SpvOpImageSparseTexelsResident: + return "OpImageSparseTexelsResident"; + case SpvOpNoLine: + return "OpNoLine"; + case SpvOpAtomicFlagTestAndSet: + return "OpAtomicFlagTestAndSet"; + case SpvOpAtomicFlagClear: + return "OpAtomicFlagClear"; + case SpvOpImageSparseRead: + return "OpImageSparseRead"; + case SpvOpSizeOf: + return "OpSizeOf"; + case SpvOpTypePipeStorage: + return "OpTypePipeStorage"; + case SpvOpConstantPipeStorage: + return "OpConstantPipeStorage"; + case SpvOpCreatePipeFromPipeStorage: + return "OpCreatePipeFromPipeStorage"; + case SpvOpGetKernelLocalSizeForSubgroupCount: + return "OpGetKernelLocalSizeForSubgroupCount"; + case SpvOpGetKernelMaxNumSubgroups: + return "OpGetKernelMaxNumSubgroups"; + case SpvOpTypeNamedBarrier: + return "OpTypeNamedBarrier"; + case SpvOpNamedBarrierInitialize: + return "OpNamedBarrierInitialize"; + case SpvOpMemoryNamedBarrier: + return "OpMemoryNamedBarrier"; + case SpvOpModuleProcessed: + return "OpModuleProcessed"; + case SpvOpExecutionModeId: + return "OpExecutionModeId"; + case SpvOpDecorateId: + return "OpDecorateId"; + case SpvOpGroupNonUniformElect: + return "OpGroupNonUniformElect"; + case SpvOpGroupNonUniformAll: + return "OpGroupNonUniformAll"; + case SpvOpGroupNonUniformAny: + return "OpGroupNonUniformAny"; + case SpvOpGroupNonUniformAllEqual: + return "OpGroupNonUniformAllEqual"; + case SpvOpGroupNonUniformBroadcast: + return "OpGroupNonUniformBroadcast"; + case SpvOpGroupNonUniformBroadcastFirst: + return "OpGroupNonUniformBroadcastFirst"; + case SpvOpGroupNonUniformBallot: + return "OpGroupNonUniformBallot"; + case SpvOpGroupNonUniformInverseBallot: + return "OpGroupNonUniformInverseBallot"; + case SpvOpGroupNonUniformBallotBitExtract: + return "OpGroupNonUniformBallotBitExtract"; + case SpvOpGroupNonUniformBallotBitCount: + return "OpGroupNonUniformBallotBitCount"; + case SpvOpGroupNonUniformBallotFindLSB: + return "OpGroupNonUniformBallotFindLSB"; + case SpvOpGroupNonUniformBallotFindMSB: + return "OpGroupNonUniformBallotFindMSB"; + case SpvOpGroupNonUniformShuffle: + return "OpGroupNonUniformShuffle"; + case SpvOpGroupNonUniformShuffleXor: + return "OpGroupNonUniformShuffleXor"; + case SpvOpGroupNonUniformShuffleUp: + return "OpGroupNonUniformShuffleUp"; + case SpvOpGroupNonUniformShuffleDown: + return "OpGroupNonUniformShuffleDown"; + case SpvOpGroupNonUniformIAdd: + return "OpGroupNonUniformIAdd"; + case SpvOpGroupNonUniformFAdd: + return "OpGroupNonUniformFAdd"; + case SpvOpGroupNonUniformIMul: + return "OpGroupNonUniformIMul"; + case SpvOpGroupNonUniformFMul: + return "OpGroupNonUniformFMul"; + case SpvOpGroupNonUniformSMin: + return "OpGroupNonUniformSMin"; + case SpvOpGroupNonUniformUMin: + return "OpGroupNonUniformUMin"; + case SpvOpGroupNonUniformFMin: + return "OpGroupNonUniformFMin"; + case SpvOpGroupNonUniformSMax: + return "OpGroupNonUniformSMax"; + case SpvOpGroupNonUniformUMax: + return "OpGroupNonUniformUMax"; + case SpvOpGroupNonUniformFMax: + return "OpGroupNonUniformFMax"; + case SpvOpGroupNonUniformBitwiseAnd: + return "OpGroupNonUniformBitwiseAnd"; + case SpvOpGroupNonUniformBitwiseOr: + return "OpGroupNonUniformBitwiseOr"; + case SpvOpGroupNonUniformBitwiseXor: + return "OpGroupNonUniformBitwiseXor"; + case SpvOpGroupNonUniformLogicalAnd: + return "OpGroupNonUniformLogicalAnd"; + case SpvOpGroupNonUniformLogicalOr: + return "OpGroupNonUniformLogicalOr"; + case SpvOpGroupNonUniformLogicalXor: + return "OpGroupNonUniformLogicalXor"; + case SpvOpGroupNonUniformQuadBroadcast: + return "OpGroupNonUniformQuadBroadcast"; + case SpvOpGroupNonUniformQuadSwap: + return "OpGroupNonUniformQuadSwap"; + case SpvOpCopyLogical: + return "OpCopyLogical"; + case SpvOpPtrEqual: + return "OpPtrEqual"; + case SpvOpPtrNotEqual: + return "OpPtrNotEqual"; + case SpvOpPtrDiff: + return "OpPtrDiff"; + case SpvOpColorAttachmentReadEXT: + return "OpColorAttachmentReadEXT"; + case SpvOpDepthAttachmentReadEXT: + return "OpDepthAttachmentReadEXT"; + case SpvOpStencilAttachmentReadEXT: + return "OpStencilAttachmentReadEXT"; + case SpvOpTypeTensorARM: + return "OpTypeTensorARM"; + case SpvOpTensorReadARM: + return "OpTensorReadARM"; + case SpvOpTensorWriteARM: + return "OpTensorWriteARM"; + case SpvOpTensorQuerySizeARM: + return "OpTensorQuerySizeARM"; + case SpvOpGraphConstantARM: + return "OpGraphConstantARM"; + case SpvOpGraphEntryPointARM: + return "OpGraphEntryPointARM"; + case SpvOpGraphARM: + return "OpGraphARM"; + case SpvOpGraphInputARM: + return "OpGraphInputARM"; + case SpvOpGraphSetOutputARM: + return "OpGraphSetOutputARM"; + case SpvOpGraphEndARM: + return "OpGraphEndARM"; + case SpvOpTypeGraphARM: + return "OpTypeGraphARM"; + case SpvOpTerminateInvocation: + return "OpTerminateInvocation"; + case SpvOpTypeUntypedPointerKHR: + return "OpTypeUntypedPointerKHR"; + case SpvOpUntypedVariableKHR: + return "OpUntypedVariableKHR"; + case SpvOpUntypedAccessChainKHR: + return "OpUntypedAccessChainKHR"; + case SpvOpUntypedInBoundsAccessChainKHR: + return "OpUntypedInBoundsAccessChainKHR"; + case SpvOpSubgroupBallotKHR: + return "OpSubgroupBallotKHR"; + case SpvOpSubgroupFirstInvocationKHR: + return "OpSubgroupFirstInvocationKHR"; + case SpvOpUntypedPtrAccessChainKHR: + return "OpUntypedPtrAccessChainKHR"; + case SpvOpUntypedInBoundsPtrAccessChainKHR: + return "OpUntypedInBoundsPtrAccessChainKHR"; + case SpvOpUntypedArrayLengthKHR: + return "OpUntypedArrayLengthKHR"; + case SpvOpUntypedPrefetchKHR: + return "OpUntypedPrefetchKHR"; + case SpvOpSubgroupAllKHR: + return "OpSubgroupAllKHR"; + case SpvOpSubgroupAnyKHR: + return "OpSubgroupAnyKHR"; + case SpvOpSubgroupAllEqualKHR: + return "OpSubgroupAllEqualKHR"; + case SpvOpGroupNonUniformRotateKHR: + return "OpGroupNonUniformRotateKHR"; + case SpvOpSubgroupReadInvocationKHR: + return "OpSubgroupReadInvocationKHR"; + case SpvOpExtInstWithForwardRefsKHR: + return "OpExtInstWithForwardRefsKHR"; + case SpvOpUntypedGroupAsyncCopyKHR: + return "OpUntypedGroupAsyncCopyKHR"; + case SpvOpTraceRayKHR: + return "OpTraceRayKHR"; + case SpvOpExecuteCallableKHR: + return "OpExecuteCallableKHR"; + case SpvOpConvertUToAccelerationStructureKHR: + return "OpConvertUToAccelerationStructureKHR"; + case SpvOpIgnoreIntersectionKHR: + return "OpIgnoreIntersectionKHR"; + case SpvOpTerminateRayKHR: + return "OpTerminateRayKHR"; + case SpvOpSDot: + return "OpSDot"; + case SpvOpUDot: + return "OpUDot"; + case SpvOpSUDot: + return "OpSUDot"; + case SpvOpSDotAccSat: + return "OpSDotAccSat"; + case SpvOpUDotAccSat: + return "OpUDotAccSat"; + case SpvOpSUDotAccSat: + return "OpSUDotAccSat"; + case SpvOpTypeCooperativeMatrixKHR: + return "OpTypeCooperativeMatrixKHR"; + case SpvOpCooperativeMatrixLoadKHR: + return "OpCooperativeMatrixLoadKHR"; + case SpvOpCooperativeMatrixStoreKHR: + return "OpCooperativeMatrixStoreKHR"; + case SpvOpCooperativeMatrixMulAddKHR: + return "OpCooperativeMatrixMulAddKHR"; + case SpvOpCooperativeMatrixLengthKHR: + return "OpCooperativeMatrixLengthKHR"; + case SpvOpConstantCompositeReplicateEXT: + return "OpConstantCompositeReplicateEXT"; + case SpvOpSpecConstantCompositeReplicateEXT: + return "OpSpecConstantCompositeReplicateEXT"; + case SpvOpCompositeConstructReplicateEXT: + return "OpCompositeConstructReplicateEXT"; + case SpvOpTypeRayQueryKHR: + return "OpTypeRayQueryKHR"; + case SpvOpRayQueryInitializeKHR: + return "OpRayQueryInitializeKHR"; + case SpvOpRayQueryTerminateKHR: + return "OpRayQueryTerminateKHR"; + case SpvOpRayQueryGenerateIntersectionKHR: + return "OpRayQueryGenerateIntersectionKHR"; + case SpvOpRayQueryConfirmIntersectionKHR: + return "OpRayQueryConfirmIntersectionKHR"; + case SpvOpRayQueryProceedKHR: + return "OpRayQueryProceedKHR"; + case SpvOpRayQueryGetIntersectionTypeKHR: + return "OpRayQueryGetIntersectionTypeKHR"; + case SpvOpImageSampleWeightedQCOM: + return "OpImageSampleWeightedQCOM"; + case SpvOpImageBoxFilterQCOM: + return "OpImageBoxFilterQCOM"; + case SpvOpImageBlockMatchSSDQCOM: + return "OpImageBlockMatchSSDQCOM"; + case SpvOpImageBlockMatchSADQCOM: + return "OpImageBlockMatchSADQCOM"; + case SpvOpBitCastArrayQCOM: + return "OpBitCastArrayQCOM"; + case SpvOpImageBlockMatchWindowSSDQCOM: + return "OpImageBlockMatchWindowSSDQCOM"; + case SpvOpImageBlockMatchWindowSADQCOM: + return "OpImageBlockMatchWindowSADQCOM"; + case SpvOpImageBlockMatchGatherSSDQCOM: + return "OpImageBlockMatchGatherSSDQCOM"; + case SpvOpImageBlockMatchGatherSADQCOM: + return "OpImageBlockMatchGatherSADQCOM"; + case SpvOpCompositeConstructCoopMatQCOM: + return "OpCompositeConstructCoopMatQCOM"; + case SpvOpCompositeExtractCoopMatQCOM: + return "OpCompositeExtractCoopMatQCOM"; + case SpvOpExtractSubArrayQCOM: + return "OpExtractSubArrayQCOM"; + case SpvOpGroupIAddNonUniformAMD: + return "OpGroupIAddNonUniformAMD"; + case SpvOpGroupFAddNonUniformAMD: + return "OpGroupFAddNonUniformAMD"; + case SpvOpGroupFMinNonUniformAMD: + return "OpGroupFMinNonUniformAMD"; + case SpvOpGroupUMinNonUniformAMD: + return "OpGroupUMinNonUniformAMD"; + case SpvOpGroupSMinNonUniformAMD: + return "OpGroupSMinNonUniformAMD"; + case SpvOpGroupFMaxNonUniformAMD: + return "OpGroupFMaxNonUniformAMD"; + case SpvOpGroupUMaxNonUniformAMD: + return "OpGroupUMaxNonUniformAMD"; + case SpvOpGroupSMaxNonUniformAMD: + return "OpGroupSMaxNonUniformAMD"; + case SpvOpFragmentMaskFetchAMD: + return "OpFragmentMaskFetchAMD"; + case SpvOpFragmentFetchAMD: + return "OpFragmentFetchAMD"; + case SpvOpReadClockKHR: + return "OpReadClockKHR"; + case SpvOpAllocateNodePayloadsAMDX: + return "OpAllocateNodePayloadsAMDX"; + case SpvOpEnqueueNodePayloadsAMDX: + return "OpEnqueueNodePayloadsAMDX"; + case SpvOpTypeNodePayloadArrayAMDX: + return "OpTypeNodePayloadArrayAMDX"; + case SpvOpFinishWritingNodePayloadAMDX: + return "OpFinishWritingNodePayloadAMDX"; + case SpvOpNodePayloadArrayLengthAMDX: + return "OpNodePayloadArrayLengthAMDX"; + case SpvOpIsNodePayloadValidAMDX: + return "OpIsNodePayloadValidAMDX"; + case SpvOpConstantStringAMDX: + return "OpConstantStringAMDX"; + case SpvOpSpecConstantStringAMDX: + return "OpSpecConstantStringAMDX"; + case SpvOpGroupNonUniformQuadAllKHR: + return "OpGroupNonUniformQuadAllKHR"; + case SpvOpGroupNonUniformQuadAnyKHR: + return "OpGroupNonUniformQuadAnyKHR"; + case SpvOpHitObjectRecordHitMotionNV: + return "OpHitObjectRecordHitMotionNV"; + case SpvOpHitObjectRecordHitWithIndexMotionNV: + return "OpHitObjectRecordHitWithIndexMotionNV"; + case SpvOpHitObjectRecordMissMotionNV: + return "OpHitObjectRecordMissMotionNV"; + case SpvOpHitObjectGetWorldToObjectNV: + return "OpHitObjectGetWorldToObjectNV"; + case SpvOpHitObjectGetObjectToWorldNV: + return "OpHitObjectGetObjectToWorldNV"; + case SpvOpHitObjectGetObjectRayDirectionNV: + return "OpHitObjectGetObjectRayDirectionNV"; + case SpvOpHitObjectGetObjectRayOriginNV: + return "OpHitObjectGetObjectRayOriginNV"; + case SpvOpHitObjectTraceRayMotionNV: + return "OpHitObjectTraceRayMotionNV"; + case SpvOpHitObjectGetShaderRecordBufferHandleNV: + return "OpHitObjectGetShaderRecordBufferHandleNV"; + case SpvOpHitObjectGetShaderBindingTableRecordIndexNV: + return "OpHitObjectGetShaderBindingTableRecordIndexNV"; + case SpvOpHitObjectRecordEmptyNV: + return "OpHitObjectRecordEmptyNV"; + case SpvOpHitObjectTraceRayNV: + return "OpHitObjectTraceRayNV"; + case SpvOpHitObjectRecordHitNV: + return "OpHitObjectRecordHitNV"; + case SpvOpHitObjectRecordHitWithIndexNV: + return "OpHitObjectRecordHitWithIndexNV"; + case SpvOpHitObjectRecordMissNV: + return "OpHitObjectRecordMissNV"; + case SpvOpHitObjectExecuteShaderNV: + return "OpHitObjectExecuteShaderNV"; + case SpvOpHitObjectGetCurrentTimeNV: + return "OpHitObjectGetCurrentTimeNV"; + case SpvOpHitObjectGetAttributesNV: + return "OpHitObjectGetAttributesNV"; + case SpvOpHitObjectGetHitKindNV: + return "OpHitObjectGetHitKindNV"; + case SpvOpHitObjectGetPrimitiveIndexNV: + return "OpHitObjectGetPrimitiveIndexNV"; + case SpvOpHitObjectGetGeometryIndexNV: + return "OpHitObjectGetGeometryIndexNV"; + case SpvOpHitObjectGetInstanceIdNV: + return "OpHitObjectGetInstanceIdNV"; + case SpvOpHitObjectGetInstanceCustomIndexNV: + return "OpHitObjectGetInstanceCustomIndexNV"; + case SpvOpHitObjectGetWorldRayDirectionNV: + return "OpHitObjectGetWorldRayDirectionNV"; + case SpvOpHitObjectGetWorldRayOriginNV: + return "OpHitObjectGetWorldRayOriginNV"; + case SpvOpHitObjectGetRayTMaxNV: + return "OpHitObjectGetRayTMaxNV"; + case SpvOpHitObjectGetRayTMinNV: + return "OpHitObjectGetRayTMinNV"; + case SpvOpHitObjectIsEmptyNV: + return "OpHitObjectIsEmptyNV"; + case SpvOpHitObjectIsHitNV: + return "OpHitObjectIsHitNV"; + case SpvOpHitObjectIsMissNV: + return "OpHitObjectIsMissNV"; + case SpvOpReorderThreadWithHitObjectNV: + return "OpReorderThreadWithHitObjectNV"; + case SpvOpReorderThreadWithHintNV: + return "OpReorderThreadWithHintNV"; + case SpvOpTypeHitObjectNV: + return "OpTypeHitObjectNV"; + case SpvOpImageSampleFootprintNV: + return "OpImageSampleFootprintNV"; + case SpvOpTypeCooperativeVectorNV: + return "OpTypeCooperativeVectorNV"; + case SpvOpCooperativeVectorMatrixMulNV: + return "OpCooperativeVectorMatrixMulNV"; + case SpvOpCooperativeVectorOuterProductAccumulateNV: + return "OpCooperativeVectorOuterProductAccumulateNV"; + case SpvOpCooperativeVectorReduceSumAccumulateNV: + return "OpCooperativeVectorReduceSumAccumulateNV"; + case SpvOpCooperativeVectorMatrixMulAddNV: + return "OpCooperativeVectorMatrixMulAddNV"; + case SpvOpCooperativeMatrixConvertNV: + return "OpCooperativeMatrixConvertNV"; + case SpvOpEmitMeshTasksEXT: + return "OpEmitMeshTasksEXT"; + case SpvOpSetMeshOutputsEXT: + return "OpSetMeshOutputsEXT"; + case SpvOpGroupNonUniformPartitionNV: + return "OpGroupNonUniformPartitionNV"; + case SpvOpWritePackedPrimitiveIndices4x8NV: + return "OpWritePackedPrimitiveIndices4x8NV"; + case SpvOpFetchMicroTriangleVertexPositionNV: + return "OpFetchMicroTriangleVertexPositionNV"; + case SpvOpFetchMicroTriangleVertexBarycentricNV: + return "OpFetchMicroTriangleVertexBarycentricNV"; + case SpvOpCooperativeVectorLoadNV: + return "OpCooperativeVectorLoadNV"; + case SpvOpCooperativeVectorStoreNV: + return "OpCooperativeVectorStoreNV"; + case SpvOpReportIntersectionKHR: + return "OpReportIntersectionKHR"; + case SpvOpIgnoreIntersectionNV: + return "OpIgnoreIntersectionNV"; + case SpvOpTerminateRayNV: + return "OpTerminateRayNV"; + case SpvOpTraceNV: + return "OpTraceNV"; + case SpvOpTraceMotionNV: + return "OpTraceMotionNV"; + case SpvOpTraceRayMotionNV: + return "OpTraceRayMotionNV"; + case SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR: + return "OpRayQueryGetIntersectionTriangleVertexPositionsKHR"; + case SpvOpTypeAccelerationStructureKHR: + return "OpTypeAccelerationStructureKHR"; + case SpvOpExecuteCallableNV: + return "OpExecuteCallableNV"; + case SpvOpRayQueryGetClusterIdNV: + return "OpRayQueryGetClusterIdNV"; + case SpvOpHitObjectGetClusterIdNV: + return "OpHitObjectGetClusterIdNV"; + case SpvOpTypeCooperativeMatrixNV: + return "OpTypeCooperativeMatrixNV"; + case SpvOpCooperativeMatrixLoadNV: + return "OpCooperativeMatrixLoadNV"; + case SpvOpCooperativeMatrixStoreNV: + return "OpCooperativeMatrixStoreNV"; + case SpvOpCooperativeMatrixMulAddNV: + return "OpCooperativeMatrixMulAddNV"; + case SpvOpCooperativeMatrixLengthNV: + return "OpCooperativeMatrixLengthNV"; + case SpvOpBeginInvocationInterlockEXT: + return "OpBeginInvocationInterlockEXT"; + case SpvOpEndInvocationInterlockEXT: + return "OpEndInvocationInterlockEXT"; + case SpvOpCooperativeMatrixReduceNV: + return "OpCooperativeMatrixReduceNV"; + case SpvOpCooperativeMatrixLoadTensorNV: + return "OpCooperativeMatrixLoadTensorNV"; + case SpvOpCooperativeMatrixStoreTensorNV: + return "OpCooperativeMatrixStoreTensorNV"; + case SpvOpCooperativeMatrixPerElementOpNV: + return "OpCooperativeMatrixPerElementOpNV"; + case SpvOpTypeTensorLayoutNV: + return "OpTypeTensorLayoutNV"; + case SpvOpTypeTensorViewNV: + return "OpTypeTensorViewNV"; + case SpvOpCreateTensorLayoutNV: + return "OpCreateTensorLayoutNV"; + case SpvOpTensorLayoutSetDimensionNV: + return "OpTensorLayoutSetDimensionNV"; + case SpvOpTensorLayoutSetStrideNV: + return "OpTensorLayoutSetStrideNV"; + case SpvOpTensorLayoutSliceNV: + return "OpTensorLayoutSliceNV"; + case SpvOpTensorLayoutSetClampValueNV: + return "OpTensorLayoutSetClampValueNV"; + case SpvOpCreateTensorViewNV: + return "OpCreateTensorViewNV"; + case SpvOpTensorViewSetDimensionNV: + return "OpTensorViewSetDimensionNV"; + case SpvOpTensorViewSetStrideNV: + return "OpTensorViewSetStrideNV"; + case SpvOpDemoteToHelperInvocation: + return "OpDemoteToHelperInvocation"; + case SpvOpIsHelperInvocationEXT: + return "OpIsHelperInvocationEXT"; + case SpvOpTensorViewSetClipNV: + return "OpTensorViewSetClipNV"; + case SpvOpTensorLayoutSetBlockSizeNV: + return "OpTensorLayoutSetBlockSizeNV"; + case SpvOpCooperativeMatrixTransposeNV: + return "OpCooperativeMatrixTransposeNV"; + case SpvOpConvertUToImageNV: + return "OpConvertUToImageNV"; + case SpvOpConvertUToSamplerNV: + return "OpConvertUToSamplerNV"; + case SpvOpConvertImageToUNV: + return "OpConvertImageToUNV"; + case SpvOpConvertSamplerToUNV: + return "OpConvertSamplerToUNV"; + case SpvOpConvertUToSampledImageNV: + return "OpConvertUToSampledImageNV"; + case SpvOpConvertSampledImageToUNV: + return "OpConvertSampledImageToUNV"; + case SpvOpSamplerImageAddressingModeNV: + return "OpSamplerImageAddressingModeNV"; + case SpvOpRawAccessChainNV: + return "OpRawAccessChainNV"; + case SpvOpRayQueryGetIntersectionSpherePositionNV: + return "OpRayQueryGetIntersectionSpherePositionNV"; + case SpvOpRayQueryGetIntersectionSphereRadiusNV: + return "OpRayQueryGetIntersectionSphereRadiusNV"; + case SpvOpRayQueryGetIntersectionLSSPositionsNV: + return "OpRayQueryGetIntersectionLSSPositionsNV"; + case SpvOpRayQueryGetIntersectionLSSRadiiNV: + return "OpRayQueryGetIntersectionLSSRadiiNV"; + case SpvOpRayQueryGetIntersectionLSSHitValueNV: + return "OpRayQueryGetIntersectionLSSHitValueNV"; + case SpvOpHitObjectGetSpherePositionNV: + return "OpHitObjectGetSpherePositionNV"; + case SpvOpHitObjectGetSphereRadiusNV: + return "OpHitObjectGetSphereRadiusNV"; + case SpvOpHitObjectGetLSSPositionsNV: + return "OpHitObjectGetLSSPositionsNV"; + case SpvOpHitObjectGetLSSRadiiNV: + return "OpHitObjectGetLSSRadiiNV"; + case SpvOpHitObjectIsSphereHitNV: + return "OpHitObjectIsSphereHitNV"; + case SpvOpHitObjectIsLSSHitNV: + return "OpHitObjectIsLSSHitNV"; + case SpvOpRayQueryIsSphereHitNV: + return "OpRayQueryIsSphereHitNV"; + case SpvOpRayQueryIsLSSHitNV: + return "OpRayQueryIsLSSHitNV"; + case SpvOpSubgroupShuffleINTEL: + return "OpSubgroupShuffleINTEL"; + case SpvOpSubgroupShuffleDownINTEL: + return "OpSubgroupShuffleDownINTEL"; + case SpvOpSubgroupShuffleUpINTEL: + return "OpSubgroupShuffleUpINTEL"; + case SpvOpSubgroupShuffleXorINTEL: + return "OpSubgroupShuffleXorINTEL"; + case SpvOpSubgroupBlockReadINTEL: + return "OpSubgroupBlockReadINTEL"; + case SpvOpSubgroupBlockWriteINTEL: + return "OpSubgroupBlockWriteINTEL"; + case SpvOpSubgroupImageBlockReadINTEL: + return "OpSubgroupImageBlockReadINTEL"; + case SpvOpSubgroupImageBlockWriteINTEL: + return "OpSubgroupImageBlockWriteINTEL"; + case SpvOpSubgroupImageMediaBlockReadINTEL: + return "OpSubgroupImageMediaBlockReadINTEL"; + case SpvOpSubgroupImageMediaBlockWriteINTEL: + return "OpSubgroupImageMediaBlockWriteINTEL"; + case SpvOpUCountLeadingZerosINTEL: + return "OpUCountLeadingZerosINTEL"; + case SpvOpUCountTrailingZerosINTEL: + return "OpUCountTrailingZerosINTEL"; + case SpvOpAbsISubINTEL: + return "OpAbsISubINTEL"; + case SpvOpAbsUSubINTEL: + return "OpAbsUSubINTEL"; + case SpvOpIAddSatINTEL: + return "OpIAddSatINTEL"; + case SpvOpUAddSatINTEL: + return "OpUAddSatINTEL"; + case SpvOpIAverageINTEL: + return "OpIAverageINTEL"; + case SpvOpUAverageINTEL: + return "OpUAverageINTEL"; + case SpvOpIAverageRoundedINTEL: + return "OpIAverageRoundedINTEL"; + case SpvOpUAverageRoundedINTEL: + return "OpUAverageRoundedINTEL"; + case SpvOpISubSatINTEL: + return "OpISubSatINTEL"; + case SpvOpUSubSatINTEL: + return "OpUSubSatINTEL"; + case SpvOpIMul32x16INTEL: + return "OpIMul32x16INTEL"; + case SpvOpUMul32x16INTEL: + return "OpUMul32x16INTEL"; + case SpvOpConstantFunctionPointerINTEL: + return "OpConstantFunctionPointerINTEL"; + case SpvOpFunctionPointerCallINTEL: + return "OpFunctionPointerCallINTEL"; + case SpvOpAsmTargetINTEL: + return "OpAsmTargetINTEL"; + case SpvOpAsmINTEL: + return "OpAsmINTEL"; + case SpvOpAsmCallINTEL: + return "OpAsmCallINTEL"; + case SpvOpAtomicFMinEXT: + return "OpAtomicFMinEXT"; + case SpvOpAtomicFMaxEXT: + return "OpAtomicFMaxEXT"; + case SpvOpAssumeTrueKHR: + return "OpAssumeTrueKHR"; + case SpvOpExpectKHR: + return "OpExpectKHR"; + case SpvOpDecorateString: + return "OpDecorateString"; + case SpvOpMemberDecorateString: + return "OpMemberDecorateString"; + case SpvOpVmeImageINTEL: + return "OpVmeImageINTEL"; + case SpvOpTypeVmeImageINTEL: + return "OpTypeVmeImageINTEL"; + case SpvOpTypeAvcImePayloadINTEL: + return "OpTypeAvcImePayloadINTEL"; + case SpvOpTypeAvcRefPayloadINTEL: + return "OpTypeAvcRefPayloadINTEL"; + case SpvOpTypeAvcSicPayloadINTEL: + return "OpTypeAvcSicPayloadINTEL"; + case SpvOpTypeAvcMcePayloadINTEL: + return "OpTypeAvcMcePayloadINTEL"; + case SpvOpTypeAvcMceResultINTEL: + return "OpTypeAvcMceResultINTEL"; + case SpvOpTypeAvcImeResultINTEL: + return "OpTypeAvcImeResultINTEL"; + case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: + return "OpTypeAvcImeResultSingleReferenceStreamoutINTEL"; + case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: + return "OpTypeAvcImeResultDualReferenceStreamoutINTEL"; + case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: + return "OpTypeAvcImeSingleReferenceStreaminINTEL"; + case SpvOpTypeAvcImeDualReferenceStreaminINTEL: + return "OpTypeAvcImeDualReferenceStreaminINTEL"; + case SpvOpTypeAvcRefResultINTEL: + return "OpTypeAvcRefResultINTEL"; + case SpvOpTypeAvcSicResultINTEL: + return "OpTypeAvcSicResultINTEL"; + case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL"; + case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: + return "OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL"; + case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: + return "OpSubgroupAvcMceSetInterShapePenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL"; + case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: + return "OpSubgroupAvcMceSetInterDirectionPenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: + return "OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL"; + case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: + return "OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL"; + case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: + return "OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL"; + case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: + return "OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL"; + case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: + return "OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL"; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL"; + case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: + return "OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL"; + case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: + return "OpSubgroupAvcMceSetAcOnlyHaarINTEL"; + case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: + return "OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL"; + case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: + return "OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL"; + case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: + return "OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL"; + case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: + return "OpSubgroupAvcMceConvertToImePayloadINTEL"; + case SpvOpSubgroupAvcMceConvertToImeResultINTEL: + return "OpSubgroupAvcMceConvertToImeResultINTEL"; + case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: + return "OpSubgroupAvcMceConvertToRefPayloadINTEL"; + case SpvOpSubgroupAvcMceConvertToRefResultINTEL: + return "OpSubgroupAvcMceConvertToRefResultINTEL"; + case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: + return "OpSubgroupAvcMceConvertToSicPayloadINTEL"; + case SpvOpSubgroupAvcMceConvertToSicResultINTEL: + return "OpSubgroupAvcMceConvertToSicResultINTEL"; + case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: + return "OpSubgroupAvcMceGetMotionVectorsINTEL"; + case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: + return "OpSubgroupAvcMceGetInterDistortionsINTEL"; + case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: + return "OpSubgroupAvcMceGetBestInterDistortionsINTEL"; + case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: + return "OpSubgroupAvcMceGetInterMajorShapeINTEL"; + case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: + return "OpSubgroupAvcMceGetInterMinorShapeINTEL"; + case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: + return "OpSubgroupAvcMceGetInterDirectionsINTEL"; + case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: + return "OpSubgroupAvcMceGetInterMotionVectorCountINTEL"; + case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: + return "OpSubgroupAvcMceGetInterReferenceIdsINTEL"; + case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: + return "OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL"; + case SpvOpSubgroupAvcImeInitializeINTEL: + return "OpSubgroupAvcImeInitializeINTEL"; + case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: + return "OpSubgroupAvcImeSetSingleReferenceINTEL"; + case SpvOpSubgroupAvcImeSetDualReferenceINTEL: + return "OpSubgroupAvcImeSetDualReferenceINTEL"; + case SpvOpSubgroupAvcImeRefWindowSizeINTEL: + return "OpSubgroupAvcImeRefWindowSizeINTEL"; + case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: + return "OpSubgroupAvcImeAdjustRefOffsetINTEL"; + case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: + return "OpSubgroupAvcImeConvertToMcePayloadINTEL"; + case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: + return "OpSubgroupAvcImeSetMaxMotionVectorCountINTEL"; + case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: + return "OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL"; + case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: + return "OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL"; + case SpvOpSubgroupAvcImeSetWeightedSadINTEL: + return "OpSubgroupAvcImeSetWeightedSadINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: + return "OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: + return "OpSubgroupAvcImeEvaluateWithDualReferenceINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: + return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: + return "OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: + return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: + return "OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: + return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL"; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: + return "OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL"; + case SpvOpSubgroupAvcImeConvertToMceResultINTEL: + return "OpSubgroupAvcImeConvertToMceResultINTEL"; + case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: + return "OpSubgroupAvcImeGetSingleReferenceStreaminINTEL"; + case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: + return "OpSubgroupAvcImeGetDualReferenceStreaminINTEL"; + case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: + return "OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL"; + case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: + return "OpSubgroupAvcImeStripDualReferenceStreamoutINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: + return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: + return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: + return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: + return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: + return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL"; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: + return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL"; + case SpvOpSubgroupAvcImeGetBorderReachedINTEL: + return "OpSubgroupAvcImeGetBorderReachedINTEL"; + case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: + return "OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL"; + case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: + return "OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL"; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: + return "OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL"; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: + return "OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL"; + case SpvOpSubgroupAvcFmeInitializeINTEL: + return "OpSubgroupAvcFmeInitializeINTEL"; + case SpvOpSubgroupAvcBmeInitializeINTEL: + return "OpSubgroupAvcBmeInitializeINTEL"; + case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: + return "OpSubgroupAvcRefConvertToMcePayloadINTEL"; + case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: + return "OpSubgroupAvcRefSetBidirectionalMixDisableINTEL"; + case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: + return "OpSubgroupAvcRefSetBilinearFilterEnableINTEL"; + case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: + return "OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL"; + case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: + return "OpSubgroupAvcRefEvaluateWithDualReferenceINTEL"; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: + return "OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL"; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: + return "OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL"; + case SpvOpSubgroupAvcRefConvertToMceResultINTEL: + return "OpSubgroupAvcRefConvertToMceResultINTEL"; + case SpvOpSubgroupAvcSicInitializeINTEL: + return "OpSubgroupAvcSicInitializeINTEL"; + case SpvOpSubgroupAvcSicConfigureSkcINTEL: + return "OpSubgroupAvcSicConfigureSkcINTEL"; + case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: + return "OpSubgroupAvcSicConfigureIpeLumaINTEL"; + case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: + return "OpSubgroupAvcSicConfigureIpeLumaChromaINTEL"; + case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: + return "OpSubgroupAvcSicGetMotionVectorMaskINTEL"; + case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: + return "OpSubgroupAvcSicConvertToMcePayloadINTEL"; + case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: + return "OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL"; + case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: + return "OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL"; + case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: + return "OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL"; + case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: + return "OpSubgroupAvcSicSetBilinearFilterEnableINTEL"; + case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: + return "OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL"; + case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: + return "OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL"; + case SpvOpSubgroupAvcSicEvaluateIpeINTEL: + return "OpSubgroupAvcSicEvaluateIpeINTEL"; + case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: + return "OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL"; + case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: + return "OpSubgroupAvcSicEvaluateWithDualReferenceINTEL"; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: + return "OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL"; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: + return "OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL"; + case SpvOpSubgroupAvcSicConvertToMceResultINTEL: + return "OpSubgroupAvcSicConvertToMceResultINTEL"; + case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: + return "OpSubgroupAvcSicGetIpeLumaShapeINTEL"; + case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: + return "OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL"; + case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: + return "OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL"; + case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: + return "OpSubgroupAvcSicGetPackedIpeLumaModesINTEL"; + case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: + return "OpSubgroupAvcSicGetIpeChromaModeINTEL"; + case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: + return "OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL"; + case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: + return "OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL"; + case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: + return "OpSubgroupAvcSicGetInterRawSadsINTEL"; + case SpvOpVariableLengthArrayINTEL: + return "OpVariableLengthArrayINTEL"; + case SpvOpSaveMemoryINTEL: + return "OpSaveMemoryINTEL"; + case SpvOpRestoreMemoryINTEL: + return "OpRestoreMemoryINTEL"; + case SpvOpArbitraryFloatSinCosPiINTEL: + return "OpArbitraryFloatSinCosPiINTEL"; + case SpvOpArbitraryFloatCastINTEL: + return "OpArbitraryFloatCastINTEL"; + case SpvOpArbitraryFloatCastFromIntINTEL: + return "OpArbitraryFloatCastFromIntINTEL"; + case SpvOpArbitraryFloatCastToIntINTEL: + return "OpArbitraryFloatCastToIntINTEL"; + case SpvOpArbitraryFloatAddINTEL: + return "OpArbitraryFloatAddINTEL"; + case SpvOpArbitraryFloatSubINTEL: + return "OpArbitraryFloatSubINTEL"; + case SpvOpArbitraryFloatMulINTEL: + return "OpArbitraryFloatMulINTEL"; + case SpvOpArbitraryFloatDivINTEL: + return "OpArbitraryFloatDivINTEL"; + case SpvOpArbitraryFloatGTINTEL: + return "OpArbitraryFloatGTINTEL"; + case SpvOpArbitraryFloatGEINTEL: + return "OpArbitraryFloatGEINTEL"; + case SpvOpArbitraryFloatLTINTEL: + return "OpArbitraryFloatLTINTEL"; + case SpvOpArbitraryFloatLEINTEL: + return "OpArbitraryFloatLEINTEL"; + case SpvOpArbitraryFloatEQINTEL: + return "OpArbitraryFloatEQINTEL"; + case SpvOpArbitraryFloatRecipINTEL: + return "OpArbitraryFloatRecipINTEL"; + case SpvOpArbitraryFloatRSqrtINTEL: + return "OpArbitraryFloatRSqrtINTEL"; + case SpvOpArbitraryFloatCbrtINTEL: + return "OpArbitraryFloatCbrtINTEL"; + case SpvOpArbitraryFloatHypotINTEL: + return "OpArbitraryFloatHypotINTEL"; + case SpvOpArbitraryFloatSqrtINTEL: + return "OpArbitraryFloatSqrtINTEL"; + case SpvOpArbitraryFloatLogINTEL: + return "OpArbitraryFloatLogINTEL"; + case SpvOpArbitraryFloatLog2INTEL: + return "OpArbitraryFloatLog2INTEL"; + case SpvOpArbitraryFloatLog10INTEL: + return "OpArbitraryFloatLog10INTEL"; + case SpvOpArbitraryFloatLog1pINTEL: + return "OpArbitraryFloatLog1pINTEL"; + case SpvOpArbitraryFloatExpINTEL: + return "OpArbitraryFloatExpINTEL"; + case SpvOpArbitraryFloatExp2INTEL: + return "OpArbitraryFloatExp2INTEL"; + case SpvOpArbitraryFloatExp10INTEL: + return "OpArbitraryFloatExp10INTEL"; + case SpvOpArbitraryFloatExpm1INTEL: + return "OpArbitraryFloatExpm1INTEL"; + case SpvOpArbitraryFloatSinINTEL: + return "OpArbitraryFloatSinINTEL"; + case SpvOpArbitraryFloatCosINTEL: + return "OpArbitraryFloatCosINTEL"; + case SpvOpArbitraryFloatSinCosINTEL: + return "OpArbitraryFloatSinCosINTEL"; + case SpvOpArbitraryFloatSinPiINTEL: + return "OpArbitraryFloatSinPiINTEL"; + case SpvOpArbitraryFloatCosPiINTEL: + return "OpArbitraryFloatCosPiINTEL"; + case SpvOpArbitraryFloatASinINTEL: + return "OpArbitraryFloatASinINTEL"; + case SpvOpArbitraryFloatASinPiINTEL: + return "OpArbitraryFloatASinPiINTEL"; + case SpvOpArbitraryFloatACosINTEL: + return "OpArbitraryFloatACosINTEL"; + case SpvOpArbitraryFloatACosPiINTEL: + return "OpArbitraryFloatACosPiINTEL"; + case SpvOpArbitraryFloatATanINTEL: + return "OpArbitraryFloatATanINTEL"; + case SpvOpArbitraryFloatATanPiINTEL: + return "OpArbitraryFloatATanPiINTEL"; + case SpvOpArbitraryFloatATan2INTEL: + return "OpArbitraryFloatATan2INTEL"; + case SpvOpArbitraryFloatPowINTEL: + return "OpArbitraryFloatPowINTEL"; + case SpvOpArbitraryFloatPowRINTEL: + return "OpArbitraryFloatPowRINTEL"; + case SpvOpArbitraryFloatPowNINTEL: + return "OpArbitraryFloatPowNINTEL"; + case SpvOpLoopControlINTEL: + return "OpLoopControlINTEL"; + case SpvOpAliasDomainDeclINTEL: + return "OpAliasDomainDeclINTEL"; + case SpvOpAliasScopeDeclINTEL: + return "OpAliasScopeDeclINTEL"; + case SpvOpAliasScopeListDeclINTEL: + return "OpAliasScopeListDeclINTEL"; + case SpvOpFixedSqrtINTEL: + return "OpFixedSqrtINTEL"; + case SpvOpFixedRecipINTEL: + return "OpFixedRecipINTEL"; + case SpvOpFixedRsqrtINTEL: + return "OpFixedRsqrtINTEL"; + case SpvOpFixedSinINTEL: + return "OpFixedSinINTEL"; + case SpvOpFixedCosINTEL: + return "OpFixedCosINTEL"; + case SpvOpFixedSinCosINTEL: + return "OpFixedSinCosINTEL"; + case SpvOpFixedSinPiINTEL: + return "OpFixedSinPiINTEL"; + case SpvOpFixedCosPiINTEL: + return "OpFixedCosPiINTEL"; + case SpvOpFixedSinCosPiINTEL: + return "OpFixedSinCosPiINTEL"; + case SpvOpFixedLogINTEL: + return "OpFixedLogINTEL"; + case SpvOpFixedExpINTEL: + return "OpFixedExpINTEL"; + case SpvOpPtrCastToCrossWorkgroupINTEL: + return "OpPtrCastToCrossWorkgroupINTEL"; + case SpvOpCrossWorkgroupCastToPtrINTEL: + return "OpCrossWorkgroupCastToPtrINTEL"; + case SpvOpReadPipeBlockingINTEL: + return "OpReadPipeBlockingINTEL"; + case SpvOpWritePipeBlockingINTEL: + return "OpWritePipeBlockingINTEL"; + case SpvOpFPGARegINTEL: + return "OpFPGARegINTEL"; + case SpvOpRayQueryGetRayTMinKHR: + return "OpRayQueryGetRayTMinKHR"; + case SpvOpRayQueryGetRayFlagsKHR: + return "OpRayQueryGetRayFlagsKHR"; + case SpvOpRayQueryGetIntersectionTKHR: + return "OpRayQueryGetIntersectionTKHR"; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: + return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: + return "OpRayQueryGetIntersectionInstanceIdKHR"; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: + return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: + return "OpRayQueryGetIntersectionGeometryIndexKHR"; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: + return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: + return "OpRayQueryGetIntersectionBarycentricsKHR"; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: + return "OpRayQueryGetIntersectionFrontFaceKHR"; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: + return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: + return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: + return "OpRayQueryGetIntersectionObjectRayOriginKHR"; + case SpvOpRayQueryGetWorldRayDirectionKHR: + return "OpRayQueryGetWorldRayDirectionKHR"; + case SpvOpRayQueryGetWorldRayOriginKHR: + return "OpRayQueryGetWorldRayOriginKHR"; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: + return "OpRayQueryGetIntersectionObjectToWorldKHR"; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: + return "OpRayQueryGetIntersectionWorldToObjectKHR"; + case SpvOpAtomicFAddEXT: + return "OpAtomicFAddEXT"; + case SpvOpTypeBufferSurfaceINTEL: + return "OpTypeBufferSurfaceINTEL"; + case SpvOpTypeStructContinuedINTEL: + return "OpTypeStructContinuedINTEL"; + case SpvOpConstantCompositeContinuedINTEL: + return "OpConstantCompositeContinuedINTEL"; + case SpvOpSpecConstantCompositeContinuedINTEL: + return "OpSpecConstantCompositeContinuedINTEL"; + case SpvOpCompositeConstructContinuedINTEL: + return "OpCompositeConstructContinuedINTEL"; + case SpvOpConvertFToBF16INTEL: + return "OpConvertFToBF16INTEL"; + case SpvOpConvertBF16ToFINTEL: + return "OpConvertBF16ToFINTEL"; + case SpvOpControlBarrierArriveINTEL: + return "OpControlBarrierArriveINTEL"; + case SpvOpControlBarrierWaitINTEL: + return "OpControlBarrierWaitINTEL"; + case SpvOpArithmeticFenceEXT: + return "OpArithmeticFenceEXT"; + case SpvOpTaskSequenceCreateINTEL: + return "OpTaskSequenceCreateINTEL"; + case SpvOpTaskSequenceAsyncINTEL: + return "OpTaskSequenceAsyncINTEL"; + case SpvOpTaskSequenceGetINTEL: + return "OpTaskSequenceGetINTEL"; + case SpvOpTaskSequenceReleaseINTEL: + return "OpTaskSequenceReleaseINTEL"; + case SpvOpTypeTaskSequenceINTEL: + return "OpTypeTaskSequenceINTEL"; + case SpvOpSubgroupBlockPrefetchINTEL: + return "OpSubgroupBlockPrefetchINTEL"; + case SpvOpSubgroup2DBlockLoadINTEL: + return "OpSubgroup2DBlockLoadINTEL"; + case SpvOpSubgroup2DBlockLoadTransformINTEL: + return "OpSubgroup2DBlockLoadTransformINTEL"; + case SpvOpSubgroup2DBlockLoadTransposeINTEL: + return "OpSubgroup2DBlockLoadTransposeINTEL"; + case SpvOpSubgroup2DBlockPrefetchINTEL: + return "OpSubgroup2DBlockPrefetchINTEL"; + case SpvOpSubgroup2DBlockStoreINTEL: + return "OpSubgroup2DBlockStoreINTEL"; + case SpvOpSubgroupMatrixMultiplyAccumulateINTEL: + return "OpSubgroupMatrixMultiplyAccumulateINTEL"; + case SpvOpBitwiseFunctionINTEL: + return "OpBitwiseFunctionINTEL"; + case SpvOpUntypedVariableLengthArrayINTEL: + return "OpUntypedVariableLengthArrayINTEL"; + case SpvOpConditionalExtensionINTEL: + return "OpConditionalExtensionINTEL"; + case SpvOpConditionalEntryPointINTEL: + return "OpConditionalEntryPointINTEL"; + case SpvOpConditionalCapabilityINTEL: + return "OpConditionalCapabilityINTEL"; + case SpvOpSpecConstantTargetINTEL: + return "OpSpecConstantTargetINTEL"; + case SpvOpSpecConstantArchitectureINTEL: + return "OpSpecConstantArchitectureINTEL"; + case SpvOpSpecConstantCapabilitiesINTEL: + return "OpSpecConstantCapabilitiesINTEL"; + case SpvOpConditionalCopyObjectINTEL: + return "OpConditionalCopyObjectINTEL"; + case SpvOpGroupIMulKHR: + return "OpGroupIMulKHR"; + case SpvOpGroupFMulKHR: + return "OpGroupFMulKHR"; + case SpvOpGroupBitwiseAndKHR: + return "OpGroupBitwiseAndKHR"; + case SpvOpGroupBitwiseOrKHR: + return "OpGroupBitwiseOrKHR"; + case SpvOpGroupBitwiseXorKHR: + return "OpGroupBitwiseXorKHR"; + case SpvOpGroupLogicalAndKHR: + return "OpGroupLogicalAndKHR"; + case SpvOpGroupLogicalOrKHR: + return "OpGroupLogicalOrKHR"; + case SpvOpGroupLogicalXorKHR: + return "OpGroupLogicalXorKHR"; + case SpvOpRoundFToTF32INTEL: + return "OpRoundFToTF32INTEL"; + case SpvOpMaskedGatherINTEL: + return "OpMaskedGatherINTEL"; + case SpvOpMaskedScatterINTEL: + return "OpMaskedScatterINTEL"; + case SpvOpConvertHandleToImageINTEL: + return "OpConvertHandleToImageINTEL"; + case SpvOpConvertHandleToSamplerINTEL: + return "OpConvertHandleToSamplerINTEL"; + case SpvOpConvertHandleToSampledImageINTEL: + return "OpConvertHandleToSampledImageINTEL"; + default: + return "Unknown"; + } +} + +#endif /* SPV_ENABLE_UTILITY_CODE */ + +#endif diff --git a/lib/All/SPIRV-Reflect/main.cpp b/lib/All/SPIRV-Reflect/main.cpp new file mode 100644 index 0000000..00d3a94 --- /dev/null +++ b/lib/All/SPIRV-Reflect/main.cpp @@ -0,0 +1,211 @@ +/* + Copyright 2017-2018 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include +#include +#if defined(WIN32) +#define _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include + +#include "common/output_stream.h" +#include "examples/arg_parser.h" +#include "spirv_reflect.h" + +// ================================================================================================= +// PrintUsage() +// ================================================================================================= +void PrintUsage() { + std::cout << "Usage: spirv-reflect [OPTIONS] path/to/SPIR-V/bytecode.spv" << std::endl + << "Prints a summary of the reflection data extracted from SPIR-V " + "bytecode." + << std::endl + << "Options:" << std::endl + << " --help Display this message" << std::endl + << " -o,--output Print output to file. [default: stdout]" << std::endl + << " -y,--yaml Format output as YAML. [default: disabled]" << std::endl + << " -v VERBOSITY Specify output verbosity (YAML output " + "only):" + << std::endl + << " 0: shader info, block variables, interface " + "variables," + << std::endl + << " descriptor bindings. No type " + "descriptions. [default]" + << std::endl + << " 1: Everything above, plus type " + "descriptions." + << std::endl + << " 2: Everything above, plus SPIR-V bytecode " + "and all internal" + << std::endl + << " type descriptions. If you're not " + "working on SPIRV-Reflect" + << std::endl + << " itself, you probably don't want this." << std::endl + << "-e,--entrypoint Prints entry points found in shader " + "module." + << std::endl + << "-s,--stage Prints Vulkan shader stages found in " + "shader module." + << std::endl + << "-f,--file Prints the source file found in shader " + "module." + << std::endl + << "-fcb,--flatten_cbuffers Flatten constant buffers on non-YAML " + "output." + << std::endl; +} + +// ================================================================================================= +// main() +// ================================================================================================= +int main(int argn, char** argv) { + ArgParser arg_parser; + arg_parser.AddFlag("h", "help", ""); + arg_parser.AddOptionString("o", "output", ""); + arg_parser.AddFlag("y", "yaml", ""); + arg_parser.AddOptionInt("v", "verbosity", "", 0); + arg_parser.AddFlag("e", "entrypoint", ""); + arg_parser.AddFlag("s", "stage", ""); + arg_parser.AddFlag("f", "file", ""); + arg_parser.AddFlag("fcb", "flatten_cbuffers", ""); + arg_parser.AddFlag("ci", "ci", ""); // Not advertised + if (!arg_parser.Parse(argn, argv, std::cerr)) { + PrintUsage(); + return EXIT_FAILURE; + } + + if (arg_parser.GetFlag("h", "help")) { + PrintUsage(); + return EXIT_SUCCESS; + } + + std::string output_file; + arg_parser.GetString("o", "output", &output_file); + FILE* output_fp = output_file.empty() ? NULL : freopen(output_file.c_str(), "w", stdout); + + bool output_as_yaml = arg_parser.GetFlag("y", "yaml"); + + int yaml_verbosity = 0; + arg_parser.GetInt("v", "verbosity", &yaml_verbosity); + + bool print_entry_point = arg_parser.GetFlag("e", "entrypoint"); + bool print_shader_stage = arg_parser.GetFlag("s", "stage"); + bool print_source_file = arg_parser.GetFlag("f", "file"); + bool flatten_cbuffers = arg_parser.GetFlag("fcb", "flatten_cbuffers"); + bool ci_mode = arg_parser.GetFlag("ci", "ci"); + + std::string input_spv_path; + std::vector spv_data; + + // Get SPIR-V data/input + if (arg_parser.GetArg(0, &input_spv_path)) { + std::ifstream spv_ifstream(input_spv_path.c_str(), std::ios::binary); + if (!spv_ifstream.is_open()) { + std::cerr << "ERROR: could not open '" << input_spv_path << "' for reading" << std::endl; + return EXIT_FAILURE; + } + + spv_ifstream.seekg(0, std::ios::end); + size_t size = static_cast(spv_ifstream.tellg()); + spv_ifstream.seekg(0, std::ios::beg); + + spv_data.resize(size); + spv_ifstream.read((char*)spv_data.data(), size); + } else { + uint8_t buffer[4096]; + size_t bytes_read = fread(buffer, 1, sizeof(buffer), stdin); + if (bytes_read == 0) { + std::cerr << "ERROR: no SPIR-V file specified" << std::endl; + return EXIT_FAILURE; + } + spv_data.insert(spv_data.end(), buffer, buffer + bytes_read); + while ((bytes_read = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { + spv_data.insert(spv_data.end(), buffer, buffer + bytes_read); + } + } + + // run reflection with input + { + spv_reflect::ShaderModule reflection(spv_data.size(), spv_data.data()); + if (reflection.GetResult() != SPV_REFLECT_RESULT_SUCCESS) { + std::cerr << "ERROR: could not process '" << input_spv_path << "' (is it a valid SPIR-V bytecode?)" << std::endl; + return EXIT_FAILURE; + } + + if (ci_mode) { + // When running CI we want to just test that SPIRV-Reflect doesn't crash, + // The output is not important (as there is nothing to compare it too) + // This hidden flag is here to allow a way to suppress the logging in CI + // to only the shader name (otherwise the logs noise and GBs large) + std::cout << input_spv_path << std::endl; + return EXIT_SUCCESS; + } + + if (print_entry_point || print_shader_stage || print_source_file) { + size_t printed_count = 0; + if (print_entry_point || print_shader_stage) { + for (uint32_t i = 0; i < reflection.GetEntryPointCount(); ++i) { + if (print_entry_point) { + if (printed_count > 0) { + std::cout << ";"; + } + std::cout << reflection.GetEntryPointName(i); + ++printed_count; + } + if (print_shader_stage) { + if (printed_count > 0) { + std::cout << ";"; + } + std::cout << ToStringShaderStage(reflection.GetEntryPointShaderStage(i)); + ++printed_count; + } + ++printed_count; + } + } + + if (print_source_file) { + if (printed_count > 0) { + std::cout << ";"; + } + std::cout << (reflection.GetSourceFile() != NULL ? reflection.GetSourceFile() : ""); + } + + std::cout << std::endl; + } else { + if (output_as_yaml) { + SpvReflectToYaml yamlizer(reflection.GetShaderModule(), yaml_verbosity); + std::cout << yamlizer; + } else { + WriteReflection(reflection, flatten_cbuffers, std::cout); + std::cout << std::endl; + std::cout << std::endl; + } + } + } + + if (output_fp) { + fclose(output_fp); + } + return EXIT_SUCCESS; +} diff --git a/lib/All/SPIRV-Reflect/spirv_reflect.c b/lib/All/SPIRV-Reflect/spirv_reflect.c new file mode 100644 index 0000000..7ee85ce --- /dev/null +++ b/lib/All/SPIRV-Reflect/spirv_reflect.c @@ -0,0 +1,5549 @@ +/* + Copyright 2017-2022 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "spirv_reflect.h" + +#include +#include +#include + +#if defined(WIN32) +#define _CRTDBG_MAP_ALLOC +#include +#include +#else +#include +#endif + +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 7) || defined(__APPLE_CC__) +#define FALLTHROUGH __attribute__((fallthrough)) +#else +#define FALLTHROUGH +#endif + +#if defined(SPIRV_REFLECT_ENABLE_ASSERTS) +#define SPV_REFLECT_ASSERT(COND) assert(COND); +#else +#define SPV_REFLECT_ASSERT(COND) +#endif + +// clang-format off +enum { + SPIRV_STARTING_WORD_INDEX = 5, + SPIRV_WORD_SIZE = sizeof(uint32_t), + SPIRV_BYTE_WIDTH = 8, + SPIRV_MINIMUM_FILE_SIZE = SPIRV_STARTING_WORD_INDEX * SPIRV_WORD_SIZE, + SPIRV_DATA_ALIGNMENT = 4 * SPIRV_WORD_SIZE, // 16 + SPIRV_ACCESS_CHAIN_INDEX_OFFSET = 4, + SPIRV_PHYSICAL_STORAGE_POINTER_SIZE = 8, // Pointers are defined as 64-bit +}; + +enum { + INVALID_VALUE = (int)0xFFFFFFFF, +}; + +enum { + MAX_NODE_NAME_LENGTH = 1024, + // Number of unique PhysicalStorageBuffer structs tracked to detect recursion + MAX_RECURSIVE_PHYSICAL_POINTER_CHECK = 128, +}; + +enum { + IMAGE_SAMPLED = 1, + IMAGE_STORAGE = 2, +}; + +typedef struct SpvReflectPrvArrayTraits { + uint32_t element_type_id; + uint32_t length_id; +} SpvReflectPrvArrayTraits; + +typedef struct SpvReflectPrvImageTraits { + uint32_t sampled_type_id; + SpvDim dim; + uint32_t depth; + uint32_t arrayed; + uint32_t ms; + uint32_t sampled; + SpvImageFormat image_format; +} SpvReflectPrvImageTraits; + +typedef struct SpvReflectPrvNumberDecoration { + uint32_t word_offset; + uint32_t value; +} SpvReflectPrvNumberDecoration; + +typedef struct SpvReflectPrvStringDecoration { + uint32_t word_offset; + const char* value; +} SpvReflectPrvStringDecoration; + +typedef struct SpvReflectPrvDecorations { + bool is_relaxed_precision; + bool is_block; + bool is_buffer_block; + bool is_row_major; + bool is_column_major; + bool is_built_in; + bool is_noperspective; + bool is_flat; + bool is_non_writable; + bool is_non_readable; + bool is_patch; + bool is_per_vertex; + bool is_per_task; + bool is_weight_texture; + bool is_block_match_texture; + SpvReflectUserType user_type; + SpvReflectPrvNumberDecoration set; + SpvReflectPrvNumberDecoration binding; + SpvReflectPrvNumberDecoration input_attachment_index; + SpvReflectPrvNumberDecoration location; + SpvReflectPrvNumberDecoration component; + SpvReflectPrvNumberDecoration offset; + SpvReflectPrvNumberDecoration uav_counter_buffer; + SpvReflectPrvStringDecoration semantic; + uint32_t array_stride; + uint32_t matrix_stride; + uint32_t spec_id; + SpvBuiltIn built_in; +} SpvReflectPrvDecorations; + +typedef struct SpvReflectPrvNode { + uint32_t result_id; + SpvOp op; + uint32_t result_type_id; + uint32_t type_id; + SpvCapability capability; + SpvStorageClass storage_class; + uint32_t word_offset; + uint32_t word_count; + bool is_type; + + SpvReflectPrvArrayTraits array_traits; + SpvReflectPrvImageTraits image_traits; + uint32_t image_type_id; + + const char* name; + SpvReflectPrvDecorations decorations; + uint32_t member_count; + const char** member_names; + SpvReflectPrvDecorations* member_decorations; +} SpvReflectPrvNode; + +typedef struct SpvReflectPrvString { + uint32_t result_id; + const char* string; +} SpvReflectPrvString; + +// There are a limit set of instructions that can touch an OpVariable, +// these are represented here with how it was accessed +// Examples: +// OpImageRead -> OpLoad -> OpVariable +// OpImageWrite -> OpLoad -> OpVariable +// OpStore -> OpAccessChain -> OpAccessChain -> OpVariable +// OpAtomicIAdd -> OpAccessChain -> OpVariable +// OpAtomicLoad -> OpImageTexelPointer -> OpVariable +typedef struct SpvReflectPrvAccessedVariable { + SpvReflectPrvNode* p_node; + uint32_t result_id; + uint32_t variable_ptr; + uint32_t function_id; + uint32_t function_parameter_index; +} SpvReflectPrvAccessedVariable; + +typedef struct SpvReflectPrvFunction { + uint32_t id; + uint32_t parameter_count; + uint32_t* parameters; + uint32_t callee_count; + uint32_t* callees; + struct SpvReflectPrvFunction** callee_ptrs; + uint32_t accessed_variable_count; + SpvReflectPrvAccessedVariable* accessed_variables; +} SpvReflectPrvFunction; + +typedef struct SpvReflectPrvAccessChain { + uint32_t result_id; + uint32_t result_type_id; + // + // Pointing to the base of a composite object. + // Generally the id of descriptor block variable + uint32_t base_id; + // + // From spec: + // The first index in Indexes will select the + // top-level member/element/component/element + // of the base composite + uint32_t index_count; + uint32_t* indexes; + // + // Block variable ac is pointing to (for block references) + SpvReflectBlockVariable* block_var; +} SpvReflectPrvAccessChain; + +// To prevent infinite recursion, we never walk down a +// PhysicalStorageBuffer struct twice, but incase a 2nd variable +// needs to use that struct, save a copy +typedef struct SpvReflectPrvPhysicalPointerStruct { + uint32_t struct_id; + // first variable to see the PhysicalStorageBuffer struct + SpvReflectBlockVariable* p_var; +} SpvReflectPrvPhysicalPointerStruct; + +typedef struct SpvReflectPrvParser { + size_t spirv_word_count; + uint32_t* spirv_code; + uint32_t string_count; + SpvReflectPrvString* strings; + SpvSourceLanguage source_language; + uint32_t source_language_version; + uint32_t source_file_id; + const char* source_embedded; + size_t node_count; + SpvReflectPrvNode* nodes; + uint32_t entry_point_count; + uint32_t capability_count; + uint32_t function_count; + SpvReflectPrvFunction* functions; + uint32_t access_chain_count; + SpvReflectPrvAccessChain* access_chains; + + uint32_t type_count; + uint32_t descriptor_count; + uint32_t push_constant_count; + uint32_t spec_constant_count; + + SpvReflectTypeDescription* physical_pointer_check[MAX_RECURSIVE_PHYSICAL_POINTER_CHECK]; + uint32_t physical_pointer_count; + + SpvReflectPrvPhysicalPointerStruct* physical_pointer_structs; + uint32_t physical_pointer_struct_count; +} SpvReflectPrvParser; +// clang-format on + +static uint32_t Max(uint32_t a, uint32_t b) { return a > b ? a : b; } +static uint32_t Min(uint32_t a, uint32_t b) { return a < b ? a : b; } + +static uint32_t RoundUp(uint32_t value, uint32_t multiple) { + assert(multiple && ((multiple & (multiple - 1)) == 0)); + return (value + multiple - 1) & ~(multiple - 1); +} + +#define IsNull(ptr) (ptr == NULL) + +#define IsNotNull(ptr) (ptr != NULL) + +#define SafeFree(ptr) \ + { \ + free((void*)ptr); \ + ptr = NULL; \ + } + +static int SortCompareUint32(const void* a, const void* b) { + const uint32_t* p_a = (const uint32_t*)a; + const uint32_t* p_b = (const uint32_t*)b; + + return (int)*p_a - (int)*p_b; +} + +static int SortCompareAccessedVariable(const void* a, const void* b) { + const SpvReflectPrvAccessedVariable* p_a = (const SpvReflectPrvAccessedVariable*)a; + const SpvReflectPrvAccessedVariable* p_b = (const SpvReflectPrvAccessedVariable*)b; + + return (int)p_a->variable_ptr - (int)p_b->variable_ptr; +} + +// +// De-duplicates a sorted array and returns the new size. +// +// Note: The array doesn't actually need to be sorted, just +// arranged into "runs" so that all the entries with one +// value are adjacent. +// +static size_t DedupSortedUint32(uint32_t* arr, size_t size) { + if (size == 0) { + return 0; + } + size_t dedup_idx = 0; + for (size_t i = 0; i < size; ++i) { + if (arr[dedup_idx] != arr[i]) { + ++dedup_idx; + arr[dedup_idx] = arr[i]; + } + } + return dedup_idx + 1; +} + +static bool SearchSortedUint32(const uint32_t* arr, size_t size, uint32_t target) { + size_t lo = 0; + size_t hi = size; + while (lo < hi) { + size_t mid = (hi - lo) / 2 + lo; + if (arr[mid] == target) { + return true; + } else if (arr[mid] < target) { + lo = mid + 1; + } else { + hi = mid; + } + } + return false; +} + +static SpvReflectResult IntersectSortedAccessedVariable(const SpvReflectPrvAccessedVariable* p_arr0, size_t arr0_size, + const uint32_t* p_arr1, size_t arr1_size, uint32_t** pp_res, + size_t* res_size) { + *pp_res = NULL; + *res_size = 0; + if (IsNull(p_arr0) || IsNull(p_arr1)) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + const SpvReflectPrvAccessedVariable* p_arr0_end = p_arr0 + arr0_size; + const uint32_t* p_arr1_end = p_arr1 + arr1_size; + + const SpvReflectPrvAccessedVariable* p_idx0 = p_arr0; + const uint32_t* p_idx1 = p_arr1; + while (p_idx0 != p_arr0_end && p_idx1 != p_arr1_end) { + if (p_idx0->variable_ptr < *p_idx1) { + ++p_idx0; + } else if (p_idx0->variable_ptr > *p_idx1) { + ++p_idx1; + } else { + ++*res_size; + ++p_idx0; + ++p_idx1; + } + } + + if (*res_size > 0) { + *pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res)); + if (IsNull(*pp_res)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + uint32_t* p_idxr = *pp_res; + p_idx0 = p_arr0; + p_idx1 = p_arr1; + while (p_idx0 != p_arr0_end && p_idx1 != p_arr1_end) { + if (p_idx0->variable_ptr < *p_idx1) { + ++p_idx0; + } else if (p_idx0->variable_ptr > *p_idx1) { + ++p_idx1; + } else { + *(p_idxr++) = p_idx0->variable_ptr; + ++p_idx0; + ++p_idx1; + } + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static bool InRange(const SpvReflectPrvParser* p_parser, uint32_t index) { + bool in_range = false; + if (IsNotNull(p_parser)) { + in_range = (index < p_parser->spirv_word_count); + } + return in_range; +} + +static SpvReflectResult ReadU32(SpvReflectPrvParser* p_parser, uint32_t word_offset, uint32_t* p_value) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(InRange(p_parser, word_offset)); + SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF; + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, word_offset)) { + *p_value = *(p_parser->spirv_code + word_offset); + result = SPV_REFLECT_RESULT_SUCCESS; + } + return result; +} + +#define UNCHECKED_READU32(parser, word_offset, value) \ + { (void)ReadU32(parser, word_offset, (uint32_t*)&(value)); } + +#define CHECKED_READU32(parser, word_offset, value) \ + { \ + SpvReflectResult checked_readu32_result = ReadU32(parser, word_offset, (uint32_t*)&(value)); \ + if (checked_readu32_result != SPV_REFLECT_RESULT_SUCCESS) { \ + return checked_readu32_result; \ + } \ + } + +#define CHECKED_READU32_CAST(parser, word_offset, cast_to_type, value) \ + { \ + uint32_t checked_readu32_cast_u32 = UINT32_MAX; \ + SpvReflectResult checked_readu32_cast_result = ReadU32(parser, word_offset, (uint32_t*)&(checked_readu32_cast_u32)); \ + if (checked_readu32_cast_result != SPV_REFLECT_RESULT_SUCCESS) { \ + return checked_readu32_cast_result; \ + } \ + value = (cast_to_type)checked_readu32_cast_u32; \ + } + +#define IF_READU32(result, parser, word_offset, value) \ + if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \ + result = ReadU32(parser, word_offset, (uint32_t*)&(value)); \ + } + +#define IF_READU32_CAST(result, parser, word_offset, cast_to_type, value) \ + if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \ + uint32_t if_readu32_cast_u32 = UINT32_MAX; \ + result = ReadU32(parser, word_offset, &if_readu32_cast_u32); \ + if ((result) == SPV_REFLECT_RESULT_SUCCESS) { \ + value = (cast_to_type)if_readu32_cast_u32; \ + } \ + } + +static SpvReflectResult ReadStr(SpvReflectPrvParser* p_parser, uint32_t word_offset, uint32_t word_index, uint32_t word_count, + uint32_t* p_buf_size, char* p_buf) { + uint32_t limit = (word_offset + word_count); + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(InRange(p_parser, limit)); + SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF; + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, limit)) { + const char* c_str = (const char*)(p_parser->spirv_code + word_offset + word_index); + uint32_t n = word_count * SPIRV_WORD_SIZE; + uint32_t length_with_terminator = 0; + for (uint32_t i = 0; i < n; ++i) { + char c = *(c_str + i); + if (c == 0) { + length_with_terminator = i + 1; + break; + } + } + + if (length_with_terminator > 0) { + result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + if (IsNotNull(p_buf_size) && IsNotNull(p_buf)) { + result = SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; + if (length_with_terminator <= *p_buf_size) { + memset(p_buf, 0, *p_buf_size); + memcpy(p_buf, c_str, length_with_terminator); + result = SPV_REFLECT_RESULT_SUCCESS; + } + } else { + if (IsNotNull(p_buf_size)) { + *p_buf_size = length_with_terminator; + result = SPV_REFLECT_RESULT_SUCCESS; + } + } + } + } + return result; +} + +static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations* p_decoration_fields) { + SpvReflectDecorationFlags decorations = SPV_REFLECT_DECORATION_NONE; + if (p_decoration_fields->is_relaxed_precision) { + decorations |= SPV_REFLECT_DECORATION_RELAXED_PRECISION; + } + if (p_decoration_fields->is_block) { + decorations |= SPV_REFLECT_DECORATION_BLOCK; + } + if (p_decoration_fields->is_buffer_block) { + decorations |= SPV_REFLECT_DECORATION_BUFFER_BLOCK; + } + if (p_decoration_fields->is_row_major) { + decorations |= SPV_REFLECT_DECORATION_ROW_MAJOR; + } + if (p_decoration_fields->is_column_major) { + decorations |= SPV_REFLECT_DECORATION_COLUMN_MAJOR; + } + if (p_decoration_fields->is_built_in) { + decorations |= SPV_REFLECT_DECORATION_BUILT_IN; + } + if (p_decoration_fields->is_noperspective) { + decorations |= SPV_REFLECT_DECORATION_NOPERSPECTIVE; + } + if (p_decoration_fields->is_flat) { + decorations |= SPV_REFLECT_DECORATION_FLAT; + } + if (p_decoration_fields->is_non_writable) { + decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE; + } + if (p_decoration_fields->is_non_readable) { + decorations |= SPV_REFLECT_DECORATION_NON_READABLE; + } + if (p_decoration_fields->is_patch) { + decorations |= SPV_REFLECT_DECORATION_PATCH; + } + if (p_decoration_fields->is_per_vertex) { + decorations |= SPV_REFLECT_DECORATION_PER_VERTEX; + } + if (p_decoration_fields->is_per_task) { + decorations |= SPV_REFLECT_DECORATION_PER_TASK; + } + if (p_decoration_fields->is_weight_texture) { + decorations |= SPV_REFLECT_DECORATION_WEIGHT_TEXTURE; + } + if (p_decoration_fields->is_block_match_texture) { + decorations |= SPV_REFLECT_DECORATION_BLOCK_MATCH_TEXTURE; + } + return decorations; +} + +static void ApplyNumericTraits(const SpvReflectTypeDescription* p_type, SpvReflectNumericTraits* p_numeric_traits) { + memcpy(p_numeric_traits, &p_type->traits.numeric, sizeof(p_type->traits.numeric)); +} + +static void ApplyArrayTraits(const SpvReflectTypeDescription* p_type, SpvReflectArrayTraits* p_array_traits) { + memcpy(p_array_traits, &p_type->traits.array, sizeof(p_type->traits.array)); +} + +static bool IsSpecConstant(const SpvReflectPrvNode* p_node) { + return (p_node->op == SpvOpSpecConstant || p_node->op == SpvOpSpecConstantOp || p_node->op == SpvOpSpecConstantTrue || + p_node->op == SpvOpSpecConstantFalse); +} + +static SpvReflectPrvNode* FindNode(SpvReflectPrvParser* p_parser, uint32_t result_id) { + SpvReflectPrvNode* p_node = NULL; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_elem = &(p_parser->nodes[i]); + if (p_elem->result_id == result_id) { + p_node = p_elem; + break; + } + } + return p_node; +} + +static SpvReflectTypeDescription* FindType(SpvReflectShaderModule* p_module, uint32_t type_id) { + SpvReflectTypeDescription* p_type = NULL; + for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) { + SpvReflectTypeDescription* p_elem = &(p_module->_internal->type_descriptions[i]); + if (p_elem->id == type_id) { + p_type = p_elem; + break; + } + } + return p_type; +} + +static SpvReflectPrvAccessChain* FindAccessChain(SpvReflectPrvParser* p_parser, uint32_t id) { + const uint32_t ac_count = p_parser->access_chain_count; + for (uint32_t i = 0; i < ac_count; i++) { + if (p_parser->access_chains[i].result_id == id) { + return &p_parser->access_chains[i]; + } + } + return 0; +} + +// Access Chains mostly have their Base ID pointed directly to a OpVariable, but sometimes +// it will be through a load and this funciton handles the edge cases how to find that +static uint32_t FindAccessChainBaseVariable(SpvReflectPrvParser* p_parser, SpvReflectPrvAccessChain* p_access_chain) { + uint32_t base_id = p_access_chain->base_id; + SpvReflectPrvNode* base_node = FindNode(p_parser, base_id); + // TODO - This is just a band-aid to fix crashes. + // Need to understand why here and hopefully remove + // https://github.com/KhronosGroup/SPIRV-Reflect/pull/206 + if (IsNull(base_node)) { + return 0; + } + while (base_node->op != SpvOpVariable) { + switch (base_node->op) { + case SpvOpLoad: { + UNCHECKED_READU32(p_parser, base_node->word_offset + 3, base_id); + } break; + case SpvOpFunctionParameter: { + UNCHECKED_READU32(p_parser, base_node->word_offset + 2, base_id); + } break; + case SpvOpBitcast: + // This can be caused by something like GL_EXT_buffer_reference_uvec2 trying to load a pointer. + // We currently call from a push constant, so no way to have a reference loop back into the PC block + return 0; + default: { + assert(false); + } break; + } + + SpvReflectPrvAccessChain* base_ac = FindAccessChain(p_parser, base_id); + if (base_ac == 0) { + return 0; + } + base_id = base_ac->base_id; + base_node = FindNode(p_parser, base_id); + if (IsNull(base_node)) { + return 0; + } + } + return base_id; +} + +static SpvReflectBlockVariable* GetRefBlkVar(SpvReflectPrvParser* p_parser, SpvReflectPrvAccessChain* p_access_chain) { + uint32_t base_id = p_access_chain->base_id; + SpvReflectPrvNode* base_node = FindNode(p_parser, base_id); + assert(base_node->op == SpvOpLoad); + UNCHECKED_READU32(p_parser, base_node->word_offset + 3, base_id); + SpvReflectPrvAccessChain* base_ac = FindAccessChain(p_parser, base_id); + assert(base_ac != 0); + SpvReflectBlockVariable* base_var = base_ac->block_var; + assert(base_var != 0); + return base_var; +} + +bool IsPointerToPointer(SpvReflectPrvParser* p_parser, uint32_t type_id) { + SpvReflectPrvNode* ptr_node = FindNode(p_parser, type_id); + if (IsNull(ptr_node) || (ptr_node->op != SpvOpTypePointer)) { + return false; + } + uint32_t pte_id = 0; + UNCHECKED_READU32(p_parser, ptr_node->word_offset + 3, pte_id); + SpvReflectPrvNode* pte_node = FindNode(p_parser, pte_id); + if (IsNull(pte_node)) { + return false; + } + return pte_node->op == SpvOpTypePointer; +} + +static SpvReflectResult CreateParser(size_t size, void* p_code, SpvReflectPrvParser* p_parser) { + if (p_code == NULL) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (size < SPIRV_MINIMUM_FILE_SIZE) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE; + } + if ((size % 4) != 0) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE; + } + + p_parser->spirv_word_count = size / SPIRV_WORD_SIZE; + p_parser->spirv_code = (uint32_t*)p_code; + + if (p_parser->spirv_code[0] != SpvMagicNumber) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static void DestroyParser(SpvReflectPrvParser* p_parser) { + if (!IsNull(p_parser->nodes)) { + // Free nodes + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (IsNotNull(p_node->member_names)) { + SafeFree(p_node->member_names); + } + if (IsNotNull(p_node->member_decorations)) { + SafeFree(p_node->member_decorations); + } + } + + // Free functions + for (size_t i = 0; i < p_parser->function_count; ++i) { + SafeFree(p_parser->functions[i].parameters); + SafeFree(p_parser->functions[i].callees); + SafeFree(p_parser->functions[i].callee_ptrs); + SafeFree(p_parser->functions[i].accessed_variables); + } + + // Free access chains + for (uint32_t i = 0; i < p_parser->access_chain_count; ++i) { + SafeFree(p_parser->access_chains[i].indexes); + } + + SafeFree(p_parser->nodes); + SafeFree(p_parser->strings); + SafeFree(p_parser->source_embedded); + SafeFree(p_parser->functions); + SafeFree(p_parser->access_chains); + + if (IsNotNull(p_parser->physical_pointer_structs)) { + SafeFree(p_parser->physical_pointer_structs); + } + p_parser->node_count = 0; + } +} + +static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + + uint32_t* p_spirv = p_parser->spirv_code; + uint32_t spirv_word_index = SPIRV_STARTING_WORD_INDEX; + + // Count nodes + uint32_t node_count = 0; + while (spirv_word_index < p_parser->spirv_word_count) { + uint32_t word = p_spirv[spirv_word_index]; + SpvOp op = (SpvOp)(word & 0xFFFF); + uint32_t node_word_count = (word >> 16) & 0xFFFF; + if (node_word_count == 0) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION; + } + if (op == SpvOpAccessChain || op == SpvOpInBoundsAccessChain) { + ++(p_parser->access_chain_count); + } + spirv_word_index += node_word_count; + ++node_count; + } + + if (node_count == 0) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF; + } + + // Allocate nodes + p_parser->node_count = node_count; + p_parser->nodes = (SpvReflectPrvNode*)calloc(p_parser->node_count, sizeof(*(p_parser->nodes))); + if (IsNull(p_parser->nodes)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + // Mark all nodes with an invalid state + for (uint32_t i = 0; i < node_count; ++i) { + p_parser->nodes[i].op = (SpvOp)INVALID_VALUE; + p_parser->nodes[i].storage_class = (SpvStorageClass)INVALID_VALUE; + p_parser->nodes[i].decorations.set.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.binding.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.location.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.component.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.spec_id = (uint32_t)INVALID_VALUE; + p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE; + } + // Mark source file id node + p_parser->source_file_id = (uint32_t)INVALID_VALUE; + p_parser->source_embedded = NULL; + + // Function node + uint32_t function_node = (uint32_t)INVALID_VALUE; + + // Allocate access chain + if (p_parser->access_chain_count > 0) { + p_parser->access_chains = (SpvReflectPrvAccessChain*)calloc(p_parser->access_chain_count, sizeof(*(p_parser->access_chains))); + if (IsNull(p_parser->access_chains)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + // Parse nodes + uint32_t node_index = 0; + uint32_t access_chain_index = 0; + spirv_word_index = SPIRV_STARTING_WORD_INDEX; + while (spirv_word_index < p_parser->spirv_word_count) { + uint32_t word = p_spirv[spirv_word_index]; + SpvOp op = (SpvOp)(word & 0xFFFF); + uint32_t node_word_count = (word >> 16) & 0xFFFF; + + SpvReflectPrvNode* p_node = &(p_parser->nodes[node_index]); + p_node->op = op; + p_node->word_offset = spirv_word_index; + p_node->word_count = node_word_count; + + switch (p_node->op) { + default: + break; + + case SpvOpString: { + ++(p_parser->string_count); + } break; + + case SpvOpSource: { + CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvSourceLanguage, p_parser->source_language); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_parser->source_language_version); + if (p_node->word_count >= 4) { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_parser->source_file_id); + } + if (p_node->word_count >= 5) { + const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 4); + + const size_t source_len = strlen(p_source); + char* p_source_temp = (char*)calloc(source_len + 1, sizeof(char)); + + if (IsNull(p_source_temp)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + +#ifdef _WIN32 + strcpy_s(p_source_temp, source_len + 1, p_source); +#else + strcpy(p_source_temp, p_source); +#endif + + SafeFree(p_parser->source_embedded); + p_parser->source_embedded = p_source_temp; + } + } break; + + case SpvOpSourceContinued: { + const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 1); + + const size_t source_len = strlen(p_source); + const size_t embedded_source_len = strlen(p_parser->source_embedded); + char* p_continued_source = (char*)calloc(source_len + embedded_source_len + 1, sizeof(char)); + + if (IsNull(p_continued_source)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + +#ifdef _WIN32 + strcpy_s(p_continued_source, embedded_source_len + 1, p_parser->source_embedded); + strcat_s(p_continued_source, embedded_source_len + source_len + 1, p_source); +#else + strcpy(p_continued_source, p_parser->source_embedded); + strcat(p_continued_source, p_source); +#endif + + SafeFree(p_parser->source_embedded); + p_parser->source_embedded = p_continued_source; + } break; + + case SpvOpEntryPoint: { + ++(p_parser->entry_point_count); + } break; + + case SpvOpCapability: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->capability); + ++(p_parser->capability_count); + } break; + + case SpvOpName: + case SpvOpMemberName: { + uint32_t member_offset = (p_node->op == SpvOpMemberName) ? 1 : 0; + uint32_t name_start = p_node->word_offset + member_offset + 2; + p_node->name = (const char*)(p_parser->spirv_code + name_start); + } break; + + case SpvOpTypeStruct: { + p_node->member_count = p_node->word_count - 2; + FALLTHROUGH; + } // Fall through + + // This is all the rest of OpType* that need to be tracked + // Possible new extensions might expose new type, will need to be added + // here + case SpvOpTypeVoid: + case SpvOpTypeBool: + case SpvOpTypeInt: + case SpvOpTypeFloat: + case SpvOpTypeVector: + case SpvOpTypeMatrix: + case SpvOpTypeSampler: + case SpvOpTypeOpaque: + case SpvOpTypeFunction: + case SpvOpTypeEvent: + case SpvOpTypeDeviceEvent: + case SpvOpTypeReserveId: + case SpvOpTypeQueue: + case SpvOpTypePipe: + case SpvOpTypeAccelerationStructureKHR: + case SpvOpTypeRayQueryKHR: + case SpvOpTypeHitObjectNV: + case SpvOpTypeCooperativeVectorNV: + case SpvOpTypeCooperativeMatrixNV: + case SpvOpTypeCooperativeMatrixKHR: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + p_node->is_type = true; + } break; + + case SpvOpTypeImage: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_traits.sampled_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->image_traits.dim); + CHECKED_READU32(p_parser, p_node->word_offset + 4, p_node->image_traits.depth); + CHECKED_READU32(p_parser, p_node->word_offset + 5, p_node->image_traits.arrayed); + CHECKED_READU32(p_parser, p_node->word_offset + 6, p_node->image_traits.ms); + CHECKED_READU32(p_parser, p_node->word_offset + 7, p_node->image_traits.sampled); + CHECKED_READU32(p_parser, p_node->word_offset + 8, p_node->image_traits.image_format); + p_node->is_type = true; + } break; + + case SpvOpTypeSampledImage: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_type_id); + p_node->is_type = true; + } break; + + case SpvOpTypeArray: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->array_traits.length_id); + p_node->is_type = true; + } break; + + case SpvOpTypeRuntimeArray: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id); + p_node->is_type = true; + } break; + + case SpvOpTypePointer: { + uint32_t result_id; + CHECKED_READU32(p_parser, p_node->word_offset + 1, result_id); + // Look for forward pointer. Clear result id if found + SpvReflectPrvNode* p_fwd_node = FindNode(p_parser, result_id); + if (p_fwd_node) { + p_fwd_node->result_id = 0; + } + // Register pointer type + p_node->result_id = result_id; + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->type_id); + p_node->is_type = true; + } break; + + case SpvOpTypeForwardPointer: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class); + p_node->is_type = true; + } break; + + case SpvOpConstantTrue: + case SpvOpConstantFalse: + case SpvOpConstant: + case SpvOpConstantComposite: + case SpvOpConstantSampler: + case SpvOpConstantNull: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } break; + + case SpvOpSpecConstantTrue: + case SpvOpSpecConstantFalse: + case SpvOpSpecConstant: + case SpvOpSpecConstantComposite: + case SpvOpSpecConstantOp: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } break; + + case SpvOpVariable: { + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->storage_class); + } break; + + case SpvOpLoad: { + // Only load enough so OpDecorate can reference the node, skip the remaining operands. + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } break; + + case SpvOpAccessChain: + case SpvOpInBoundsAccessChain: { + SpvReflectPrvAccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]); + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_access_chain->result_type_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_access_chain->result_id); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id); + // + // SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index: + // [Node, Result Type Id, Result Id, Base Id, ] + // + p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET); + if (p_access_chain->index_count > 0) { + p_access_chain->indexes = (uint32_t*)calloc(p_access_chain->index_count, sizeof(*(p_access_chain->indexes))); + if (IsNull(p_access_chain->indexes)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + // Parse any index values for access chain + for (uint32_t index_index = 0; index_index < p_access_chain->index_count; ++index_index) { + // Read index id + uint32_t index_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + SPIRV_ACCESS_CHAIN_INDEX_OFFSET + index_index, index_id); + // Find OpConstant node that contains index value + SpvReflectPrvNode* p_index_value_node = FindNode(p_parser, index_id); + if ((p_index_value_node != NULL) && + (p_index_value_node->op == SpvOpConstant || p_index_value_node->op == SpvOpSpecConstant)) { + // Read index value + uint32_t index_value = UINT32_MAX; + CHECKED_READU32(p_parser, p_index_value_node->word_offset + 3, index_value); + assert(index_value != UINT32_MAX); + // Write index value to array + p_access_chain->indexes[index_index] = index_value; + } + } + } + ++access_chain_index; + } break; + + case SpvOpFunction: { + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + // Count function definitions, not function declarations. To determine + // the difference, set an in-function variable, and then if an OpLabel + // is reached before the end of the function increment the function + // count. + function_node = node_index; + } break; + + case SpvOpLabel: { + if (function_node != (uint32_t)INVALID_VALUE) { + SpvReflectPrvNode* p_func_node = &(p_parser->nodes[function_node]); + CHECKED_READU32(p_parser, p_func_node->word_offset + 2, p_func_node->result_id); + ++(p_parser->function_count); + } + FALLTHROUGH; + } // Fall through + + case SpvOpFunctionEnd: { + function_node = (uint32_t)INVALID_VALUE; + } break; + case SpvOpFunctionParameter: { + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } break; + case SpvOpBitcast: + case SpvOpShiftRightLogical: + case SpvOpIAdd: + case SpvOpISub: + case SpvOpIMul: + case SpvOpUDiv: + case SpvOpSDiv: { + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id); + } break; + } + + if (p_node->is_type) { + ++(p_parser->type_count); + } + + spirv_word_index += node_word_count; + ++node_index; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseStrings(SpvReflectPrvParser* p_parser) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(IsNotNull(p_parser->nodes)); + + // Early out + if (p_parser->string_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + // Allocate string storage + p_parser->strings = (SpvReflectPrvString*)calloc(p_parser->string_count, sizeof(*(p_parser->strings))); + + uint32_t string_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op != SpvOpString) { + continue; + } + + // Paranoid check against string count + assert(string_index < p_parser->string_count); + if (string_index >= p_parser->string_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + // Result id + SpvReflectPrvString* p_string = &(p_parser->strings[string_index]); + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_string->result_id); + + // String + uint32_t string_start = p_node->word_offset + 2; + p_string->string = (const char*)(p_parser->spirv_code + string_start); + + // Increment string index + ++string_index; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseSource(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code)) { + // Source file + if (IsNotNull(p_parser->strings)) { + for (uint32_t i = 0; i < p_parser->string_count; ++i) { + SpvReflectPrvString* p_string = &(p_parser->strings[i]); + if (p_string->result_id == p_parser->source_file_id) { + p_module->source_file = p_string->string; + break; + } + } + } + + // Source code + if (IsNotNull(p_parser->source_embedded)) { + const size_t source_len = strlen(p_parser->source_embedded); + char* p_source = (char*)calloc(source_len + 1, sizeof(char)); + + if (IsNull(p_source)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + +#ifdef _WIN32 + strcpy_s(p_source, source_len + 1, p_parser->source_embedded); +#else + strcpy(p_source, p_parser->source_embedded); +#endif + + p_module->source_source = p_source; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseFunction(SpvReflectPrvParser* p_parser, SpvReflectPrvNode* p_func_node, SpvReflectPrvFunction* p_func, + size_t first_label_index) { + p_func->id = p_func_node->result_id; + + p_func->parameter_count = 0; + p_func->callee_count = 0; + p_func->accessed_variable_count = 0; + + // First get count to know how much to allocate + for (size_t i = first_label_index; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op == SpvOpFunctionEnd) { + break; + } + switch (p_node->op) { + case SpvOpFunctionParameter: { + ++(p_func->parameter_count); + } break; + case SpvOpFunctionCall: { + p_func->accessed_variable_count += p_node->word_count - 4; + ++(p_func->callee_count); + } break; + case SpvOpLoad: + case SpvOpAccessChain: + case SpvOpInBoundsAccessChain: + case SpvOpPtrAccessChain: + case SpvOpArrayLength: + case SpvOpGenericPtrMemSemantics: + case SpvOpInBoundsPtrAccessChain: + case SpvOpStore: + case SpvOpImageTexelPointer: { + ++(p_func->accessed_variable_count); + } break; + case SpvOpCopyMemory: + case SpvOpCopyMemorySized: { + p_func->accessed_variable_count += 2; + } break; + default: + break; + } + } + + if (p_func->parameter_count > 0) { + p_func->parameters = (uint32_t*)calloc(p_func->parameter_count, sizeof(*(p_func->parameters))); + if (IsNull(p_func->parameters)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_func->callee_count > 0) { + p_func->callees = (uint32_t*)calloc(p_func->callee_count, sizeof(*(p_func->callees))); + if (IsNull(p_func->callees)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_func->accessed_variable_count > 0) { + p_func->accessed_variables = + (SpvReflectPrvAccessedVariable*)calloc(p_func->accessed_variable_count, sizeof(*(p_func->accessed_variables))); + if (IsNull(p_func->accessed_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + p_func->parameter_count = 0; + p_func->callee_count = 0; + p_func->accessed_variable_count = 0; + // Now have allocation, fill in values + for (size_t i = first_label_index; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op == SpvOpFunctionEnd) { + break; + } + switch (p_node->op) { + case SpvOpFunctionParameter: { + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_func->parameters[p_func->parameter_count]); + (++p_func->parameter_count); + } break; + case SpvOpFunctionCall: { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_func->callees[p_func->callee_count]); + const uint32_t result_index = p_node->word_offset + 2; + for (uint32_t j = 0, parameter_count = p_node->word_count - 4; j < parameter_count; j++) { + const uint32_t ptr_index = p_node->word_offset + 4 + j; + SpvReflectPrvAccessedVariable* access_ptr = &p_func->accessed_variables[p_func->accessed_variable_count]; + + access_ptr->p_node = p_node; + // Need to track Result ID as not sure there has been any memory access through here yet + CHECKED_READU32(p_parser, result_index, access_ptr->result_id); + CHECKED_READU32(p_parser, ptr_index, access_ptr->variable_ptr); + access_ptr->function_id = p_func->callees[p_func->callee_count]; + access_ptr->function_parameter_index = j; + (++p_func->accessed_variable_count); + } + (++p_func->callee_count); + } break; + case SpvOpLoad: + case SpvOpAccessChain: + case SpvOpInBoundsAccessChain: + case SpvOpPtrAccessChain: + case SpvOpArrayLength: + case SpvOpGenericPtrMemSemantics: + case SpvOpInBoundsPtrAccessChain: + case SpvOpImageTexelPointer: { + const uint32_t result_index = p_node->word_offset + 2; + const uint32_t ptr_index = p_node->word_offset + 3; + SpvReflectPrvAccessedVariable* access_ptr = &p_func->accessed_variables[p_func->accessed_variable_count]; + + access_ptr->p_node = p_node; + // Need to track Result ID as not sure there has been any memory access through here yet + CHECKED_READU32(p_parser, result_index, access_ptr->result_id); + CHECKED_READU32(p_parser, ptr_index, access_ptr->variable_ptr); + (++p_func->accessed_variable_count); + } break; + case SpvOpStore: { + const uint32_t result_index = p_node->word_offset + 2; + CHECKED_READU32(p_parser, result_index, p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr); + p_func->accessed_variables[p_func->accessed_variable_count].p_node = p_node; + (++p_func->accessed_variable_count); + } break; + case SpvOpCopyMemory: + case SpvOpCopyMemorySized: { + // There is no result_id or node, being zero is same as being invalid + CHECKED_READU32(p_parser, p_node->word_offset + 1, + p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr); + (++p_func->accessed_variable_count); + CHECKED_READU32(p_parser, p_node->word_offset + 2, + p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr); + (++p_func->accessed_variable_count); + } break; + default: + break; + } + } + + if (p_func->callee_count > 0) { + qsort(p_func->callees, p_func->callee_count, sizeof(*(p_func->callees)), SortCompareUint32); + } + p_func->callee_count = (uint32_t)DedupSortedUint32(p_func->callees, p_func->callee_count); + + if (p_func->accessed_variable_count > 0) { + qsort(p_func->accessed_variables, p_func->accessed_variable_count, sizeof(*(p_func->accessed_variables)), + SortCompareAccessedVariable); + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static int SortCompareFunctions(const void* a, const void* b) { + const SpvReflectPrvFunction* af = (const SpvReflectPrvFunction*)a; + const SpvReflectPrvFunction* bf = (const SpvReflectPrvFunction*)b; + return (int)af->id - (int)bf->id; +} + +static SpvReflectResult ParseFunctions(SpvReflectPrvParser* p_parser) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(IsNotNull(p_parser->nodes)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + if (p_parser->function_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_parser->functions = (SpvReflectPrvFunction*)calloc(p_parser->function_count, sizeof(*(p_parser->functions))); + if (IsNull(p_parser->functions)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + size_t function_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op != SpvOpFunction) { + continue; + } + + // Skip over function declarations that aren't definitions + bool func_definition = false; + for (size_t j = i; j < p_parser->node_count; ++j) { + if (p_parser->nodes[j].op == SpvOpLabel) { + func_definition = true; + break; + } + if (p_parser->nodes[j].op == SpvOpFunctionEnd) { + break; + } + } + if (!func_definition) { + continue; + } + + SpvReflectPrvFunction* p_function = &(p_parser->functions[function_index]); + + SpvReflectResult result = ParseFunction(p_parser, p_node, p_function, i); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + ++function_index; + } + + qsort(p_parser->functions, p_parser->function_count, sizeof(*(p_parser->functions)), SortCompareFunctions); + + // Once they're sorted, link the functions with pointers to improve graph + // traversal efficiency + for (size_t i = 0; i < p_parser->function_count; ++i) { + SpvReflectPrvFunction* p_func = &(p_parser->functions[i]); + if (p_func->callee_count == 0) { + continue; + } + p_func->callee_ptrs = (SpvReflectPrvFunction**)calloc(p_func->callee_count, sizeof(*(p_func->callee_ptrs))); + for (size_t j = 0, k = 0; j < p_func->callee_count; ++j) { + while (p_parser->functions[k].id != p_func->callees[j]) { + ++k; + if (k >= p_parser->function_count) { + // Invalid called function ID somewhere + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + p_func->callee_ptrs[j] = &(p_parser->functions[k]); + } + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseMemberCounts(SpvReflectPrvParser* p_parser) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(IsNotNull(p_parser->nodes)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpMemberName) && (p_node->op != SpvOpMemberDecorate)) { + continue; + } + + uint32_t target_id = 0; + uint32_t member_index = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id); + CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index); + SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id); + // Not all nodes get parsed, so FindNode returning NULL is expected. + if (IsNull(p_target_node)) { + continue; + } + + if (member_index == (uint32_t)INVALID_VALUE) { + return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; + } + + p_target_node->member_count = Max(p_target_node->member_count, member_index + 1); + } + + for (uint32_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->member_count == 0) { + continue; + } + + p_node->member_names = (const char**)calloc(p_node->member_count, sizeof(*(p_node->member_names))); + if (IsNull(p_node->member_names)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + p_node->member_decorations = (SpvReflectPrvDecorations*)calloc(p_node->member_count, sizeof(*(p_node->member_decorations))); + if (IsNull(p_node->member_decorations)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseNames(SpvReflectPrvParser* p_parser) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->spirv_code)); + assert(IsNotNull(p_parser->nodes)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpName) && (p_node->op != SpvOpMemberName)) { + continue; + } + + uint32_t target_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id); + SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id); + // Not all nodes get parsed, so FindNode returning NULL is expected. + if (IsNull(p_target_node)) { + continue; + } + + const char** pp_target_name = &(p_target_node->name); + if (p_node->op == SpvOpMemberName) { + uint32_t member_index = UINT32_MAX; + CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index); + pp_target_name = &(p_target_node->member_names[member_index]); + } + + *pp_target_name = p_node->name; + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +// Returns true if user_type matches pattern or if user_type begins with pattern and the next character is ':' +// For example, UserTypeMatches("rwbuffer", "rwbuffer") will be true, UserTypeMatches("rwbuffer", "rwbuffer:") will be true, and +// UserTypeMatches("rwbuffer", "rwbufferfoo") will be false. +static bool UserTypeMatches(const char* user_type, const char* pattern) { + const size_t pattern_length = strlen(pattern); + if (strncmp(user_type, pattern, pattern_length) == 0) { + if (user_type[pattern_length] == ':' || user_type[pattern_length] == '\0') { + return true; + } + } + return false; +} + +static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser) { + uint32_t spec_constant_count = 0; + for (uint32_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + + if ((p_node->op != SpvOpDecorate) && (p_node->op != SpvOpMemberDecorate) && (p_node->op != SpvOpDecorateId) && + (p_node->op != SpvOpDecorateString) && (p_node->op != SpvOpMemberDecorateString)) { + continue; + } + + // Need to adjust the read offset if this is a member decoration + uint32_t member_offset = 0; + if (p_node->op == SpvOpMemberDecorate) { + member_offset = 1; + } + + // Get decoration + uint32_t decoration = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + member_offset + 2, decoration); + + // Filter out the decoration that do not affect reflection, otherwise + // there will be random crashes because the nodes aren't found. + bool skip = false; + switch (decoration) { + default: { + skip = true; + } break; + case SpvDecorationRelaxedPrecision: + case SpvDecorationBlock: + case SpvDecorationBufferBlock: + case SpvDecorationColMajor: + case SpvDecorationRowMajor: + case SpvDecorationArrayStride: + case SpvDecorationMatrixStride: + case SpvDecorationBuiltIn: + case SpvDecorationNoPerspective: + case SpvDecorationFlat: + case SpvDecorationNonWritable: + case SpvDecorationNonReadable: + case SpvDecorationPatch: + case SpvDecorationPerVertexKHR: + case SpvDecorationPerTaskNV: + case SpvDecorationLocation: + case SpvDecorationComponent: + case SpvDecorationBinding: + case SpvDecorationDescriptorSet: + case SpvDecorationOffset: + case SpvDecorationInputAttachmentIndex: + case SpvDecorationSpecId: + case SpvDecorationWeightTextureQCOM: + case SpvDecorationBlockMatchTextureQCOM: + case SpvDecorationUserTypeGOOGLE: + case SpvDecorationHlslCounterBufferGOOGLE: + case SpvDecorationHlslSemanticGOOGLE: { + skip = false; + } break; + } + if (skip) { + continue; + } + + // Find target node + uint32_t target_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id); + SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id); + if (IsNull(p_target_node)) { + if ((p_node->op == (uint32_t)SpvOpDecorate) && (decoration == SpvDecorationRelaxedPrecision)) { + // Many OPs can be decorated that we don't care about. Ignore those. + // See https://github.com/KhronosGroup/SPIRV-Reflect/issues/134 + continue; + } + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Get decorations + SpvReflectPrvDecorations* p_target_decorations = &(p_target_node->decorations); + // Update pointer if this is a member decoration + if (p_node->op == SpvOpMemberDecorate) { + uint32_t member_index = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index); + p_target_decorations = &(p_target_node->member_decorations[member_index]); + } + + switch (decoration) { + default: + break; + + case SpvDecorationRelaxedPrecision: { + p_target_decorations->is_relaxed_precision = true; + } break; + + case SpvDecorationBlock: { + p_target_decorations->is_block = true; + } break; + + case SpvDecorationBufferBlock: { + p_target_decorations->is_buffer_block = true; + } break; + + case SpvDecorationColMajor: { + p_target_decorations->is_column_major = true; + } break; + + case SpvDecorationRowMajor: { + p_target_decorations->is_row_major = true; + } break; + + case SpvDecorationArrayStride: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->array_stride); + } break; + + case SpvDecorationMatrixStride: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->matrix_stride); + } break; + + case SpvDecorationBuiltIn: { + p_target_decorations->is_built_in = true; + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32_CAST(p_parser, word_offset, SpvBuiltIn, p_target_decorations->built_in); + } break; + + case SpvDecorationNoPerspective: { + p_target_decorations->is_noperspective = true; + } break; + + case SpvDecorationFlat: { + p_target_decorations->is_flat = true; + } break; + + case SpvDecorationNonWritable: { + p_target_decorations->is_non_writable = true; + } break; + + case SpvDecorationNonReadable: { + p_target_decorations->is_non_readable = true; + } break; + + case SpvDecorationPatch: { + p_target_decorations->is_patch = true; + } break; + + case SpvDecorationPerVertexKHR: { + p_target_decorations->is_per_vertex = true; + } break; + + case SpvDecorationPerTaskNV: { + p_target_decorations->is_per_task = true; + } break; + + case SpvDecorationLocation: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value); + p_target_decorations->location.word_offset = word_offset; + } break; + + case SpvDecorationComponent: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->component.value); + p_target_decorations->component.word_offset = word_offset; + } break; + + case SpvDecorationBinding: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->binding.value); + p_target_decorations->binding.word_offset = word_offset; + } break; + + case SpvDecorationDescriptorSet: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->set.value); + p_target_decorations->set.word_offset = word_offset; + } break; + + case SpvDecorationOffset: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->offset.value); + p_target_decorations->offset.word_offset = word_offset; + } break; + + case SpvDecorationInputAttachmentIndex: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->input_attachment_index.value); + p_target_decorations->input_attachment_index.word_offset = word_offset; + } break; + + case SpvDecorationSpecId: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->spec_id); + spec_constant_count++; + } break; + + case SpvDecorationHlslCounterBufferGOOGLE: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value); + p_target_decorations->uav_counter_buffer.word_offset = word_offset; + } break; + + case SpvDecorationHlslSemanticGOOGLE: { + uint32_t word_offset = p_node->word_offset + member_offset + 3; + p_target_decorations->semantic.value = (const char*)(p_parser->spirv_code + word_offset); + p_target_decorations->semantic.word_offset = word_offset; + } break; + + case SpvDecorationWeightTextureQCOM: { + p_target_decorations->is_weight_texture = true; + } break; + + case SpvDecorationBlockMatchTextureQCOM: { + p_target_decorations->is_block_match_texture = true; + } break; + } + + if (p_node->op == SpvOpDecorateString && decoration == SpvDecorationUserTypeGOOGLE) { + uint32_t terminator = 0; + SpvReflectResult result = ReadStr(p_parser, p_node->word_offset + 3, 0, p_node->word_count, &terminator, NULL); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + const char* name = (const char*)(p_parser->spirv_code + p_node->word_offset + 3); + if (UserTypeMatches(name, "cbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CBUFFER; + } else if (UserTypeMatches(name, "tbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TBUFFER; + } else if (UserTypeMatches(name, "appendstructuredbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_APPEND_STRUCTURED_BUFFER; + } else if (UserTypeMatches(name, "buffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_BUFFER; + } else if (UserTypeMatches(name, "byteaddressbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER; + } else if (UserTypeMatches(name, "constantbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CONSTANT_BUFFER; + } else if (UserTypeMatches(name, "consumestructuredbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CONSUME_STRUCTURED_BUFFER; + } else if (UserTypeMatches(name, "inputpatch")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_INPUT_PATCH; + } else if (UserTypeMatches(name, "outputpatch")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_OUTPUT_PATCH; + } else if (UserTypeMatches(name, "rasterizerorderedbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BUFFER; + } else if (UserTypeMatches(name, "rasterizerorderedbyteaddressbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BYTE_ADDRESS_BUFFER; + } else if (UserTypeMatches(name, "rasterizerorderedstructuredbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_STRUCTURED_BUFFER; + } else if (UserTypeMatches(name, "rasterizerorderedtexture1d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D; + } else if (UserTypeMatches(name, "rasterizerorderedtexture1darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D_ARRAY; + } else if (UserTypeMatches(name, "rasterizerorderedtexture2d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D; + } else if (UserTypeMatches(name, "rasterizerorderedtexture2darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D_ARRAY; + } else if (UserTypeMatches(name, "rasterizerorderedtexture3d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_3D; + } else if (UserTypeMatches(name, "raytracingaccelerationstructure")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RAYTRACING_ACCELERATION_STRUCTURE; + } else if (UserTypeMatches(name, "rwbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_BUFFER; + } else if (UserTypeMatches(name, "rwbyteaddressbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER; + } else if (UserTypeMatches(name, "rwstructuredbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_STRUCTURED_BUFFER; + } else if (UserTypeMatches(name, "rwtexture1d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D; + } else if (UserTypeMatches(name, "rwtexture1darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D_ARRAY; + } else if (UserTypeMatches(name, "rwtexture2d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D; + } else if (UserTypeMatches(name, "rwtexture2darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D_ARRAY; + } else if (UserTypeMatches(name, "rwtexture3d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_3D; + } else if (UserTypeMatches(name, "structuredbuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_STRUCTURED_BUFFER; + } else if (UserTypeMatches(name, "subpassinput")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_SUBPASS_INPUT; + } else if (UserTypeMatches(name, "subpassinputms")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_SUBPASS_INPUT_MS; + } else if (UserTypeMatches(name, "texture1d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_1D; + } else if (UserTypeMatches(name, "texture1darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_1D_ARRAY; + } else if (UserTypeMatches(name, "texture2d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2D; + } else if (UserTypeMatches(name, "texture2darray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2D_ARRAY; + } else if (UserTypeMatches(name, "texture2dms")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2DMS; + } else if (UserTypeMatches(name, "texture2dmsarray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2DMS_ARRAY; + } else if (UserTypeMatches(name, "texture3d")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_3D; + } else if (UserTypeMatches(name, "texturebuffer")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_BUFFER; + } else if (UserTypeMatches(name, "texturecube")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_CUBE; + } else if (UserTypeMatches(name, "texturecubearray")) { + p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_CUBE_ARRAY; + } + } + } + + p_parser->spec_constant_count = spec_constant_count; + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult EnumerateAllUniforms(SpvReflectShaderModule* p_module, size_t* p_uniform_count, uint32_t** pp_uniforms) { + *p_uniform_count = p_module->descriptor_binding_count; + if (*p_uniform_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + *pp_uniforms = (uint32_t*)calloc(*p_uniform_count, sizeof(**pp_uniforms)); + + if (IsNull(*pp_uniforms)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + for (size_t i = 0; i < *p_uniform_count; ++i) { + (*pp_uniforms)[i] = p_module->descriptor_bindings[i].spirv_id; + } + qsort(*pp_uniforms, *p_uniform_count, sizeof(**pp_uniforms), SortCompareUint32); + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseType(SpvReflectPrvParser* p_parser, SpvReflectPrvNode* p_node, + SpvReflectPrvDecorations* p_struct_member_decorations, SpvReflectShaderModule* p_module, + SpvReflectTypeDescription* p_type) { + SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; + + if (p_node->member_count > 0) { + p_type->struct_type_description = FindType(p_module, p_node->result_id); + p_type->member_count = p_node->member_count; + p_type->members = (SpvReflectTypeDescription*)calloc(p_type->member_count, sizeof(*(p_type->members))); + if (IsNotNull(p_type->members)) { + // Mark all members types with an invalid state + for (size_t i = 0; i < p_type->members->member_count; ++i) { + SpvReflectTypeDescription* p_member_type = &(p_type->members[i]); + p_member_type->id = (uint32_t)INVALID_VALUE; + p_member_type->op = (SpvOp)INVALID_VALUE; + p_member_type->storage_class = INVALID_VALUE; + } + } else { + result = SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (result == SPV_REFLECT_RESULT_SUCCESS) { + // Since the parse descends on type information, these will get overwritten + // if not guarded against assignment. Only assign if the id is invalid. + if (p_type->id == (uint32_t)INVALID_VALUE) { + p_type->id = p_node->result_id; + p_type->op = p_node->op; + p_type->decoration_flags = 0; + } + // Top level types need to pick up decorations from all types below it. + // Issue and fix here: https://github.com/chaoticbob/SPIRV-Reflect/issues/64 + p_type->decoration_flags = ApplyDecorations(&p_node->decorations); + + switch (p_node->op) { + default: + break; + case SpvOpTypeVoid: + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VOID; + break; + + case SpvOpTypeBool: + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_BOOL; + break; + + case SpvOpTypeInt: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_INT; + IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width); + IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.scalar.signedness); + } break; + + case SpvOpTypeFloat: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_FLOAT; + IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width); + } break; + + case SpvOpTypeVector: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VECTOR; + uint32_t component_type_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, component_type_id); + IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.vector.component_count); + // Parse component type + SpvReflectPrvNode* p_next_node = FindNode(p_parser, component_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + } break; + + case SpvOpTypeMatrix: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_MATRIX; + uint32_t column_type_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, column_type_id); + IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.matrix.column_count); + SpvReflectPrvNode* p_next_node = FindNode(p_parser, column_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + p_type->traits.numeric.matrix.row_count = p_type->traits.numeric.vector.component_count; + p_type->traits.numeric.matrix.stride = p_node->decorations.matrix_stride; + // NOTE: Matrix stride is decorated using OpMemberDecoreate - not OpDecoreate. + if (IsNotNull(p_struct_member_decorations)) { + p_type->traits.numeric.matrix.stride = p_struct_member_decorations->matrix_stride; + } + } break; + + case SpvOpTypeImage: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE; + uint32_t sampled_type_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, sampled_type_id); + SpvReflectPrvNode* p_next_node = FindNode(p_parser, sampled_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + IF_READU32_CAST(result, p_parser, p_node->word_offset + 3, SpvDim, p_type->traits.image.dim); + IF_READU32(result, p_parser, p_node->word_offset + 4, p_type->traits.image.depth); + IF_READU32(result, p_parser, p_node->word_offset + 5, p_type->traits.image.arrayed); + IF_READU32(result, p_parser, p_node->word_offset + 6, p_type->traits.image.ms); + IF_READU32(result, p_parser, p_node->word_offset + 7, p_type->traits.image.sampled); + IF_READU32_CAST(result, p_parser, p_node->word_offset + 8, SpvImageFormat, p_type->traits.image.image_format); + } break; + + case SpvOpTypeSampler: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER; + } break; + + case SpvOpTypeSampledImage: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE; + uint32_t image_type_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, image_type_id); + SpvReflectPrvNode* p_next_node = FindNode(p_parser, image_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + } break; + + case SpvOpTypeArray: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_ARRAY; + if (result == SPV_REFLECT_RESULT_SUCCESS) { + uint32_t element_type_id = (uint32_t)INVALID_VALUE; + uint32_t length_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id); + IF_READU32(result, p_parser, p_node->word_offset + 3, length_id); + // NOTE: Array stride is decorated using OpDecorate instead of + // OpMemberDecorate, even if the array is apart of a struct. + p_type->traits.array.stride = p_node->decorations.array_stride; + // Get length for current dimension + SpvReflectPrvNode* p_length_node = FindNode(p_parser, length_id); + if (IsNotNull(p_length_node)) { + uint32_t dim_index = p_type->traits.array.dims_count; + uint32_t length = 0; + IF_READU32(result, p_parser, p_length_node->word_offset + 3, length); + if (result == SPV_REFLECT_RESULT_SUCCESS) { + p_type->traits.array.dims[dim_index] = length; + p_type->traits.array.dims_count += 1; + p_type->traits.array.spec_constant_op_ids[dim_index] = + IsSpecConstant(p_length_node) ? p_length_node->decorations.spec_id : (uint32_t)INVALID_VALUE; + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + // Parse next dimension or element type + SpvReflectPrvNode* p_next_node = FindNode(p_parser, element_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + } + } break; + + case SpvOpTypeRuntimeArray: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_ARRAY; + uint32_t element_type_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id); + p_type->traits.array.stride = p_node->decorations.array_stride; + uint32_t dim_index = p_type->traits.array.dims_count; + p_type->traits.array.dims[dim_index] = (uint32_t)SPV_REFLECT_ARRAY_DIM_RUNTIME; + p_type->traits.array.spec_constant_op_ids[dim_index] = (uint32_t)INVALID_VALUE; + p_type->traits.array.dims_count += 1; + // Parse next dimension or element type + SpvReflectPrvNode* p_next_node = FindNode(p_parser, element_type_id); + if (IsNotNull(p_next_node)) { + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } else { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + } + } break; + + case SpvOpTypeStruct: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_STRUCT; + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK; + uint32_t word_index = 2; + uint32_t member_index = 0; + for (; word_index < p_node->word_count; ++word_index, ++member_index) { + uint32_t member_id = (uint32_t)INVALID_VALUE; + IF_READU32(result, p_parser, p_node->word_offset + word_index, member_id); + // Find member node + SpvReflectPrvNode* p_member_node = FindNode(p_parser, member_id); + if (IsNull(p_member_node)) { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + break; + } + + // Member decorations + SpvReflectPrvDecorations* p_member_decorations = &p_node->member_decorations[member_index]; + + assert(member_index < p_type->member_count); + // Parse member type + SpvReflectTypeDescription* p_member_type = &(p_type->members[member_index]); + p_member_type->id = member_id; + p_member_type->op = p_member_node->op; + result = ParseType(p_parser, p_member_node, p_member_decorations, p_module, p_member_type); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + break; + } + // This looks wrong + // p_member_type->type_name = p_member_node->name; + p_member_type->struct_member_name = p_node->member_names[member_index]; + } + } break; + + case SpvOpTypeOpaque: + break; + + case SpvOpTypePointer: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_REF; + IF_READU32_CAST(result, p_parser, p_node->word_offset + 2, SpvStorageClass, p_type->storage_class); + + SpvReflectPrvNode* p_next_node = FindNode(p_parser, p_node->type_id); + if (IsNull(p_next_node)) { + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); + break; + } + + bool found_recursion = false; + if (p_type->storage_class == SpvStorageClassPhysicalStorageBuffer) { + // Need to make sure we haven't started an infinite recursive loop + for (uint32_t i = 0; i < p_parser->physical_pointer_count; i++) { + if (p_type->id == p_parser->physical_pointer_check[i]->id) { + found_recursion = true; + memcpy(p_type, p_parser->physical_pointer_check[i], sizeof(SpvReflectTypeDescription)); + p_type->copied = 1; + return SPV_REFLECT_RESULT_SUCCESS; + } + } + if (!found_recursion && p_next_node->op == SpvOpTypeStruct) { + p_parser->physical_pointer_struct_count++; + p_parser->physical_pointer_check[p_parser->physical_pointer_count] = p_type; + p_parser->physical_pointer_count++; + if (p_parser->physical_pointer_count >= MAX_RECURSIVE_PHYSICAL_POINTER_CHECK) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED; + } + } + } + + if (!found_recursion) { + if (p_next_node->op == SpvOpTypeStruct) { + p_type->struct_type_description = FindType(p_module, p_next_node->result_id); + } + + result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); + } + } break; + + case SpvOpTypeAccelerationStructureKHR: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE; + } break; + } + + if (result == SPV_REFLECT_RESULT_SUCCESS) { + // Names get assigned on the way down. Guard against names + // get overwritten on the way up. + if (IsNull(p_type->type_name)) { + p_type->type_name = p_node->name; + } + } + } + + return result; +} + +static SpvReflectResult ParseTypes(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + if (p_parser->type_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->_internal->type_description_count = p_parser->type_count; + p_module->_internal->type_descriptions = (SpvReflectTypeDescription*)calloc(p_module->_internal->type_description_count, + sizeof(*(p_module->_internal->type_descriptions))); + if (IsNull(p_module->_internal->type_descriptions)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + // Mark all types with an invalid state + for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) { + SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[i]); + p_type->id = (uint32_t)INVALID_VALUE; + p_type->op = (SpvOp)INVALID_VALUE; + p_type->storage_class = INVALID_VALUE; + } + + size_t type_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (!p_node->is_type) { + continue; + } + + SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[type_index]); + p_parser->physical_pointer_count = 0; + SpvReflectResult result = ParseType(p_parser, p_node, NULL, p_module, p_type); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + ++type_index; + } + + // allocate now and fill in when parsing struct variable later + if (p_parser->physical_pointer_struct_count > 0) { + p_parser->physical_pointer_structs = (SpvReflectPrvPhysicalPointerStruct*)calloc(p_parser->physical_pointer_struct_count, + sizeof(*(p_parser->physical_pointer_structs))); + if (IsNull(p_parser->physical_pointer_structs)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseCapabilities(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + if (p_parser->capability_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->capability_count = p_parser->capability_count; + p_module->capabilities = (SpvReflectCapability*)calloc(p_module->capability_count, sizeof(*(p_module->capabilities))); + if (IsNull(p_module->capabilities)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + // Mark all types with an invalid state + for (size_t i = 0; i < p_module->capability_count; ++i) { + SpvReflectCapability* p_cap = &(p_module->capabilities[i]); + p_cap->value = SpvCapabilityMax; + p_cap->word_offset = (uint32_t)INVALID_VALUE; + } + + size_t capability_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (SpvOpCapability != p_node->op) { + continue; + } + + SpvReflectCapability* p_cap = &(p_module->capabilities[capability_index]); + p_cap->value = p_node->capability; + p_cap->word_offset = p_node->word_offset + 1; + ++capability_index; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static int SortCompareDescriptorBinding(const void* a, const void* b) { + const SpvReflectDescriptorBinding* p_elem_a = (const SpvReflectDescriptorBinding*)a; + const SpvReflectDescriptorBinding* p_elem_b = (const SpvReflectDescriptorBinding*)b; + int value = (int)(p_elem_a->binding) - (int)(p_elem_b->binding); + if (value == 0) { + // use spirv-id as a tiebreaker to ensure a stable ordering, as they're guaranteed + // unique. + assert(p_elem_a->spirv_id != p_elem_b->spirv_id); + value = (int)(p_elem_a->spirv_id) - (int)(p_elem_b->spirv_id); + } + return value; +} + +static SpvReflectResult ParseDescriptorBindings(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + p_module->descriptor_binding_count = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpVariable) || + ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassStorageBuffer) && + (p_node->storage_class != SpvStorageClassUniformConstant))) { + continue; + } + if ((p_node->decorations.set.value == (uint32_t)INVALID_VALUE) || (p_node->decorations.binding.value == (uint32_t)INVALID_VALUE)) { + continue; + } + + p_module->descriptor_binding_count += 1; + } + + if (p_module->descriptor_binding_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->descriptor_bindings = + (SpvReflectDescriptorBinding*)calloc(p_module->descriptor_binding_count, sizeof(*(p_module->descriptor_bindings))); + if (IsNull(p_module->descriptor_bindings)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + // Mark all types with an invalid state + for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); + p_descriptor->binding = (uint32_t)INVALID_VALUE; + p_descriptor->input_attachment_index = (uint32_t)INVALID_VALUE; + p_descriptor->set = (uint32_t)INVALID_VALUE; + p_descriptor->descriptor_type = (SpvReflectDescriptorType)INVALID_VALUE; + p_descriptor->uav_counter_id = (uint32_t)INVALID_VALUE; + } + + size_t descriptor_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpVariable) || + ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassStorageBuffer) && + (p_node->storage_class != SpvStorageClassUniformConstant))) { + continue; + } + if ((p_node->decorations.set.value == (uint32_t)INVALID_VALUE) || (p_node->decorations.binding.value == (uint32_t)INVALID_VALUE)) { + continue; + } + + SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id); + if (IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // If the type is a pointer, resolve it. We need to retain the storage class + // from the pointer so that we can use it to deduce deescriptor types. + SpvStorageClass pointer_storage_class = SpvStorageClassMax; + if (p_type->op == SpvOpTypePointer) { + assert(p_type->storage_class != -1 && "Pointer types must have a valid storage class."); + pointer_storage_class = (SpvStorageClass)p_type->storage_class; + // Find the type's node + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Should be the resolved type + p_type = FindType(p_module, p_type_node->type_id); + if (IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + + SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[descriptor_index]; + p_descriptor->spirv_id = p_node->result_id; + p_descriptor->name = p_node->name; + p_descriptor->binding = p_node->decorations.binding.value; + p_descriptor->input_attachment_index = p_node->decorations.input_attachment_index.value; + p_descriptor->set = p_node->decorations.set.value; + p_descriptor->count = 1; + p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value; + p_descriptor->type_description = p_type; + p_descriptor->decoration_flags = ApplyDecorations(&p_node->decorations); + p_descriptor->user_type = p_node->decorations.user_type; + + // Flags like non-writable and non-readable are found as member decorations only. + // If all members have one of those decorations set, promote the decoration up + // to the whole descriptor. + const SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNotNull(p_type_node) && p_type_node->member_count) { + SpvReflectPrvDecorations common_flags = p_type_node->member_decorations[0]; + + for (uint32_t m = 1; m < p_type_node->member_count; ++m) { + common_flags.is_relaxed_precision &= p_type_node->member_decorations[m].is_relaxed_precision; + common_flags.is_block &= p_type_node->member_decorations[m].is_block; + common_flags.is_buffer_block &= p_type_node->member_decorations[m].is_buffer_block; + common_flags.is_row_major &= p_type_node->member_decorations[m].is_row_major; + common_flags.is_column_major &= p_type_node->member_decorations[m].is_column_major; + common_flags.is_built_in &= p_type_node->member_decorations[m].is_built_in; + common_flags.is_noperspective &= p_type_node->member_decorations[m].is_noperspective; + common_flags.is_flat &= p_type_node->member_decorations[m].is_flat; + common_flags.is_non_writable &= p_type_node->member_decorations[m].is_non_writable; + common_flags.is_non_readable &= p_type_node->member_decorations[m].is_non_readable; + common_flags.is_patch &= p_type_node->member_decorations[m].is_patch; + common_flags.is_per_vertex &= p_type_node->member_decorations[m].is_per_vertex; + common_flags.is_per_task &= p_type_node->member_decorations[m].is_per_task; + common_flags.is_weight_texture &= p_type_node->member_decorations[m].is_weight_texture; + common_flags.is_block_match_texture &= p_type_node->member_decorations[m].is_block_match_texture; + } + + p_descriptor->decoration_flags |= ApplyDecorations(&common_flags); + } + + // If this is in the StorageBuffer storage class, it's for sure a storage + // buffer descriptor. We need to handle this case earlier because in SPIR-V + // there are two ways to indicate a storage buffer: + // 1) Uniform storage class + BufferBlock decoration, or + // 2) StorageBuffer storage class + Buffer decoration. + // The 1) way is deprecated since SPIR-V v1.3. But the Buffer decoration is + // also used together with Uniform storage class to mean uniform buffer.. + // We'll handle the pre-v1.3 cases in ParseDescriptorType(). + if (pointer_storage_class == SpvStorageClassStorageBuffer) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER; + } + + // Copy image traits + if ((p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) == SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE) { + memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image)); + } + + // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096 + { + const uint32_t resource_mask = SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE; + if ((p_type->type_flags & resource_mask) == resource_mask) { + memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image)); + } + } + + // Copy array traits + if (p_type->traits.array.dims_count > 0) { + p_descriptor->array.dims_count = p_type->traits.array.dims_count; + for (uint32_t dim_index = 0; dim_index < p_type->traits.array.dims_count; ++dim_index) { + uint32_t dim_value = p_type->traits.array.dims[dim_index]; + p_descriptor->array.dims[dim_index] = dim_value; + p_descriptor->count *= dim_value; + } + } + + // Count + + p_descriptor->word_offset.binding = p_node->decorations.binding.word_offset; + p_descriptor->word_offset.set = p_node->decorations.set.word_offset; + + ++descriptor_index; + } + + if (p_module->descriptor_binding_count > 0) { + qsort(p_module->descriptor_bindings, p_module->descriptor_binding_count, sizeof(*(p_module->descriptor_bindings)), + SortCompareDescriptorBinding); + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseDescriptorType(SpvReflectShaderModule* p_module) { + if (p_module->descriptor_binding_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); + SpvReflectTypeDescription* p_type = p_descriptor->type_description; + + if ((int)p_descriptor->descriptor_type == (int)INVALID_VALUE) { + switch (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) { + default: + assert(false && "unknown type flag"); + break; + + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE: { + if (p_descriptor->image.dim == SpvDimBuffer) { + switch (p_descriptor->image.sampled) { + default: + assert(false && "unknown texel buffer sampled value"); + break; + case IMAGE_SAMPLED: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + break; + case IMAGE_STORAGE: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + break; + } + } else if (p_descriptor->image.dim == SpvDimSubpassData) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + } else { + switch (p_descriptor->image.sampled) { + default: + assert(false && "unknown image sampled value"); + break; + case IMAGE_SAMPLED: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + break; + case IMAGE_STORAGE: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE; + break; + } + } + } break; + + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER: { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER; + } break; + + case (SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE): { + // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096 + if (p_descriptor->image.dim == SpvDimBuffer) { + switch (p_descriptor->image.sampled) { + default: + assert(false && "unknown texel buffer sampled value"); + break; + case IMAGE_SAMPLED: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + break; + case IMAGE_STORAGE: + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + break; + } + } else { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + } + } break; + + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK: { + if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BLOCK) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + } else if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BUFFER_BLOCK) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER; + } else { + assert(false && "unknown struct"); + } + } break; + + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE: { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + } break; + } + } + + switch (p_descriptor->descriptor_type) { + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SAMPLER; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + p_descriptor->resource_type = (SpvReflectResourceType)(SPV_REFLECT_RESOURCE_FLAG_SAMPLER | SPV_REFLECT_RESOURCE_FLAG_SRV); + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + break; + case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; + break; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseUAVCounterBindings(SpvReflectShaderModule* p_module) { + char name[MAX_NODE_NAME_LENGTH]; + const char* k_count_tag = "@count"; + + for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); + + if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + continue; + } + + SpvReflectDescriptorBinding* p_counter_descriptor = NULL; + // Use UAV counter buffer id if present... + if (p_descriptor->uav_counter_id != UINT32_MAX) { + for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; + ++counter_descriptor_index) { + SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]); + if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + continue; + } + if (p_descriptor->uav_counter_id == p_test_counter_descriptor->spirv_id) { + p_counter_descriptor = p_test_counter_descriptor; + break; + } + } + } + // ...otherwise use old @count convention. + else { + const size_t descriptor_name_length = p_descriptor->name ? strlen(p_descriptor->name) : 0; + + memset(name, 0, MAX_NODE_NAME_LENGTH); + memcpy(name, p_descriptor->name, descriptor_name_length); +#if defined(_WIN32) + strcat_s(name, MAX_NODE_NAME_LENGTH, k_count_tag); +#else + strcat(name, k_count_tag); +#endif + + for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; + ++counter_descriptor_index) { + SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]); + if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + continue; + } + if (p_test_counter_descriptor->name && strcmp(name, p_test_counter_descriptor->name) == 0) { + p_counter_descriptor = p_test_counter_descriptor; + break; + } + } + } + + if (p_counter_descriptor != NULL) { + p_descriptor->uav_counter_binding = p_counter_descriptor; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseDescriptorBlockVariable(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module, + SpvReflectTypeDescription* p_type, SpvReflectBlockVariable* p_var) { + bool has_non_writable = false; + + if (IsNotNull(p_type->members) && (p_type->member_count > 0)) { + p_var->member_count = p_type->member_count; + p_var->members = (SpvReflectBlockVariable*)calloc(p_var->member_count, sizeof(*p_var->members)); + if (IsNull(p_var->members)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Resolve to element type if current type is array or run time array + while (p_type_node->op == SpvOpTypeArray || p_type_node->op == SpvOpTypeRuntimeArray) { + if (p_type_node->op == SpvOpTypeArray) { + p_type_node = FindNode(p_parser, p_type_node->array_traits.element_type_id); + } else { + // Element type description + SpvReflectTypeDescription* p_type_temp = FindType(p_module, p_type_node->array_traits.element_type_id); + if (IsNull(p_type_temp)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Element type node + p_type_node = FindNode(p_parser, p_type_temp->id); + } + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + + // Parse members + for (uint32_t member_index = 0; member_index < p_type->member_count; ++member_index) { + SpvReflectTypeDescription* p_member_type = &p_type->members[member_index]; + SpvReflectBlockVariable* p_member_var = &p_var->members[member_index]; + // If pointer type, treat like reference and resolve to pointee type + SpvReflectTypeDescription* p_member_ptr_type = 0; + bool found_recursion = false; + + if ((p_member_type->storage_class == SpvStorageClassPhysicalStorageBuffer) && + (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_REF)) { + // Remember the original type + p_member_ptr_type = p_member_type; + + // strip array + if (p_member_type->op == SpvOpTypeArray || p_member_type->op == SpvOpTypeRuntimeArray) { + SpvReflectPrvNode* p_node = FindNode(p_parser, p_member_type->id); + if (p_node == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + uint32_t element_type_id = p_node->array_traits.element_type_id; + p_member_type = FindType(p_module, element_type_id); + if (p_member_type == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + + // Need to make sure we haven't started an infinite recursive loop + for (uint32_t i = 0; i < p_parser->physical_pointer_count; i++) { + if (p_member_type->id == p_parser->physical_pointer_check[i]->id) { + found_recursion = true; + break; // still need to fill in p_member_type values + } + } + if (!found_recursion) { + SpvReflectTypeDescription* struct_type = FindType(p_module, p_member_type->id); + // could be pointer directly to non-struct type here + if (struct_type->struct_type_description) { + uint32_t struct_id = struct_type->struct_type_description->id; + p_parser->physical_pointer_structs[p_parser->physical_pointer_struct_count].struct_id = struct_id; + p_parser->physical_pointer_structs[p_parser->physical_pointer_struct_count].p_var = p_member_var; + p_parser->physical_pointer_struct_count++; + + p_parser->physical_pointer_check[p_parser->physical_pointer_count] = p_member_type; + p_parser->physical_pointer_count++; + if (p_parser->physical_pointer_count >= MAX_RECURSIVE_PHYSICAL_POINTER_CHECK) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED; + } + } + } + + SpvReflectPrvNode* p_member_type_node = FindNode(p_parser, p_member_type->id); + if (IsNull(p_member_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Should be the pointee type + p_member_type = FindType(p_module, p_member_type_node->type_id); + if (IsNull(p_member_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT; + if (is_struct) { + if (!found_recursion) { + SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_member_type, p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } else { + // if 2 member of structs are same PhysicalPointer type, copy the + // members values that aren't found skipping the recursion call + for (uint32_t i = 0; i < p_parser->physical_pointer_struct_count; i++) { + if (p_parser->physical_pointer_structs[i].struct_id == p_member_type->id) { + p_member_var->members = p_parser->physical_pointer_structs[i].p_var->members; + p_member_var->member_count = p_parser->physical_pointer_structs[i].p_var->member_count; + // Set here as it is the first time we need to walk down structs + p_member_var->flags |= SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY; + } + } + } + } + + if (p_type_node->storage_class == SpvStorageClassPhysicalStorageBuffer && !p_type_node->member_names) { + // TODO 212 - If a buffer ref has an array of itself, all members are null + continue; + } + + p_member_var->name = p_type_node->member_names[member_index]; + p_member_var->offset = p_type_node->member_decorations[member_index].offset.value; + p_member_var->decoration_flags = ApplyDecorations(&p_type_node->member_decorations[member_index]); + p_member_var->flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + if (!has_non_writable && (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE)) { + has_non_writable = true; + } + ApplyNumericTraits(p_member_type, &p_member_var->numeric); + if (p_member_type->op == SpvOpTypeArray) { + ApplyArrayTraits(p_member_type, &p_member_var->array); + } + + p_member_var->word_offset.offset = p_type_node->member_decorations[member_index].offset.word_offset; + p_member_var->type_description = p_member_ptr_type ? p_member_ptr_type : p_member_type; + } + } + + p_var->name = p_type->type_name; + p_var->type_description = p_type; + if (has_non_writable) { + p_var->decoration_flags |= SPV_REFLECT_DECORATION_NON_WRITABLE; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static uint32_t GetPhysicalPointerStructSize(SpvReflectPrvParser* p_parser, uint32_t id) { + for (uint32_t i = 0; i < p_parser->physical_pointer_struct_count; i++) { + if (p_parser->physical_pointer_structs[i].struct_id == id) { + return p_parser->physical_pointer_structs[i].p_var->size; + } + } + return 0; +} + +static SpvReflectResult ParseDescriptorBlockVariableSizes(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module, + bool is_parent_root, bool is_parent_aos, bool is_parent_rta, + SpvReflectBlockVariable* p_var) { + if (p_var->member_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + bool is_parent_ref = p_var->type_description->op == SpvOpTypePointer; + + // Absolute offsets + for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) { + SpvReflectBlockVariable* p_member_var = &p_var->members[member_index]; + if (is_parent_root) { + p_member_var->absolute_offset = p_member_var->offset; + } else { + p_member_var->absolute_offset = + is_parent_aos ? 0 : (is_parent_ref ? p_member_var->offset : p_member_var->offset + p_var->absolute_offset); + } + } + + // Size + for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) { + SpvReflectBlockVariable* p_member_var = &p_var->members[member_index]; + SpvReflectTypeDescription* p_member_type = p_member_var->type_description; + + if (!p_member_type) { + // TODO 212 - If a buffer ref has an array of itself, all members are null + continue; + } + switch (p_member_type->op) { + case SpvOpTypeBool: { + p_member_var->size = SPIRV_WORD_SIZE; + } break; + + case SpvOpTypeInt: + case SpvOpTypeFloat: { + p_member_var->size = p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH; + } break; + + case SpvOpTypeVector: { + uint32_t size = + p_member_type->traits.numeric.vector.component_count * (p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH); + p_member_var->size = size; + } break; + + case SpvOpTypeMatrix: { + if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_COLUMN_MAJOR) { + p_member_var->size = p_member_var->numeric.matrix.column_count * p_member_var->numeric.matrix.stride; + } else if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_ROW_MAJOR) { + p_member_var->size = p_member_var->numeric.matrix.row_count * p_member_var->numeric.matrix.stride; + } + } break; + + case SpvOpTypeArray: { + // If array of structs, parse members first... + bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT; + if (is_struct) { + if (p_member_var->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) { + p_member_var->size = GetPhysicalPointerStructSize(p_parser, p_member_type->id); + } else { + SpvReflectResult result = + ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, is_parent_rta, p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + } + // ...then array + uint32_t element_count = (p_member_var->array.dims_count > 0 ? 1 : 0); + for (uint32_t i = 0; i < p_member_var->array.dims_count; ++i) { + element_count *= p_member_var->array.dims[i]; + } + p_member_var->size = element_count * p_member_var->array.stride; + } break; + + case SpvOpTypeRuntimeArray: { + bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT; + if (is_struct) { + SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, true, p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + } break; + + case SpvOpTypePointer: { + // Reference. Get to underlying struct type. + SpvReflectPrvNode* p_member_type_node = FindNode(p_parser, p_member_type->id); + if (IsNull(p_member_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Get the pointee type + p_member_type = FindType(p_module, p_member_type_node->type_id); + if (IsNull(p_member_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + // If we found a struct, we need to fall through and get the size of it or else we grab the size here + if (p_member_type->op != SpvOpTypeStruct) { + // If we hit this, we are seeing a POD pointer and the size is fixed + p_member_var->size = SPIRV_PHYSICAL_STORAGE_POINTER_SIZE; + break; + } + FALLTHROUGH; + } + + case SpvOpTypeStruct: { + if (p_member_var->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) { + p_member_var->size = GetPhysicalPointerStructSize(p_parser, p_member_type->id); + } else { + SpvReflectResult result = + ParseDescriptorBlockVariableSizes(p_parser, p_module, false, is_parent_aos, is_parent_rta, p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + } break; + + default: + break; + } + } + + // Structs can offset order don't need to match the index order, so first order by offset + // example: + // OpMemberDecorate %struct 0 Offset 4 + // OpMemberDecorate %struct 1 Offset 0 + SpvReflectBlockVariable** pp_member_offset_order = + (SpvReflectBlockVariable**)calloc(p_var->member_count, sizeof(SpvReflectBlockVariable*)); + if (IsNull(pp_member_offset_order)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + uint32_t bottom_bound = 0; + for (uint32_t i = 0; i < p_var->member_count; ++i) { + uint32_t lowest_offset = UINT32_MAX; + uint32_t member_index = 0; + for (uint32_t j = 0; j < p_var->member_count; ++j) { + const uint32_t offset = p_var->members[j].offset; + if (offset < lowest_offset && offset >= bottom_bound) { + member_index = j; + lowest_offset = offset; + } + } + pp_member_offset_order[i] = &p_var->members[member_index]; + bottom_bound = lowest_offset + 1; // 2 index can't share the same offset + } + + // Parse padded size using offset difference for all member except for the last entry... + for (uint32_t i = 0; i < (p_var->member_count - 1); ++i) { + SpvReflectBlockVariable* p_member_var = pp_member_offset_order[i]; + SpvReflectBlockVariable* p_next_member_var = pp_member_offset_order[i + 1]; + p_member_var->padded_size = p_next_member_var->offset - p_member_var->offset; + if (p_member_var->size > p_member_var->padded_size) { + p_member_var->size = p_member_var->padded_size; + } + if (is_parent_rta) { + p_member_var->padded_size = p_member_var->size; + } + } + + // ...last entry just gets rounded up to near multiple of SPIRV_DATA_ALIGNMENT, which is 16 and + // subtract the offset. + // last entry == entry with largest offset value + SpvReflectBlockVariable* p_last_member_var = pp_member_offset_order[p_var->member_count - 1]; + p_last_member_var->padded_size = + RoundUp(p_last_member_var->offset + p_last_member_var->size, SPIRV_DATA_ALIGNMENT) - p_last_member_var->offset; + if (p_last_member_var->size > p_last_member_var->padded_size) { + p_last_member_var->size = p_last_member_var->padded_size; + } + if (is_parent_rta) { + p_last_member_var->padded_size = p_last_member_var->size; + } + + SafeFree(pp_member_offset_order); + + // If buffer ref, sizes are same as uint64_t + if (is_parent_ref) { + p_var->size = p_var->padded_size = 8; + return SPV_REFLECT_RESULT_SUCCESS; + } + + // @TODO validate this with assertion + p_var->size = p_last_member_var->offset + p_last_member_var->padded_size; + p_var->padded_size = p_var->size; + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static void MarkSelfAndAllMemberVarsAsUsed(SpvReflectBlockVariable* p_var) { + // Clear the current variable's UNUSED flag + p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + + SpvOp op_type = p_var->type_description->op; + if (op_type == SpvOpTypeStruct) { + for (uint32_t i = 0; i < p_var->member_count; ++i) { + SpvReflectBlockVariable* p_member_var = &p_var->members[i]; + MarkSelfAndAllMemberVarsAsUsed(p_member_var); + } + } +} + +static SpvReflectResult ParseDescriptorBlockVariableUsage(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module, + SpvReflectPrvAccessChain* p_access_chain, uint32_t index_index, + SpvOp override_op_type, SpvReflectBlockVariable* p_var) { + // Clear the current variable's UNUSED flag + p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + + // Parsing arrays requires overriding the op type for + // for the lowest dim's element type. + SpvReflectTypeDescription* p_type = p_var->type_description; + SpvOp op_type = p_type->op; + if (override_op_type != (SpvOp)INVALID_VALUE) { + op_type = override_op_type; + } + + switch (op_type) { + default: + break; + + case SpvOpTypeArray: { + // Parse through array's type hierarchy to find the actual/non-array element type + while ((p_type->op == SpvOpTypeArray) && (index_index < p_access_chain->index_count)) { + // Find the array element type id + SpvReflectPrvNode* p_node = FindNode(p_parser, p_type->id); + if (p_node == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + uint32_t element_type_id = p_node->array_traits.element_type_id; + // Get the array element type + p_type = FindType(p_module, element_type_id); + if (p_type == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Next access chain index + index_index += 1; + } + + // Only continue parsing if there's remaining indices in the access + // chain. If the end of the access chain has been reached then all + // remaining variables (including those in struct hierarchies) + // are considered USED. + // + // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78 + // + if (index_index < p_access_chain->index_count) { + // Parse current var again with a type override and advanced index index + SpvReflectResult result = + ParseDescriptorBlockVariableUsage(p_parser, p_module, p_access_chain, index_index, p_type->op, p_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } else { + // Clear UNUSED flag for remaining variables + MarkSelfAndAllMemberVarsAsUsed(p_var); + } + } break; + + case SpvOpTypePointer: { + // Reference. Get to underlying struct type. + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Get the pointee type + p_type = FindType(p_module, p_type_node->type_id); + if (IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + if (p_type->op != SpvOpTypeStruct) { + break; + } + FALLTHROUGH; + } + + case SpvOpTypeStruct: { + assert(p_var->member_count > 0); + if (p_var->member_count == 0) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA; + } + + // The access chain can have zero indexes, if used for a runtime array + if (p_access_chain->index_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + // Get member variable at the access's chain current index + uint32_t index = p_access_chain->indexes[index_index]; + if (index >= p_var->member_count) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE; + } + SpvReflectBlockVariable* p_member_var = &p_var->members[index]; + + bool is_pointer_to_pointer = IsPointerToPointer(p_parser, p_access_chain->result_type_id); + if (is_pointer_to_pointer) { + // Remember block var for this access chain for downstream dereference + p_access_chain->block_var = p_member_var; + } + + // Next access chain index + index_index += 1; + + // Only continue parsing if there's remaining indices in the access + // chain. If the end of the access chain has been reach then all + // remaining variables (including those in struct hierarchies) + // are considered USED. + // + // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78 + // + if (index_index < p_access_chain->index_count) { + SpvReflectResult result = + ParseDescriptorBlockVariableUsage(p_parser, p_module, p_access_chain, index_index, (SpvOp)INVALID_VALUE, p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } else if (is_pointer_to_pointer) { + // Clear UNUSED flag, but only for the pointer + p_member_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + } else { + // Clear UNUSED flag for remaining variables + MarkSelfAndAllMemberVarsAsUsed(p_member_var); + } + } break; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseDescriptorBlocks(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + if (p_module->descriptor_binding_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_parser->physical_pointer_struct_count = 0; + + for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); + SpvReflectTypeDescription* p_type = p_descriptor->type_description; + if ((p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER) && + (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER)) { + continue; + } + + // Mark UNUSED + p_descriptor->block.flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + p_parser->physical_pointer_count = 0; + // Parse descriptor block + SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, &p_descriptor->block); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + for (uint32_t access_chain_index = 0; access_chain_index < p_parser->access_chain_count; ++access_chain_index) { + SpvReflectPrvAccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]); + // Skip any access chains that aren't touching this descriptor block + if (p_descriptor->spirv_id != p_access_chain->base_id) { + continue; + } + result = ParseDescriptorBlockVariableUsage(p_parser, p_module, p_access_chain, 0, (SpvOp)INVALID_VALUE, &p_descriptor->block); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + + p_descriptor->block.name = p_descriptor->name; + + bool is_parent_rta = (p_descriptor->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER); + result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, is_parent_rta, &p_descriptor->block); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + if (is_parent_rta) { + p_descriptor->block.size = 0; + p_descriptor->block.padded_size = 0; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseFormat(const SpvReflectTypeDescription* p_type, SpvReflectFormat* p_format) { + SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR; + bool signedness = (p_type->traits.numeric.scalar.signedness != 0); + uint32_t bit_width = p_type->traits.numeric.scalar.width; + if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR) { + uint32_t component_count = p_type->traits.numeric.vector.component_count; + if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) { + switch (bit_width) { + case 16: { + switch (component_count) { + case 2: + *p_format = SPV_REFLECT_FORMAT_R16G16_SFLOAT; + break; + case 3: + *p_format = SPV_REFLECT_FORMAT_R16G16B16_SFLOAT; + break; + case 4: + *p_format = SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT; + break; + } + } break; + + case 32: { + switch (component_count) { + case 2: + *p_format = SPV_REFLECT_FORMAT_R32G32_SFLOAT; + break; + case 3: + *p_format = SPV_REFLECT_FORMAT_R32G32B32_SFLOAT; + break; + case 4: + *p_format = SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT; + break; + } + } break; + + case 64: { + switch (component_count) { + case 2: + *p_format = SPV_REFLECT_FORMAT_R64G64_SFLOAT; + break; + case 3: + *p_format = SPV_REFLECT_FORMAT_R64G64B64_SFLOAT; + break; + case 4: + *p_format = SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT; + break; + } + } + } + result = SPV_REFLECT_RESULT_SUCCESS; + } else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) { + switch (bit_width) { + case 16: { + switch (component_count) { + case 2: + *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16_SINT : SPV_REFLECT_FORMAT_R16G16_UINT; + break; + case 3: + *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16B16_SINT : SPV_REFLECT_FORMAT_R16G16B16_UINT; + break; + case 4: + *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16B16A16_SINT : SPV_REFLECT_FORMAT_R16G16B16A16_UINT; + break; + } + } break; + + case 32: { + switch (component_count) { + case 2: + *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32_SINT : SPV_REFLECT_FORMAT_R32G32_UINT; + break; + case 3: + *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32_SINT : SPV_REFLECT_FORMAT_R32G32B32_UINT; + break; + case 4: + *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32A32_SINT : SPV_REFLECT_FORMAT_R32G32B32A32_UINT; + break; + } + } break; + + case 64: { + switch (component_count) { + case 2: + *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64_SINT : SPV_REFLECT_FORMAT_R64G64_UINT; + break; + case 3: + *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64_SINT : SPV_REFLECT_FORMAT_R64G64B64_UINT; + break; + case 4: + *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64A64_SINT : SPV_REFLECT_FORMAT_R64G64B64A64_UINT; + break; + } + } + } + result = SPV_REFLECT_RESULT_SUCCESS; + } + } else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) { + switch (bit_width) { + case 16: + *p_format = SPV_REFLECT_FORMAT_R16_SFLOAT; + break; + case 32: + *p_format = SPV_REFLECT_FORMAT_R32_SFLOAT; + break; + case 64: + *p_format = SPV_REFLECT_FORMAT_R64_SFLOAT; + break; + } + result = SPV_REFLECT_RESULT_SUCCESS; + } else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) { + switch (bit_width) { + case 16: + *p_format = signedness ? SPV_REFLECT_FORMAT_R16_SINT : SPV_REFLECT_FORMAT_R16_UINT; + break; + break; + case 32: + *p_format = signedness ? SPV_REFLECT_FORMAT_R32_SINT : SPV_REFLECT_FORMAT_R32_UINT; + break; + break; + case 64: + *p_format = signedness ? SPV_REFLECT_FORMAT_R64_SINT : SPV_REFLECT_FORMAT_R64_UINT; + break; + } + result = SPV_REFLECT_RESULT_SUCCESS; + } else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) { + *p_format = SPV_REFLECT_FORMAT_UNDEFINED; + result = SPV_REFLECT_RESULT_SUCCESS; + } + return result; +} + +static SpvReflectResult ParseInterfaceVariable(SpvReflectPrvParser* p_parser, + const SpvReflectPrvDecorations* p_var_node_decorations, + const SpvReflectPrvDecorations* p_type_node_decorations, + SpvReflectShaderModule* p_module, SpvReflectTypeDescription* p_type, + SpvReflectInterfaceVariable* p_var, bool* p_has_built_in) { + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + if (p_type->member_count > 0) { + p_var->member_count = p_type->member_count; + p_var->members = (SpvReflectInterfaceVariable*)calloc(p_var->member_count, sizeof(*p_var->members)); + if (IsNull(p_var->members)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + for (uint32_t member_index = 0; member_index < p_type_node->member_count; ++member_index) { + SpvReflectPrvDecorations* p_member_decorations = &p_type_node->member_decorations[member_index]; + SpvReflectTypeDescription* p_member_type = &p_type->members[member_index]; + SpvReflectInterfaceVariable* p_member_var = &p_var->members[member_index]; + + // Storage class is the same throughout the whole struct + p_member_var->storage_class = p_var->storage_class; + + SpvReflectResult result = + ParseInterfaceVariable(p_parser, NULL, p_member_decorations, p_module, p_member_type, p_member_var, p_has_built_in); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); + return result; + } + } + } + + p_var->name = p_type_node->name; + p_var->decoration_flags = ApplyDecorations(p_type_node_decorations); + if (p_var_node_decorations != NULL) { + p_var->decoration_flags |= ApplyDecorations(p_var_node_decorations); + } else { + // Apply member decoration values to struct members + p_var->location = p_type_node_decorations->location.value; + p_var->component = p_type_node_decorations->component.value; + } + + p_var->built_in = p_type_node_decorations->built_in; + ApplyNumericTraits(p_type, &p_var->numeric); + if (p_type->op == SpvOpTypeArray) { + ApplyArrayTraits(p_type, &p_var->array); + } + + p_var->type_description = p_type; + + *p_has_built_in |= p_type_node_decorations->is_built_in; + + // Only parse format for interface variables that are input or output + if ((p_var->storage_class == SpvStorageClassInput) || (p_var->storage_class == SpvStorageClassOutput)) { + SpvReflectResult result = ParseFormat(p_var->type_description, &p_var->format); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); + return result; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseInterfaceVariables(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module, + SpvReflectEntryPoint* p_entry, uint32_t interface_variable_count, + uint32_t* p_interface_variable_ids) { + if (interface_variable_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_entry->interface_variable_count = interface_variable_count; + p_entry->input_variable_count = 0; + p_entry->output_variable_count = 0; + for (size_t i = 0; i < interface_variable_count; ++i) { + uint32_t var_result_id = *(p_interface_variable_ids + i); + SpvReflectPrvNode* p_node = FindNode(p_parser, var_result_id); + if (IsNull(p_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + if (p_node->storage_class == SpvStorageClassInput) { + p_entry->input_variable_count += 1; + } else if (p_node->storage_class == SpvStorageClassOutput) { + p_entry->output_variable_count += 1; + } + } + + if (p_entry->input_variable_count > 0) { + p_entry->input_variables = + (SpvReflectInterfaceVariable**)calloc(p_entry->input_variable_count, sizeof(*(p_entry->input_variables))); + if (IsNull(p_entry->input_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_entry->output_variable_count > 0) { + p_entry->output_variables = + (SpvReflectInterfaceVariable**)calloc(p_entry->output_variable_count, sizeof(*(p_entry->output_variables))); + if (IsNull(p_entry->output_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_entry->interface_variable_count > 0) { + p_entry->interface_variables = + (SpvReflectInterfaceVariable*)calloc(p_entry->interface_variable_count, sizeof(*(p_entry->interface_variables))); + if (IsNull(p_entry->interface_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + size_t input_index = 0; + size_t output_index = 0; + for (size_t i = 0; i < interface_variable_count; ++i) { + uint32_t var_result_id = *(p_interface_variable_ids + i); + SpvReflectPrvNode* p_node = FindNode(p_parser, var_result_id); + if (IsNull(p_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id); + if (IsNull(p_node) || IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // If the type is a pointer, resolve it + if (p_type->op == SpvOpTypePointer) { + // Find the type's node + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Should be the resolved type + p_type = FindType(p_module, p_type_node->type_id); + if (IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + SpvReflectInterfaceVariable* p_var = &(p_entry->interface_variables[i]); + p_var->storage_class = p_node->storage_class; + + bool has_built_in = p_node->decorations.is_built_in; + SpvReflectResult result = + ParseInterfaceVariable(p_parser, &p_node->decorations, &p_type_node->decorations, p_module, p_type, p_var, &has_built_in); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); + return result; + } + + // Input and output variables + if (p_var->storage_class == SpvStorageClassInput) { + p_entry->input_variables[input_index] = p_var; + ++input_index; + } else if (p_node->storage_class == SpvStorageClassOutput) { + p_entry->output_variables[output_index] = p_var; + ++output_index; + } + + // SPIR-V result id + p_var->spirv_id = p_node->result_id; + // Name + p_var->name = p_node->name; + // Semantic + p_var->semantic = p_node->decorations.semantic.value; + + // Decorate with built-in if any member is built-in + if (has_built_in) { + p_var->decoration_flags |= SPV_REFLECT_DECORATION_BUILT_IN; + } + + // Location is decorated on OpVariable node, not the type node. + p_var->location = p_node->decorations.location.value; + p_var->component = p_node->decorations.component.value; + p_var->word_offset.location = p_node->decorations.location.word_offset; + + // Built in + if (p_node->decorations.is_built_in) { + p_var->built_in = p_node->decorations.built_in; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult EnumerateAllPushConstants(SpvReflectShaderModule* p_module, size_t* p_push_constant_count, + uint32_t** p_push_constants) { + *p_push_constant_count = p_module->push_constant_block_count; + if (*p_push_constant_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + *p_push_constants = (uint32_t*)calloc(*p_push_constant_count, sizeof(**p_push_constants)); + + if (IsNull(*p_push_constants)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + for (size_t i = 0; i < *p_push_constant_count; ++i) { + (*p_push_constants)[i] = p_module->push_constant_blocks[i].spirv_id; + } + qsort(*p_push_constants, *p_push_constant_count, sizeof(**p_push_constants), SortCompareUint32); + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult TraverseCallGraph(SpvReflectPrvParser* p_parser, SpvReflectPrvFunction* p_func, size_t* p_func_count, + uint32_t* p_func_ids, uint32_t depth) { + if (depth > p_parser->function_count) { + // Vulkan does not permit recursion (Vulkan spec Appendix A): + // "Recursion: The static function-call graph for an entry point must not + // contain cycles." + return SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION; + } + if (IsNotNull(p_func_ids)) { + p_func_ids[(*p_func_count)++] = p_func->id; + } else { + ++*p_func_count; + } + for (size_t i = 0; i < p_func->callee_count; ++i) { + SpvReflectResult result = TraverseCallGraph(p_parser, p_func->callee_ptrs[i], p_func_count, p_func_ids, depth + 1); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static uint32_t GetUint32Constant(SpvReflectPrvParser* p_parser, uint32_t id) { + uint32_t result = (uint32_t)INVALID_VALUE; + SpvReflectPrvNode* p_node = FindNode(p_parser, id); + if (p_node && p_node->op == SpvOpConstant) { + UNCHECKED_READU32(p_parser, p_node->word_offset + 3, result); + } + return result; +} + +static bool HasByteAddressBufferOffset(SpvReflectPrvNode* p_node, SpvReflectDescriptorBinding* p_binding) { + return IsNotNull(p_node) && IsNotNull(p_binding) && (p_node->op == SpvOpAccessChain || p_node->op == SpvOpInBoundsAccessChain) && p_node->word_count == 6 && + (p_binding->user_type == SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER || + p_binding->user_type == SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER); +} + +static SpvReflectResult ParseByteAddressBuffer(SpvReflectPrvParser* p_parser, SpvReflectPrvNode* p_node, + SpvReflectDescriptorBinding* p_binding) { + const SpvReflectResult not_found = SPV_REFLECT_RESULT_SUCCESS; + if (!HasByteAddressBufferOffset(p_node, p_binding)) { + return not_found; + } + + uint32_t offset = 0; // starting offset + + uint32_t base_id = 0; + // expect first index of 2D access is zero + UNCHECKED_READU32(p_parser, p_node->word_offset + 4, base_id); + if (GetUint32Constant(p_parser, base_id) != 0) { + return not_found; + } + UNCHECKED_READU32(p_parser, p_node->word_offset + 5, base_id); + SpvReflectPrvNode* p_next_node = FindNode(p_parser, base_id); + if (IsNull(p_next_node)) { + return not_found; + } else if (p_next_node->op == SpvOpConstant) { + // The access chain might just be a constant right to the offset + offset = GetUint32Constant(p_parser, base_id); + p_binding->byte_address_buffer_offsets[p_binding->byte_address_buffer_offset_count] = offset; + p_binding->byte_address_buffer_offset_count++; + return SPV_REFLECT_RESULT_SUCCESS; + } + + // there is usually 2 (sometimes 3) instrucitons that make up the arithmetic logic to calculate the offset + SpvReflectPrvNode* arithmetic_node_stack[8]; + uint32_t arithmetic_count = 0; + + while (IsNotNull(p_next_node)) { + if (p_next_node->op == SpvOpLoad || p_next_node->op == SpvOpBitcast || p_next_node->op == SpvOpConstant) { + break; // arithmetic starts here + } + arithmetic_node_stack[arithmetic_count++] = p_next_node; + if (arithmetic_count >= 8) { + return not_found; + } + + UNCHECKED_READU32(p_parser, p_next_node->word_offset + 3, base_id); + p_next_node = FindNode(p_parser, base_id); + } + + const uint32_t count = arithmetic_count; + for (uint32_t i = 0; i < count; i++) { + p_next_node = arithmetic_node_stack[--arithmetic_count]; + // All arithmetic ops takes 2 operands, assumption is the 2nd operand has the constant + UNCHECKED_READU32(p_parser, p_next_node->word_offset + 4, base_id); + uint32_t value = GetUint32Constant(p_parser, base_id); + if (value == (uint32_t)INVALID_VALUE) { + return not_found; + } + + switch (p_next_node->op) { + case SpvOpShiftRightLogical: + offset >>= value; + break; + case SpvOpIAdd: + offset += value; + break; + case SpvOpISub: + offset -= value; + break; + case SpvOpIMul: + offset *= value; + break; + case SpvOpUDiv: + offset /= value; + break; + case SpvOpSDiv: + // OpConstant might be signed, but value should never be negative + assert((int32_t)value > 0); + offset /= value; + break; + default: + return not_found; + } + } + + p_binding->byte_address_buffer_offsets[p_binding->byte_address_buffer_offset_count] = offset; + p_binding->byte_address_buffer_offset_count++; + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseFunctionParameterAccess(SpvReflectPrvParser* p_parser, uint32_t callee_function_id, + uint32_t function_parameter_index, uint32_t* p_accessed) { + SpvReflectPrvFunction* p_func = NULL; + for (size_t i = 0; i < p_parser->function_count; ++i) { + if (p_parser->functions[i].id == callee_function_id) { + p_func = &(p_parser->functions[i]); + break; + } + } + if (p_func == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + assert(function_parameter_index < p_func->parameter_count); + + for (size_t i = 0; i < p_func->accessed_variable_count; ++i) { + if (p_func->parameters[function_parameter_index] == p_func->accessed_variables[i].variable_ptr) { + SpvReflectPrvAccessedVariable* p_var = &p_func->accessed_variables[i]; + if (p_var->function_id > 0) { + SpvReflectResult result = + ParseFunctionParameterAccess(p_parser, p_var->function_id, p_var->function_parameter_index, p_accessed); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } else { + *p_accessed = 1; + } + // Early out as soon as p_accessed is true + if (*p_accessed) { + return SPV_REFLECT_RESULT_SUCCESS; + } + } + } + + *p_accessed = 0; + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseStaticallyUsedResources(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module, + SpvReflectEntryPoint* p_entry, size_t uniform_count, uint32_t* uniforms, + size_t push_constant_count, uint32_t* push_constants) { + // Find function with the right id + SpvReflectPrvFunction* p_func = NULL; + for (size_t i = 0; i < p_parser->function_count; ++i) { + if (p_parser->functions[i].id == p_entry->id) { + p_func = &(p_parser->functions[i]); + break; + } + } + if (p_func == NULL) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + size_t called_function_count = 0; + SpvReflectResult result = TraverseCallGraph(p_parser, p_func, &called_function_count, NULL, 0); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + uint32_t* p_called_functions = NULL; + if (called_function_count > 0) { + p_called_functions = (uint32_t*)calloc(called_function_count, sizeof(*p_called_functions)); + if (IsNull(p_called_functions)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + called_function_count = 0; + result = TraverseCallGraph(p_parser, p_func, &called_function_count, p_called_functions, 0); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SafeFree(p_called_functions); + return result; + } + + if (called_function_count > 0) { + qsort(p_called_functions, called_function_count, sizeof(*p_called_functions), SortCompareUint32); + } + called_function_count = DedupSortedUint32(p_called_functions, called_function_count); + + uint32_t used_acessed_count = 0; + for (size_t i = 0, j = 0; i < called_function_count; ++i) { + // No need to bounds check j because a missing ID issue would have been + // found during TraverseCallGraph + while (p_parser->functions[j].id != p_called_functions[i]) { + ++j; + } + used_acessed_count += p_parser->functions[j].accessed_variable_count; + } + + // If there are no used accessed, this is something like an empty function/early return + // Basically there is going to be nothing to reflect, but everything after this expects |p_used_accesses| to be allocated with + // real memory, see https://github.com/KhronosGroup/SPIRV-Reflect/issues/319 + if (used_acessed_count == 0) { + SafeFree(p_called_functions); + return SPV_REFLECT_RESULT_SUCCESS; + } + + SpvReflectPrvAccessedVariable* p_used_accesses = + (SpvReflectPrvAccessedVariable*)calloc(used_acessed_count, sizeof(SpvReflectPrvAccessedVariable)); + if (IsNull(p_used_accesses)) { + SafeFree(p_called_functions); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + used_acessed_count = 0; + for (size_t i = 0, j = 0; i < called_function_count; ++i) { + while (p_parser->functions[j].id != p_called_functions[i]) { + ++j; + } + + memcpy(&p_used_accesses[used_acessed_count], p_parser->functions[j].accessed_variables, + p_parser->functions[j].accessed_variable_count * sizeof(SpvReflectPrvAccessedVariable)); + used_acessed_count += p_parser->functions[j].accessed_variable_count; + } + SafeFree(p_called_functions); + + if (used_acessed_count > 0) { + qsort(p_used_accesses, used_acessed_count, sizeof(*p_used_accesses), SortCompareAccessedVariable); + } + + // Do set intersection to find the used uniform and push constants + size_t used_uniform_count = 0; + result = IntersectSortedAccessedVariable(p_used_accesses, used_acessed_count, uniforms, uniform_count, &p_entry->used_uniforms, + &used_uniform_count); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SafeFree(p_used_accesses); + return result; + } + + size_t used_push_constant_count = 0; + result = IntersectSortedAccessedVariable(p_used_accesses, used_acessed_count, push_constants, push_constant_count, + &p_entry->used_push_constants, &used_push_constant_count); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SafeFree(p_used_accesses); + return result; + } + + for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) { + SpvReflectDescriptorBinding* p_binding = &p_module->descriptor_bindings[i]; + uint32_t byte_address_buffer_offset_count = 0; + + for (uint32_t j = 0; j < used_acessed_count; j++) { + SpvReflectPrvAccessedVariable* p_var = &p_used_accesses[j]; + if (p_var->variable_ptr == p_binding->spirv_id) { + if (p_var->function_id > 0) { + result = + ParseFunctionParameterAccess(p_parser, p_var->function_id, p_var->function_parameter_index, &p_binding->accessed); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SafeFree(p_used_accesses); + return result; + } + } else { + p_binding->accessed = 1; + } + + if (HasByteAddressBufferOffset(p_used_accesses[j].p_node, p_binding)) { + byte_address_buffer_offset_count++; + } + } + } + + // only if SPIR-V has ByteAddressBuffer user type + if (byte_address_buffer_offset_count > 0) { + bool multi_entrypoint = p_binding->byte_address_buffer_offset_count > 0; + if (multi_entrypoint) { + // If there is a 2nd entrypoint, we can have multiple entry points, in this case we want to just combine the accessed + // offsets and then de-duplicate it + uint32_t* prev_byte_address_buffer_offsets = p_binding->byte_address_buffer_offsets; + p_binding->byte_address_buffer_offsets = + (uint32_t*)calloc(byte_address_buffer_offset_count + p_binding->byte_address_buffer_offset_count, sizeof(uint32_t)); + memcpy(p_binding->byte_address_buffer_offsets, prev_byte_address_buffer_offsets, + sizeof(uint32_t) * p_binding->byte_address_buffer_offset_count); + SafeFree(prev_byte_address_buffer_offsets); + } else { + // possible not all allocated offset slots are used, but this will be a max per binding + p_binding->byte_address_buffer_offsets = (uint32_t*)calloc(byte_address_buffer_offset_count, sizeof(uint32_t)); + } + + if (IsNull(p_binding->byte_address_buffer_offsets)) { + SafeFree(p_used_accesses); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + for (uint32_t j = 0; j < used_acessed_count; j++) { + if (p_used_accesses[j].variable_ptr == p_binding->spirv_id) { + result = ParseByteAddressBuffer(p_parser, p_used_accesses[j].p_node, p_binding); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SafeFree(p_used_accesses); + return result; + } + } + } + + if (multi_entrypoint) { + qsort(p_binding->byte_address_buffer_offsets, p_binding->byte_address_buffer_offset_count, + sizeof(*(p_binding->byte_address_buffer_offsets)), SortCompareUint32); + p_binding->byte_address_buffer_offset_count = + (uint32_t)DedupSortedUint32(p_binding->byte_address_buffer_offsets, p_binding->byte_address_buffer_offset_count); + } + } + } + + SafeFree(p_used_accesses); + + p_entry->used_uniform_count = (uint32_t)used_uniform_count; + p_entry->used_push_constant_count = (uint32_t)used_push_constant_count; + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseEntryPoints(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + if (p_parser->entry_point_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->entry_point_count = p_parser->entry_point_count; + p_module->entry_points = (SpvReflectEntryPoint*)calloc(p_module->entry_point_count, sizeof(*(p_module->entry_points))); + if (IsNull(p_module->entry_points)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + SpvReflectResult result; + size_t uniform_count = 0; + uint32_t* uniforms = NULL; + if ((result = EnumerateAllUniforms(p_module, &uniform_count, &uniforms)) != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + size_t push_constant_count = 0; + uint32_t* push_constants = NULL; + if ((result = EnumerateAllPushConstants(p_module, &push_constant_count, &push_constants)) != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + size_t entry_point_index = 0; + for (size_t i = 0; entry_point_index < p_parser->entry_point_count && i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op != SpvOpEntryPoint) { + continue; + } + + SpvReflectEntryPoint* p_entry_point = &(p_module->entry_points[entry_point_index]); + CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvExecutionModel, p_entry_point->spirv_execution_model); + CHECKED_READU32(p_parser, p_node->word_offset + 2, p_entry_point->id); + + switch (p_entry_point->spirv_execution_model) { + default: + break; + case SpvExecutionModelVertex: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_VERTEX_BIT; + break; + case SpvExecutionModelTessellationControl: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + break; + case SpvExecutionModelTessellationEvaluation: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + break; + case SpvExecutionModelGeometry: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT; + break; + case SpvExecutionModelFragment: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT; + break; + case SpvExecutionModelGLCompute: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT; + break; + case SpvExecutionModelTaskNV: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV; + break; + case SpvExecutionModelTaskEXT: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TASK_BIT_EXT; + break; + case SpvExecutionModelMeshNV: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV; + break; + case SpvExecutionModelMeshEXT: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_EXT; + break; + case SpvExecutionModelRayGenerationKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR; + break; + case SpvExecutionModelIntersectionKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR; + break; + case SpvExecutionModelAnyHitKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR; + break; + case SpvExecutionModelClosestHitKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + break; + case SpvExecutionModelMissKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR; + break; + case SpvExecutionModelCallableKHR: + p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR; + break; + } + + ++entry_point_index; + + // Name length is required to calculate next operand + uint32_t name_start_word_offset = 3; + uint32_t name_length_with_terminator = 0; + result = + ReadStr(p_parser, p_node->word_offset + name_start_word_offset, 0, p_node->word_count, &name_length_with_terminator, NULL); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + p_entry_point->name = (const char*)(p_parser->spirv_code + p_node->word_offset + name_start_word_offset); + + uint32_t name_word_count = RoundUp(name_length_with_terminator, SPIRV_WORD_SIZE) / SPIRV_WORD_SIZE; + uint32_t interface_variable_count = (p_node->word_count - (name_start_word_offset + name_word_count)); + uint32_t* p_interface_variables = NULL; + if (interface_variable_count > 0) { + p_interface_variables = (uint32_t*)calloc(interface_variable_count, sizeof(*(p_interface_variables))); + if (IsNull(p_interface_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + for (uint32_t var_index = 0; var_index < interface_variable_count; ++var_index) { + uint32_t var_result_id = (uint32_t)INVALID_VALUE; + uint32_t offset = name_start_word_offset + name_word_count + var_index; + CHECKED_READU32(p_parser, p_node->word_offset + offset, var_result_id); + p_interface_variables[var_index] = var_result_id; + } + + result = ParseInterfaceVariables(p_parser, p_module, p_entry_point, interface_variable_count, p_interface_variables); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + SafeFree(p_interface_variables); + + result = ParseStaticallyUsedResources(p_parser, p_module, p_entry_point, uniform_count, uniforms, push_constant_count, + push_constants); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + + SafeFree(uniforms); + SafeFree(push_constants); + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseExecutionModes(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->nodes)); + assert(IsNotNull(p_module)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]); + if (p_node->op != SpvOpExecutionMode && p_node->op != SpvOpExecutionModeId) { + continue; + } + + // Read entry point id + uint32_t entry_point_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id); + + // Find entry point + SpvReflectEntryPoint* p_entry_point = NULL; + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + if (p_module->entry_points[entry_point_idx].id == entry_point_id) { + p_entry_point = &p_module->entry_points[entry_point_idx]; + break; + } + } + // Bail if entry point is null + if (IsNull(p_entry_point)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT; + } + + // Read execution mode + uint32_t execution_mode = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode); + + // Parse execution mode + switch (execution_mode) { + case SpvExecutionModeInvocations: { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->invocations); + } break; + + case SpvExecutionModeLocalSize: { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->local_size.x); + CHECKED_READU32(p_parser, p_node->word_offset + 4, p_entry_point->local_size.y); + CHECKED_READU32(p_parser, p_node->word_offset + 5, p_entry_point->local_size.z); + } break; + case SpvExecutionModeLocalSizeId: { + uint32_t local_size_x_id = 0; + uint32_t local_size_y_id = 0; + uint32_t local_size_z_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 3, local_size_x_id); + CHECKED_READU32(p_parser, p_node->word_offset + 4, local_size_y_id); + CHECKED_READU32(p_parser, p_node->word_offset + 5, local_size_z_id); + + SpvReflectPrvNode* x_node = FindNode(p_parser, local_size_x_id); + SpvReflectPrvNode* y_node = FindNode(p_parser, local_size_y_id); + SpvReflectPrvNode* z_node = FindNode(p_parser, local_size_z_id); + if (IsNotNull(x_node) && IsNotNull(y_node) && IsNotNull(z_node)) { + if (IsSpecConstant(x_node)) { + p_entry_point->local_size.x = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, x_node->word_offset + 3, p_entry_point->local_size.x); + } + + if (IsSpecConstant(y_node)) { + p_entry_point->local_size.y = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, y_node->word_offset + 3, p_entry_point->local_size.y); + } + + if (IsSpecConstant(z_node)) { + p_entry_point->local_size.z = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT; + } else { + CHECKED_READU32(p_parser, z_node->word_offset + 3, p_entry_point->local_size.z); + } + } + } break; + + case SpvExecutionModeOutputVertices: { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->output_vertices); + } break; + + default: + break; + } + p_entry_point->execution_mode_count++; + } + uint32_t* indices = (uint32_t*)calloc(p_module->entry_point_count, sizeof(indices)); + if (IsNull(indices)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx]; + if (p_entry_point->execution_mode_count > 0) { + p_entry_point->execution_modes = + (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes)); + if (IsNull(p_entry_point->execution_modes)) { + SafeFree(indices); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + } + + for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]); + if (p_node->op != SpvOpExecutionMode) { + continue; + } + + // Read entry point id + uint32_t entry_point_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id); + + // Find entry point + SpvReflectEntryPoint* p_entry_point = NULL; + uint32_t* idx = NULL; + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + if (p_module->entry_points[entry_point_idx].id == entry_point_id) { + p_entry_point = &p_module->entry_points[entry_point_idx]; + idx = &indices[entry_point_idx]; + break; + } + } + + // Read execution mode + uint32_t execution_mode = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode); + p_entry_point->execution_modes[(*idx)++] = (SpvExecutionMode)execution_mode; + } + SafeFree(indices); + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParsePushConstantBlocks(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) { + continue; + } + + p_module->push_constant_block_count += 1; + } + + if (p_module->push_constant_block_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + p_module->push_constant_blocks = + (SpvReflectBlockVariable*)calloc(p_module->push_constant_block_count, sizeof(*p_module->push_constant_blocks)); + if (IsNull(p_module->push_constant_blocks)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + p_parser->physical_pointer_struct_count = 0; + uint32_t push_constant_index = 0; + for (size_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) { + continue; + } + + SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id); + if (IsNull(p_node) || IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // If the type is a pointer, resolve it + if (p_type->op == SpvOpTypePointer) { + // Find the type's node + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + // Should be the resolved type + p_type = FindType(p_module, p_type_node->type_id); + if (IsNull(p_type)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + } + + SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id); + if (IsNull(p_type_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + SpvReflectBlockVariable* p_push_constant = &p_module->push_constant_blocks[push_constant_index]; + p_push_constant->spirv_id = p_node->result_id; + p_parser->physical_pointer_count = 0; + SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, p_push_constant); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + for (uint32_t access_chain_index = 0; access_chain_index < p_parser->access_chain_count; ++access_chain_index) { + SpvReflectPrvAccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]); + // Skip any access chains that aren't touching this push constant block + if (p_push_constant->spirv_id != FindAccessChainBaseVariable(p_parser, p_access_chain)) { + continue; + } + SpvReflectBlockVariable* p_var = + (p_access_chain->base_id == p_push_constant->spirv_id) ? p_push_constant : GetRefBlkVar(p_parser, p_access_chain); + result = ParseDescriptorBlockVariableUsage(p_parser, p_module, p_access_chain, 0, (SpvOp)INVALID_VALUE, p_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + + p_push_constant->name = p_node->name; + result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, true, p_push_constant); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + + // Get minimum offset for whole Push Constant block + // It is not valid SPIR-V to have an empty Push Constant Block + p_push_constant->offset = UINT32_MAX; + for (uint32_t k = 0; k < p_push_constant->member_count; ++k) { + const uint32_t member_offset = p_push_constant->members[k].offset; + p_push_constant->offset = Min(p_push_constant->offset, member_offset); + } + + ++push_constant_index; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseSpecConstants(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) { + if (p_parser->spec_constant_count > 0) { + p_module->spec_constants = (SpvReflectSpecializationConstant*)calloc(p_parser->spec_constant_count, sizeof(*p_module->spec_constants)); + if (IsNull(p_module->spec_constants)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } else { + return SPV_REFLECT_RESULT_SUCCESS; + } + for (uint32_t i = 0; i < p_parser->node_count; ++i) { + SpvReflectPrvNode* p_node = &(p_parser->nodes[i]); + if (p_node->op == SpvOpDecorate) { + uint32_t decoration = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, decoration); + if (decoration == SpvDecorationSpecId) { + SpvReflectSpecializationConstant* p_spec_constant = &(p_module->spec_constants[p_module->spec_constant_count]); + CHECKED_READU32(p_parser, p_node->word_offset + 1, p_spec_constant->spirv_id); + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_spec_constant->constant_id); + SpvReflectPrvNode* target_node = FindNode(p_parser, p_spec_constant->spirv_id); + if (IsNotNull(target_node)) { + // If being used for a OpSpecConstantComposite (ex. LocalSizeId), there won't be a name + p_spec_constant->name = target_node->name; + + // During external specialization, Boolean values are true if non-zero and false if zero. + static uint32_t true_value = 1; + static uint32_t false_value = 0; + switch (target_node->op) { + default: + // Unexpected, since Spec states: + // (SpecId) Apply only to a scalar specialization constant + SPV_REFLECT_ASSERT(false); + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION; + case SpvOpSpecConstantTrue: + p_spec_constant->default_value_size = sizeof(uint32_t); + p_spec_constant->default_value = &true_value; + break; + case SpvOpSpecConstantFalse: + p_spec_constant->default_value_size = sizeof(uint32_t); + p_spec_constant->default_value = &false_value; + break; + case SpvOpSpecConstant: + p_spec_constant->default_value_size = (target_node->word_count - 3) * sizeof(uint32_t); + p_spec_constant->default_value = p_parser->spirv_code + target_node->word_offset + 3; + break; + } + p_spec_constant->type_description = FindType(p_module, target_node->result_type_id); + } else { + // Decoration target not found + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + p_module->spec_constant_count++; + } + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +static int SortCompareDescriptorSet(const void* a, const void* b) { + const SpvReflectDescriptorSet* p_elem_a = (const SpvReflectDescriptorSet*)a; + const SpvReflectDescriptorSet* p_elem_b = (const SpvReflectDescriptorSet*)b; + int value = (int)(p_elem_a->set) - (int)(p_elem_b->set); + // We should never see duplicate descriptor set numbers in a shader; if so, a tiebreaker + // would be needed here. + assert(value != 0); + return value; +} + +static SpvReflectResult ParseEntrypointDescriptorSets(SpvReflectShaderModule* p_module) { + // Update the entry point's sets + for (uint32_t i = 0; i < p_module->entry_point_count; ++i) { + SpvReflectEntryPoint* p_entry = &p_module->entry_points[i]; + for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) { + SafeFree(p_entry->descriptor_sets[j].bindings); + } + SafeFree(p_entry->descriptor_sets); + p_entry->descriptor_set_count = 0; + for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) { + const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j]; + for (uint32_t k = 0; k < p_set->binding_count; ++k) { + bool found = SearchSortedUint32(p_entry->used_uniforms, p_entry->used_uniform_count, p_set->bindings[k]->spirv_id); + if (found) { + ++p_entry->descriptor_set_count; + break; + } + } + } + + p_entry->descriptor_sets = NULL; + if (p_entry->descriptor_set_count > 0) { + p_entry->descriptor_sets = (SpvReflectDescriptorSet*)calloc(p_entry->descriptor_set_count, sizeof(*p_entry->descriptor_sets)); + if (IsNull(p_entry->descriptor_sets)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + p_entry->descriptor_set_count = 0; + for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) { + const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j]; + uint32_t count = 0; + for (uint32_t k = 0; k < p_set->binding_count; ++k) { + bool found = SearchSortedUint32(p_entry->used_uniforms, p_entry->used_uniform_count, p_set->bindings[k]->spirv_id); + if (found) { + ++count; + } + } + if (count == 0) { + continue; + } + SpvReflectDescriptorSet* p_entry_set = &p_entry->descriptor_sets[p_entry->descriptor_set_count++]; + p_entry_set->set = p_set->set; + p_entry_set->bindings = (SpvReflectDescriptorBinding**)calloc(count, sizeof(*p_entry_set->bindings)); + if (IsNull(p_entry_set->bindings)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + for (uint32_t k = 0; k < p_set->binding_count; ++k) { + bool found = SearchSortedUint32(p_entry->used_uniforms, p_entry->used_uniform_count, p_set->bindings[k]->spirv_id); + if (found) { + p_entry_set->bindings[p_entry_set->binding_count++] = p_set->bindings[k]; + } + } + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult ParseDescriptorSets(SpvReflectShaderModule* p_module) { + // Count the descriptors in each set + for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[i]); + + // Look for a target set using the descriptor's set number + SpvReflectDescriptorSet* p_target_set = NULL; + for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) { + SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j]; + if (p_set->set == p_descriptor->set) { + p_target_set = p_set; + break; + } + } + + // If a target set isn't found, find the first available one. + if (IsNull(p_target_set)) { + for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) { + SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j]; + if (p_set->set == (uint32_t)INVALID_VALUE) { + p_target_set = p_set; + p_target_set->set = p_descriptor->set; + break; + } + } + } + + if (IsNull(p_target_set)) { + return SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR; + } + + p_target_set->binding_count += 1; + } + + // Count the descriptor sets + for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) { + const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i]; + if (p_set->set != (uint32_t)INVALID_VALUE) { + p_module->descriptor_set_count += 1; + } + } + + // Sort the descriptor sets based on numbers + if (p_module->descriptor_set_count > 0) { + qsort(p_module->descriptor_sets, p_module->descriptor_set_count, sizeof(*(p_module->descriptor_sets)), + SortCompareDescriptorSet); + } + + // Build descriptor pointer array + for (uint32_t i = 0; i < p_module->descriptor_set_count; ++i) { + SpvReflectDescriptorSet* p_set = &(p_module->descriptor_sets[i]); + p_set->bindings = (SpvReflectDescriptorBinding**)calloc(p_set->binding_count, sizeof(*(p_set->bindings))); + + uint32_t descriptor_index = 0; + for (uint32_t j = 0; j < p_module->descriptor_binding_count; ++j) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[j]); + if (p_descriptor->set == p_set->set) { + assert(descriptor_index < p_set->binding_count); + p_set->bindings[descriptor_index] = p_descriptor; + ++descriptor_index; + } + } + } + + return ParseEntrypointDescriptorSets(p_module); +} + +static SpvReflectResult DisambiguateStorageBufferSrvUav(SpvReflectShaderModule* p_module) { + if (p_module->descriptor_binding_count == 0) { + return SPV_REFLECT_RESULT_SUCCESS; + } + + for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) { + SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); + // Skip everything that isn't a STORAGE_BUFFER descriptor + if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + continue; + } + + // + // Vulkan doesn't disambiguate between SRVs and UAVs so they + // come back as STORAGE_BUFFER. The block parsing process will + // mark a block as non-writable should any member of the block + // or its descendants are non-writable. + // + if (p_descriptor->block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) { + p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; + } + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +static SpvReflectResult SynchronizeDescriptorSets(SpvReflectShaderModule* p_module) { + // Free and reset all descriptor set numbers + for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) { + SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i]; + SafeFree(p_set->bindings); + p_set->binding_count = 0; + p_set->set = (uint32_t)INVALID_VALUE; + } + // Set descriptor set count to zero + p_module->descriptor_set_count = 0; + + SpvReflectResult result = ParseDescriptorSets(p_module); + return result; +} + +static SpvReflectResult CreateShaderModule(uint32_t flags, size_t size, const void* p_code, SpvReflectShaderModule* p_module) { + // Initialize all module fields to zero + memset(p_module, 0, sizeof(*p_module)); + + // Allocate module internals +#ifdef __cplusplus + p_module->_internal = (SpvReflectShaderModule::Internal*)calloc(1, sizeof(*(p_module->_internal))); +#else + p_module->_internal = calloc(1, sizeof(*(p_module->_internal))); +#endif + if (IsNull(p_module->_internal)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + // Copy flags + p_module->_internal->module_flags = flags; + // Figure out if we need to copy the SPIR-V code or not + if (flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) { + // Set internal size and pointer to args passed in + p_module->_internal->spirv_size = size; +#if defined(__cplusplus) + p_module->_internal->spirv_code = const_cast(static_cast(p_code)); // cast that const away +#else + p_module->_internal->spirv_code = (void*)p_code; // cast that const away +#endif + p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE); + } else { + // Allocate SPIR-V code storage + p_module->_internal->spirv_size = size; + p_module->_internal->spirv_code = (uint32_t*)calloc(1, p_module->_internal->spirv_size); + p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE); + if (IsNull(p_module->_internal->spirv_code)) { + SafeFree(p_module->_internal); + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + // Copy SPIR-V to code storage + memcpy(p_module->_internal->spirv_code, p_code, size); + } + + // Initialize everything to zero + SpvReflectPrvParser parser; + memset(&parser, 0, sizeof(SpvReflectPrvParser)); + + // Create parser + SpvReflectResult result = CreateParser(p_module->_internal->spirv_size, p_module->_internal->spirv_code, &parser); + + // Generator + { + const uint32_t* p_ptr = (const uint32_t*)p_module->_internal->spirv_code; + p_module->generator = (SpvReflectGenerator)((*(p_ptr + 2) & 0xFFFF0000) >> 16); + } + + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseNodes(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseStrings(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseSource(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseFunctions(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseMemberCounts(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseNames(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseDecorations(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + + // Start of reflection data parsing + if (result == SPV_REFLECT_RESULT_SUCCESS) { + p_module->source_language = parser.source_language; + p_module->source_language_version = parser.source_language_version; + + // Zero out descriptor set data + p_module->descriptor_set_count = 0; + memset(p_module->descriptor_sets, 0, SPV_REFLECT_MAX_DESCRIPTOR_SETS * sizeof(*p_module->descriptor_sets)); + // Initialize descriptor set numbers + for (uint32_t set_number = 0; set_number < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++set_number) { + p_module->descriptor_sets[set_number].set = (uint32_t)INVALID_VALUE; + } + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseTypes(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseDescriptorBindings(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseDescriptorType(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseUAVCounterBindings(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseDescriptorBlocks(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParsePushConstantBlocks(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseSpecConstants(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseEntryPoints(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseCapabilities(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS && p_module->entry_point_count > 0) { + SpvReflectEntryPoint* p_entry = &(p_module->entry_points[0]); + p_module->entry_point_name = p_entry->name; + p_module->entry_point_id = p_entry->id; + p_module->spirv_execution_model = p_entry->spirv_execution_model; + p_module->shader_stage = p_entry->shader_stage; + p_module->input_variable_count = p_entry->input_variable_count; + p_module->input_variables = p_entry->input_variables; + p_module->output_variable_count = p_entry->output_variable_count; + p_module->output_variables = p_entry->output_variables; + p_module->interface_variable_count = p_entry->interface_variable_count; + p_module->interface_variables = p_entry->interface_variables; + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = DisambiguateStorageBufferSrvUav(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = SynchronizeDescriptorSets(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseExecutionModes(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + + // Destroy module if parse was not successful + if (result != SPV_REFLECT_RESULT_SUCCESS) { + spvReflectDestroyShaderModule(p_module); + } + + DestroyParser(&parser); + + return result; +} + +SpvReflectResult spvReflectCreateShaderModule(size_t size, const void* p_code, SpvReflectShaderModule* p_module) { + return CreateShaderModule(0, size, p_code, p_module); +} + +SpvReflectResult spvReflectCreateShaderModule2(uint32_t flags, size_t size, const void* p_code, SpvReflectShaderModule* p_module) { + return CreateShaderModule(flags, size, p_code, p_module); +} + +SpvReflectResult spvReflectGetShaderModule(size_t size, const void* p_code, SpvReflectShaderModule* p_module) { + return spvReflectCreateShaderModule(size, p_code, p_module); +} + +static void SafeFreeTypes(SpvReflectTypeDescription* p_type) { + if (IsNull(p_type) || p_type->copied) { + return; + } + + if (IsNotNull(p_type->members)) { + for (size_t i = 0; i < p_type->member_count; ++i) { + SpvReflectTypeDescription* p_member = &p_type->members[i]; + SafeFreeTypes(p_member); + } + + SafeFree(p_type->members); + p_type->members = NULL; + } +} + +static void SafeFreeBlockVariables(SpvReflectBlockVariable* p_block) { + if (IsNull(p_block)) { + return; + } + + // We share pointers to Physical Pointer structs and don't want to double free + if (p_block->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) { + return; + } + + if (IsNotNull(p_block->members)) { + for (size_t i = 0; i < p_block->member_count; ++i) { + SpvReflectBlockVariable* p_member = &p_block->members[i]; + SafeFreeBlockVariables(p_member); + } + + SafeFree(p_block->members); + p_block->members = NULL; + } +} + +static void SafeFreeInterfaceVariable(SpvReflectInterfaceVariable* p_interface) { + if (IsNull(p_interface)) { + return; + } + + if (IsNotNull(p_interface->members)) { + for (size_t i = 0; i < p_interface->member_count; ++i) { + SpvReflectInterfaceVariable* p_member = &p_interface->members[i]; + SafeFreeInterfaceVariable(p_member); + } + + SafeFree(p_interface->members); + p_interface->members = NULL; + } +} + +void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) { + if (IsNull(p_module->_internal)) { + return; + } + + SafeFree(p_module->source_source); + + // Descriptor set bindings + for (size_t i = 0; i < p_module->descriptor_set_count; ++i) { + SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i]; + free(p_set->bindings); + } + + // Descriptor binding blocks + for (size_t i = 0; i < p_module->descriptor_binding_count; ++i) { + SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[i]; + if (IsNotNull(p_descriptor->byte_address_buffer_offsets)) { + SafeFree(p_descriptor->byte_address_buffer_offsets); + } + SafeFreeBlockVariables(&p_descriptor->block); + } + SafeFree(p_module->descriptor_bindings); + + // Entry points + for (size_t i = 0; i < p_module->entry_point_count; ++i) { + SpvReflectEntryPoint* p_entry = &p_module->entry_points[i]; + for (size_t j = 0; j < p_entry->interface_variable_count; j++) { + SafeFreeInterfaceVariable(&p_entry->interface_variables[j]); + } + for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) { + SafeFree(p_entry->descriptor_sets[j].bindings); + } + SafeFree(p_entry->descriptor_sets); + SafeFree(p_entry->input_variables); + SafeFree(p_entry->output_variables); + SafeFree(p_entry->interface_variables); + SafeFree(p_entry->used_uniforms); + SafeFree(p_entry->used_push_constants); + SafeFree(p_entry->execution_modes); + } + SafeFree(p_module->capabilities); + SafeFree(p_module->entry_points); + SafeFree(p_module->spec_constants); + + // Push constants + for (size_t i = 0; i < p_module->push_constant_block_count; ++i) { + SafeFreeBlockVariables(&p_module->push_constant_blocks[i]); + } + SafeFree(p_module->push_constant_blocks); + + // Type infos + for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) { + SpvReflectTypeDescription* p_type = &p_module->_internal->type_descriptions[i]; + if (IsNotNull(p_type->members)) { + SafeFreeTypes(p_type); + } + SafeFree(p_type->members); + } + SafeFree(p_module->_internal->type_descriptions); + + // Free SPIR-V code if there was a copy + if ((p_module->_internal->module_flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) == 0) { + SafeFree(p_module->_internal->spirv_code); + } + // Free internal + SafeFree(p_module->_internal); +} + +uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module) { + if (IsNull(p_module)) { + return 0; + } + + return (uint32_t)(p_module->_internal->spirv_size); +} + +const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module) { + if (IsNull(p_module)) { + return NULL; + } + + return p_module->_internal->spirv_code; +} + +const SpvReflectEntryPoint* spvReflectGetEntryPoint(const SpvReflectShaderModule* p_module, const char* entry_point) { + if (IsNull(p_module) || IsNull(entry_point)) { + return NULL; + } + + for (uint32_t i = 0; i < p_module->entry_point_count; ++i) { + if (strcmp(p_module->entry_points[i].name, entry_point) == 0) { + return &p_module->entry_points[i]; + } + } + return NULL; +} + +SpvReflectResult spvReflectEnumerateDescriptorBindings(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectDescriptorBinding** pp_bindings) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_bindings)) { + if (*p_count != p_module->descriptor_binding_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectDescriptorBinding* p_bindings = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[index]; + pp_bindings[index] = p_bindings; + } + } else { + *p_count = p_module->descriptor_binding_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + uint32_t count = 0; + for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) { + bool found = SearchSortedUint32(p_entry->used_uniforms, p_entry->used_uniform_count, p_module->descriptor_bindings[i].spirv_id); + if (found) { + if (IsNotNull(pp_bindings)) { + if (count >= *p_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + pp_bindings[count++] = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[i]; + } else { + ++count; + } + } + } + if (IsNotNull(pp_bindings)) { + if (count != *p_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + } else { + *p_count = count; + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateDescriptorSets(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectDescriptorSet** pp_sets) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_sets)) { + if (*p_count != p_module->descriptor_set_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_module->descriptor_sets[index]; + pp_sets[index] = p_set; + } + } else { + *p_count = p_module->descriptor_set_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + if (IsNotNull(pp_sets)) { + if (*p_count != p_entry->descriptor_set_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_entry->descriptor_sets[index]; + pp_sets[index] = p_set; + } + } else { + *p_count = p_entry->descriptor_set_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateInterfaceVariables(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_module->interface_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = &p_module->interface_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_module->interface_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_entry->interface_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = &p_entry->interface_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_entry->interface_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateInputVariables(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_module->input_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = p_module->input_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_module->input_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointInputVariables(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_entry->input_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = p_entry->input_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_entry->input_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateOutputVariables(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_module->output_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = p_module->output_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_module->output_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointOutputVariables(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_entry->output_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = p_entry->output_variables[index]; + pp_variables[index] = p_var; + } + } else { + *p_count = p_entry->output_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumeratePushConstantBlocks(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (pp_blocks != NULL) { + if (*p_count != p_module->push_constant_block_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectBlockVariable* p_push_constant_blocks = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[index]; + pp_blocks[index] = p_push_constant_blocks; + } + } else { + *p_count = p_module->push_constant_block_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} +SpvReflectResult spvReflectEnumeratePushConstants(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks) { + return spvReflectEnumeratePushConstantBlocks(p_module, p_count, pp_blocks); +} + +SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + uint32_t count = 0; + for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) { + bool found = SearchSortedUint32(p_entry->used_push_constants, p_entry->used_push_constant_count, + p_module->push_constant_blocks[i].spirv_id); + if (found) { + if (IsNotNull(pp_blocks)) { + if (count >= *p_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + pp_blocks[count++] = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[i]; + } else { + ++count; + } + } + } + if (IsNotNull(pp_blocks)) { + if (count != *p_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + } else { + *p_count = count; + } + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateSpecializationConstants(const SpvReflectShaderModule* p_module, uint32_t* p_count, + SpvReflectSpecializationConstant** pp_constants) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_constants)) { + if (*p_count != p_module->spec_constant_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectSpecializationConstant* p_constant = (SpvReflectSpecializationConstant*)&p_module->spec_constants[index]; + pp_constants[index] = p_constant; + } + } else { + *p_count = p_module->spec_constant_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding(const SpvReflectShaderModule* p_module, uint32_t binding_number, + uint32_t set_number, SpvReflectResult* p_result) { + const SpvReflectDescriptorBinding* p_descriptor = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) { + const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index]; + if ((p_potential->binding == binding_number) && (p_potential->set == set_number)) { + p_descriptor = p_potential; + break; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_descriptor) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_descriptor; +} + +const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding(const SpvReflectShaderModule* p_module, + const char* entry_point, uint32_t binding_number, + uint32_t set_number, SpvReflectResult* p_result) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectDescriptorBinding* p_descriptor = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) { + const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index]; + bool found = SearchSortedUint32(p_entry->used_uniforms, p_entry->used_uniform_count, p_potential->spirv_id); + if ((p_potential->binding == binding_number) && (p_potential->set == set_number) && found) { + p_descriptor = p_potential; + break; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_descriptor) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_descriptor; +} + +const SpvReflectDescriptorSet* spvReflectGetDescriptorSet(const SpvReflectShaderModule* p_module, uint32_t set_number, + SpvReflectResult* p_result) { + const SpvReflectDescriptorSet* p_set = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->descriptor_set_count; ++index) { + const SpvReflectDescriptorSet* p_potential = &p_module->descriptor_sets[index]; + if (p_potential->set == set_number) { + p_set = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_set) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_set; +} + +const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet(const SpvReflectShaderModule* p_module, const char* entry_point, + uint32_t set_number, SpvReflectResult* p_result) { + const SpvReflectDescriptorSet* p_set = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t index = 0; index < p_entry->descriptor_set_count; ++index) { + const SpvReflectDescriptorSet* p_potential = &p_entry->descriptor_sets[index]; + if (p_potential->set == set_number) { + p_set = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_set) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_set; +} + +const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation(const SpvReflectShaderModule* p_module, uint32_t location, + SpvReflectResult* p_result) { + if (location == (uint32_t)INVALID_VALUE) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index]; + if (p_potential->location == location) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} +const SpvReflectInterfaceVariable* spvReflectGetInputVariable(const SpvReflectShaderModule* p_module, uint32_t location, + SpvReflectResult* p_result) { + return spvReflectGetInputVariableByLocation(p_module, location, p_result); +} + +const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation(const SpvReflectShaderModule* p_module, + const char* entry_point, uint32_t location, + SpvReflectResult* p_result) { + if (location == (uint32_t)INVALID_VALUE) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index]; + if (p_potential->location == location) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic(const SpvReflectShaderModule* p_module, + const char* semantic, SpvReflectResult* p_result) { + if (IsNull(semantic)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + return NULL; + } + if (semantic[0] == '\0') { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index]; + if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic(const SpvReflectShaderModule* p_module, + const char* entry_point, const char* semantic, + SpvReflectResult* p_result) { + if (IsNull(semantic)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + return NULL; + } + if (semantic[0] == '\0') { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index]; + if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation(const SpvReflectShaderModule* p_module, uint32_t location, + SpvReflectResult* p_result) { + if (location == (uint32_t)INVALID_VALUE) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index]; + if (p_potential->location == location) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} +const SpvReflectInterfaceVariable* spvReflectGetOutputVariable(const SpvReflectShaderModule* p_module, uint32_t location, + SpvReflectResult* p_result) { + return spvReflectGetOutputVariableByLocation(p_module, location, p_result); +} + +const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation(const SpvReflectShaderModule* p_module, + const char* entry_point, uint32_t location, + SpvReflectResult* p_result) { + if (location == (uint32_t)INVALID_VALUE) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index]; + if (p_potential->location == location) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic(const SpvReflectShaderModule* p_module, + const char* semantic, SpvReflectResult* p_result) { + if (IsNull(semantic)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + return NULL; + } + if (semantic[0] == '\0') { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index]; + if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic(const SpvReflectShaderModule* p_module, + const char* entry_point, const char* semantic, + SpvReflectResult* p_result) { + if (IsNull(semantic)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + return NULL; + } + if (semantic[0] == '\0') { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + const SpvReflectInterfaceVariable* p_var = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) { + const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index]; + if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { + p_var = p_potential; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_var) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_var; +} + +const SpvReflectBlockVariable* spvReflectGetPushConstantBlock(const SpvReflectShaderModule* p_module, uint32_t index, + SpvReflectResult* p_result) { + const SpvReflectBlockVariable* p_push_constant = NULL; + if (IsNotNull(p_module)) { + if (index < p_module->push_constant_block_count) { + p_push_constant = &p_module->push_constant_blocks[index]; + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_push_constant) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_push_constant; +} +const SpvReflectBlockVariable* spvReflectGetPushConstant(const SpvReflectShaderModule* p_module, uint32_t index, + SpvReflectResult* p_result) { + return spvReflectGetPushConstantBlock(p_module, index, p_result); +} + +const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock(const SpvReflectShaderModule* p_module, + const char* entry_point, SpvReflectResult* p_result) { + const SpvReflectBlockVariable* p_push_constant = NULL; + if (IsNotNull(p_module)) { + const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + if (IsNotNull(p_result)) { + *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + return NULL; + } + for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) { + bool found = SearchSortedUint32(p_entry->used_push_constants, p_entry->used_push_constant_count, + p_module->push_constant_blocks[i].spirv_id); + if (found) { + p_push_constant = &p_module->push_constant_blocks[i]; + break; + } + } + } + if (IsNotNull(p_result)) { + *p_result = IsNotNull(p_push_constant) + ? SPV_REFLECT_RESULT_SUCCESS + : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + } + return p_push_constant; +} + +SpvReflectResult spvReflectChangeDescriptorBindingNumbers(SpvReflectShaderModule* p_module, + const SpvReflectDescriptorBinding* p_binding, uint32_t new_binding_number, + uint32_t new_set_binding) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_binding)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + SpvReflectDescriptorBinding* p_target_descriptor = NULL; + for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) { + if (&p_module->descriptor_bindings[index] == p_binding) { + p_target_descriptor = &p_module->descriptor_bindings[index]; + break; + } + } + + if (IsNotNull(p_target_descriptor)) { + if (p_target_descriptor->word_offset.binding > (p_module->_internal->spirv_word_count - 1)) { + return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; + } + // Binding number + if (new_binding_number != (uint32_t)SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE) { + uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.binding; + *p_code = new_binding_number; + p_target_descriptor->binding = new_binding_number; + } + // Set number + if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.set; + *p_code = new_set_binding; + p_target_descriptor->set = new_set_binding; + } + } + + SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; + if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + result = SynchronizeDescriptorSets(p_module); + } + return result; +} +SpvReflectResult spvReflectChangeDescriptorBindingNumber(SpvReflectShaderModule* p_module, + const SpvReflectDescriptorBinding* p_descriptor_binding, + uint32_t new_binding_number, uint32_t optional_new_set_number) { + return spvReflectChangeDescriptorBindingNumbers(p_module, p_descriptor_binding, new_binding_number, optional_new_set_number); +} + +SpvReflectResult spvReflectChangeDescriptorSetNumber(SpvReflectShaderModule* p_module, const SpvReflectDescriptorSet* p_set, + uint32_t new_set_number) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_set)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + SpvReflectDescriptorSet* p_target_set = NULL; + for (uint32_t index = 0; index < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++index) { + // The descriptor sets for specific entry points might not be in this set, + // so just match on set index. + if (p_module->descriptor_sets[index].set == p_set->set) { + p_target_set = (SpvReflectDescriptorSet*)p_set; + break; + } + } + + SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; + if (IsNotNull(p_target_set) && new_set_number != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + for (uint32_t index = 0; index < p_target_set->binding_count; ++index) { + SpvReflectDescriptorBinding* p_descriptor = p_target_set->bindings[index]; + if (p_descriptor->word_offset.set > (p_module->_internal->spirv_word_count - 1)) { + return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; + } + + uint32_t* p_code = p_module->_internal->spirv_code + p_descriptor->word_offset.set; + *p_code = new_set_number; + p_descriptor->set = new_set_number; + } + + result = SynchronizeDescriptorSets(p_module); + } + + return result; +} + +static SpvReflectResult ChangeVariableLocation(SpvReflectShaderModule* p_module, SpvReflectInterfaceVariable* p_variable, + uint32_t new_location) { + if (p_variable->word_offset.location > (p_module->_internal->spirv_word_count - 1)) { + return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; + } + uint32_t* p_code = p_module->_internal->spirv_code + p_variable->word_offset.location; + *p_code = new_location; + p_variable->location = new_location; + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectChangeInputVariableLocation(SpvReflectShaderModule* p_module, + const SpvReflectInterfaceVariable* p_input_variable, uint32_t new_location) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_input_variable)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { + if (p_module->input_variables[index] == p_input_variable) { + return ChangeVariableLocation(p_module, p_module->input_variables[index], new_location); + } + } + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; +} + +SpvReflectResult spvReflectChangeOutputVariableLocation(SpvReflectShaderModule* p_module, + const SpvReflectInterfaceVariable* p_output_variable, + uint32_t new_location) { + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_output_variable)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { + if (p_module->output_variables[index] == p_output_variable) { + return ChangeVariableLocation(p_module, p_module->output_variables[index], new_location); + } + } + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; +} + +const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang) { + switch (source_lang) { + case SpvSourceLanguageESSL: + return "ESSL"; + case SpvSourceLanguageGLSL: + return "GLSL"; + case SpvSourceLanguageOpenCL_C: + return "OpenCL_C"; + case SpvSourceLanguageOpenCL_CPP: + return "OpenCL_CPP"; + case SpvSourceLanguageHLSL: + return "HLSL"; + case SpvSourceLanguageCPP_for_OpenCL: + return "CPP_for_OpenCL"; + case SpvSourceLanguageSYCL: + return "SYCL"; + case SpvSourceLanguageHERO_C: + return "Hero C"; + case SpvSourceLanguageNZSL: + return "NZSL"; + case SpvSourceLanguageWGSL: + return "WGSL"; + case SpvSourceLanguageSlang: + return "Slang"; + case SpvSourceLanguageZig: + return "Zig"; + case SpvSourceLanguageRust: + return "Rust"; + default: + break; + } + // The source language is SpvSourceLanguageUnknown, SpvSourceLanguageMax, or + // some other value that does not correspond to a knonwn language. + return "Unknown"; +} + +const char* spvReflectBlockVariableTypeName(const SpvReflectBlockVariable* p_var) { + if (p_var == NULL) { + return NULL; + } + return p_var->type_description->type_name; +} diff --git a/lib/All/SPIRV-Reflect/spirv_reflect.cpp b/lib/All/SPIRV-Reflect/spirv_reflect.cpp new file mode 100644 index 0000000..9f991d6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/spirv_reflect.cpp @@ -0,0 +1,4 @@ +// +// This file exists to force compiling spirv_reflect.c as C++. +// +#include "spirv_reflect.c" \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/spirv_reflect.h b/lib/All/SPIRV-Reflect/spirv_reflect.h new file mode 100644 index 0000000..0d800e3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/spirv_reflect.h @@ -0,0 +1,2467 @@ +/* + Copyright 2017-2022 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + +VERSION HISTORY + + 1.0 (2018-03-27) Initial public release + +*/ + +// clang-format off +/*! + + @file spirv_reflect.h + +*/ +#ifndef SPIRV_REFLECT_H +#define SPIRV_REFLECT_H + +#if defined(SPIRV_REFLECT_USE_SYSTEM_SPIRV_H) +#include +#else +#include "./include/spirv/unified1/spirv.h" +#endif + + +#include +#include + +#ifdef _MSC_VER + #define SPV_REFLECT_DEPRECATED(msg_str) __declspec(deprecated("This symbol is deprecated. Details: " msg_str)) +#elif defined(__clang__) + #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str))) +#elif defined(__GNUC__) + #if GCC_VERSION >= 40500 + #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str))) + #else + #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated)) + #endif +#else + #define SPV_REFLECT_DEPRECATED(msg_str) +#endif + +/*! @enum SpvReflectResult + +*/ +typedef enum SpvReflectResult { + SPV_REFLECT_RESULT_SUCCESS, + SPV_REFLECT_RESULT_NOT_READY, + SPV_REFLECT_RESULT_ERROR_PARSE_FAILED, + SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED, + SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED, + SPV_REFLECT_RESULT_ERROR_NULL_POINTER, + SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR, + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH, + SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER, + SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE, + SPV_REFLECT_RESULT_ERROR_SPIRV_SET_NUMBER_OVERFLOW, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS, + SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION, + SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE, + SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED, +} SpvReflectResult; + +/*! @enum SpvReflectModuleFlagBits + +SPV_REFLECT_MODULE_FLAG_NO_COPY - Disables copying of SPIR-V code + when a SPIRV-Reflect shader module is created. It is the + responsibility of the calling program to ensure that the pointer + remains valid and the memory it's pointing to is not freed while + SPIRV-Reflect operations are taking place. Freeing the backing + memory will cause undefined behavior or most likely a crash. + This is flag is intended for cases where the memory overhead of + storing the copied SPIR-V is undesirable. + +*/ +typedef enum SpvReflectModuleFlagBits { + SPV_REFLECT_MODULE_FLAG_NONE = 0x00000000, + SPV_REFLECT_MODULE_FLAG_NO_COPY = 0x00000001, +} SpvReflectModuleFlagBits; + +typedef uint32_t SpvReflectModuleFlags; + +/*! @enum SpvReflectTypeFlagBits + +*/ +typedef enum SpvReflectTypeFlagBits { + SPV_REFLECT_TYPE_FLAG_UNDEFINED = 0x00000000, + SPV_REFLECT_TYPE_FLAG_VOID = 0x00000001, + SPV_REFLECT_TYPE_FLAG_BOOL = 0x00000002, + SPV_REFLECT_TYPE_FLAG_INT = 0x00000004, + SPV_REFLECT_TYPE_FLAG_FLOAT = 0x00000008, + SPV_REFLECT_TYPE_FLAG_VECTOR = 0x00000100, + SPV_REFLECT_TYPE_FLAG_MATRIX = 0x00000200, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE = 0x00010000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER = 0x00020000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE = 0x00040000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK = 0x00080000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE = 0x00100000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK = 0x00FF0000, + SPV_REFLECT_TYPE_FLAG_STRUCT = 0x10000000, + SPV_REFLECT_TYPE_FLAG_ARRAY = 0x20000000, + SPV_REFLECT_TYPE_FLAG_REF = 0x40000000, +} SpvReflectTypeFlagBits; + +typedef uint32_t SpvReflectTypeFlags; + +/*! @enum SpvReflectDecorationBits + +NOTE: HLSL row_major and column_major decorations are reversed + in SPIR-V. Meaning that matrices declrations with row_major + will get reflected as column_major and vice versa. The + row and column decorations get appied during the compilation. + SPIRV-Reflect reads the data as is and does not make any + attempt to correct it to match what's in the source. + + The Patch, PerVertex, and PerTask are used for Interface + variables that can have array + +*/ +typedef enum SpvReflectDecorationFlagBits { + SPV_REFLECT_DECORATION_NONE = 0x00000000, + SPV_REFLECT_DECORATION_BLOCK = 0x00000001, + SPV_REFLECT_DECORATION_BUFFER_BLOCK = 0x00000002, + SPV_REFLECT_DECORATION_ROW_MAJOR = 0x00000004, + SPV_REFLECT_DECORATION_COLUMN_MAJOR = 0x00000008, + SPV_REFLECT_DECORATION_BUILT_IN = 0x00000010, + SPV_REFLECT_DECORATION_NOPERSPECTIVE = 0x00000020, + SPV_REFLECT_DECORATION_FLAT = 0x00000040, + SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080, + SPV_REFLECT_DECORATION_RELAXED_PRECISION = 0x00000100, + SPV_REFLECT_DECORATION_NON_READABLE = 0x00000200, + SPV_REFLECT_DECORATION_PATCH = 0x00000400, + SPV_REFLECT_DECORATION_PER_VERTEX = 0x00000800, + SPV_REFLECT_DECORATION_PER_TASK = 0x00001000, + SPV_REFLECT_DECORATION_WEIGHT_TEXTURE = 0x00002000, + SPV_REFLECT_DECORATION_BLOCK_MATCH_TEXTURE = 0x00004000, +} SpvReflectDecorationFlagBits; + +typedef uint32_t SpvReflectDecorationFlags; + +// Based of SPV_GOOGLE_user_type +typedef enum SpvReflectUserType { + SPV_REFLECT_USER_TYPE_INVALID = 0, + SPV_REFLECT_USER_TYPE_CBUFFER, + SPV_REFLECT_USER_TYPE_TBUFFER, + SPV_REFLECT_USER_TYPE_APPEND_STRUCTURED_BUFFER, + SPV_REFLECT_USER_TYPE_BUFFER, + SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER, + SPV_REFLECT_USER_TYPE_CONSTANT_BUFFER, + SPV_REFLECT_USER_TYPE_CONSUME_STRUCTURED_BUFFER, + SPV_REFLECT_USER_TYPE_INPUT_PATCH, + SPV_REFLECT_USER_TYPE_OUTPUT_PATCH, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BUFFER, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BYTE_ADDRESS_BUFFER, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_STRUCTURED_BUFFER, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D_ARRAY, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D_ARRAY, + SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_3D, + SPV_REFLECT_USER_TYPE_RAYTRACING_ACCELERATION_STRUCTURE, + SPV_REFLECT_USER_TYPE_RW_BUFFER, + SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER, + SPV_REFLECT_USER_TYPE_RW_STRUCTURED_BUFFER, + SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D, + SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D_ARRAY, + SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D, + SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D_ARRAY, + SPV_REFLECT_USER_TYPE_RW_TEXTURE_3D, + SPV_REFLECT_USER_TYPE_STRUCTURED_BUFFER, + SPV_REFLECT_USER_TYPE_SUBPASS_INPUT, + SPV_REFLECT_USER_TYPE_SUBPASS_INPUT_MS, + SPV_REFLECT_USER_TYPE_TEXTURE_1D, + SPV_REFLECT_USER_TYPE_TEXTURE_1D_ARRAY, + SPV_REFLECT_USER_TYPE_TEXTURE_2D, + SPV_REFLECT_USER_TYPE_TEXTURE_2D_ARRAY, + SPV_REFLECT_USER_TYPE_TEXTURE_2DMS, + SPV_REFLECT_USER_TYPE_TEXTURE_2DMS_ARRAY, + SPV_REFLECT_USER_TYPE_TEXTURE_3D, + SPV_REFLECT_USER_TYPE_TEXTURE_BUFFER, + SPV_REFLECT_USER_TYPE_TEXTURE_CUBE, + SPV_REFLECT_USER_TYPE_TEXTURE_CUBE_ARRAY, +} SpvReflectUserType; + +/*! @enum SpvReflectResourceType + +*/ +typedef enum SpvReflectResourceType { + SPV_REFLECT_RESOURCE_FLAG_UNDEFINED = 0x00000000, + SPV_REFLECT_RESOURCE_FLAG_SAMPLER = 0x00000001, + SPV_REFLECT_RESOURCE_FLAG_CBV = 0x00000002, + SPV_REFLECT_RESOURCE_FLAG_SRV = 0x00000004, + SPV_REFLECT_RESOURCE_FLAG_UAV = 0x00000008, +} SpvReflectResourceType; + +/*! @enum SpvReflectFormat + +*/ +typedef enum SpvReflectFormat { + SPV_REFLECT_FORMAT_UNDEFINED = 0, // = VK_FORMAT_UNDEFINED + SPV_REFLECT_FORMAT_R16_UINT = 74, // = VK_FORMAT_R16_UINT + SPV_REFLECT_FORMAT_R16_SINT = 75, // = VK_FORMAT_R16_SINT + SPV_REFLECT_FORMAT_R16_SFLOAT = 76, // = VK_FORMAT_R16_SFLOAT + SPV_REFLECT_FORMAT_R16G16_UINT = 81, // = VK_FORMAT_R16G16_UINT + SPV_REFLECT_FORMAT_R16G16_SINT = 82, // = VK_FORMAT_R16G16_SINT + SPV_REFLECT_FORMAT_R16G16_SFLOAT = 83, // = VK_FORMAT_R16G16_SFLOAT + SPV_REFLECT_FORMAT_R16G16B16_UINT = 88, // = VK_FORMAT_R16G16B16_UINT + SPV_REFLECT_FORMAT_R16G16B16_SINT = 89, // = VK_FORMAT_R16G16B16_SINT + SPV_REFLECT_FORMAT_R16G16B16_SFLOAT = 90, // = VK_FORMAT_R16G16B16_SFLOAT + SPV_REFLECT_FORMAT_R16G16B16A16_UINT = 95, // = VK_FORMAT_R16G16B16A16_UINT + SPV_REFLECT_FORMAT_R16G16B16A16_SINT = 96, // = VK_FORMAT_R16G16B16A16_SINT + SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT = 97, // = VK_FORMAT_R16G16B16A16_SFLOAT + SPV_REFLECT_FORMAT_R32_UINT = 98, // = VK_FORMAT_R32_UINT + SPV_REFLECT_FORMAT_R32_SINT = 99, // = VK_FORMAT_R32_SINT + SPV_REFLECT_FORMAT_R32_SFLOAT = 100, // = VK_FORMAT_R32_SFLOAT + SPV_REFLECT_FORMAT_R32G32_UINT = 101, // = VK_FORMAT_R32G32_UINT + SPV_REFLECT_FORMAT_R32G32_SINT = 102, // = VK_FORMAT_R32G32_SINT + SPV_REFLECT_FORMAT_R32G32_SFLOAT = 103, // = VK_FORMAT_R32G32_SFLOAT + SPV_REFLECT_FORMAT_R32G32B32_UINT = 104, // = VK_FORMAT_R32G32B32_UINT + SPV_REFLECT_FORMAT_R32G32B32_SINT = 105, // = VK_FORMAT_R32G32B32_SINT + SPV_REFLECT_FORMAT_R32G32B32_SFLOAT = 106, // = VK_FORMAT_R32G32B32_SFLOAT + SPV_REFLECT_FORMAT_R32G32B32A32_UINT = 107, // = VK_FORMAT_R32G32B32A32_UINT + SPV_REFLECT_FORMAT_R32G32B32A32_SINT = 108, // = VK_FORMAT_R32G32B32A32_SINT + SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT = 109, // = VK_FORMAT_R32G32B32A32_SFLOAT + SPV_REFLECT_FORMAT_R64_UINT = 110, // = VK_FORMAT_R64_UINT + SPV_REFLECT_FORMAT_R64_SINT = 111, // = VK_FORMAT_R64_SINT + SPV_REFLECT_FORMAT_R64_SFLOAT = 112, // = VK_FORMAT_R64_SFLOAT + SPV_REFLECT_FORMAT_R64G64_UINT = 113, // = VK_FORMAT_R64G64_UINT + SPV_REFLECT_FORMAT_R64G64_SINT = 114, // = VK_FORMAT_R64G64_SINT + SPV_REFLECT_FORMAT_R64G64_SFLOAT = 115, // = VK_FORMAT_R64G64_SFLOAT + SPV_REFLECT_FORMAT_R64G64B64_UINT = 116, // = VK_FORMAT_R64G64B64_UINT + SPV_REFLECT_FORMAT_R64G64B64_SINT = 117, // = VK_FORMAT_R64G64B64_SINT + SPV_REFLECT_FORMAT_R64G64B64_SFLOAT = 118, // = VK_FORMAT_R64G64B64_SFLOAT + SPV_REFLECT_FORMAT_R64G64B64A64_UINT = 119, // = VK_FORMAT_R64G64B64A64_UINT + SPV_REFLECT_FORMAT_R64G64B64A64_SINT = 120, // = VK_FORMAT_R64G64B64A64_SINT + SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT = 121, // = VK_FORMAT_R64G64B64A64_SFLOAT +} SpvReflectFormat; + +/*! @enum SpvReflectVariableFlagBits + +*/ +enum SpvReflectVariableFlagBits{ + SPV_REFLECT_VARIABLE_FLAGS_NONE = 0x00000000, + SPV_REFLECT_VARIABLE_FLAGS_UNUSED = 0x00000001, + // If variable points to a copy of the PhysicalStorageBuffer struct + SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY = 0x00000002, +}; + +typedef uint32_t SpvReflectVariableFlags; + +/*! @enum SpvReflectDescriptorType + +*/ +typedef enum SpvReflectDescriptorType { + SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER = 0, // = VK_DESCRIPTOR_TYPE_SAMPLER + SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, // = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, // = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, // = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, // = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, // = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC + SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, // = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 // = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR +} SpvReflectDescriptorType; + +/*! @enum SpvReflectShaderStageFlagBits + +*/ +typedef enum SpvReflectShaderStageFlagBits { + SPV_REFLECT_SHADER_STAGE_VERTEX_BIT = 0x00000001, // = VK_SHADER_STAGE_VERTEX_BIT + SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002, // = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT + SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, // = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT + SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, // = VK_SHADER_STAGE_GEOMETRY_BIT + SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, // = VK_SHADER_STAGE_FRAGMENT_BIT + SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT = 0x00000020, // = VK_SHADER_STAGE_COMPUTE_BIT + SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV = 0x00000040, // = VK_SHADER_STAGE_TASK_BIT_NV + SPV_REFLECT_SHADER_STAGE_TASK_BIT_EXT = SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV, // = VK_SHADER_STAGE_CALLABLE_BIT_EXT + SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV = 0x00000080, // = VK_SHADER_STAGE_MESH_BIT_NV + SPV_REFLECT_SHADER_STAGE_MESH_BIT_EXT = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV, // = VK_SHADER_STAGE_CALLABLE_BIT_EXT + SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, // = VK_SHADER_STAGE_RAYGEN_BIT_KHR + SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, // = VK_SHADER_STAGE_ANY_HIT_BIT_KHR + SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, // = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR + SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, // = VK_SHADER_STAGE_MISS_BIT_KHR + SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, // = VK_SHADER_STAGE_INTERSECTION_BIT_KHR + SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, // = VK_SHADER_STAGE_CALLABLE_BIT_KHR + +} SpvReflectShaderStageFlagBits; + +/*! @enum SpvReflectGenerator + +*/ +typedef enum SpvReflectGenerator { + SPV_REFLECT_GENERATOR_KHRONOS_LLVM_SPIRV_TRANSLATOR = 6, + SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_ASSEMBLER = 7, + SPV_REFLECT_GENERATOR_KHRONOS_GLSLANG_REFERENCE_FRONT_END = 8, + SPV_REFLECT_GENERATOR_GOOGLE_SHADERC_OVER_GLSLANG = 13, + SPV_REFLECT_GENERATOR_GOOGLE_SPIREGG = 14, + SPV_REFLECT_GENERATOR_GOOGLE_RSPIRV = 15, + SPV_REFLECT_GENERATOR_X_LEGEND_MESA_MESAIR_SPIRV_TRANSLATOR = 16, + SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_LINKER = 17, + SPV_REFLECT_GENERATOR_WINE_VKD3D_SHADER_COMPILER = 18, + SPV_REFLECT_GENERATOR_CLAY_CLAY_SHADER_COMPILER = 19, + SPV_REFLECT_GENERATOR_SLANG_SHADER_COMPILER = 40, +} SpvReflectGenerator; + +enum { + SPV_REFLECT_MAX_ARRAY_DIMS = 32, + SPV_REFLECT_MAX_DESCRIPTOR_SETS = 64, +}; + +enum { + SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE = ~0, + SPV_REFLECT_SET_NUMBER_DONT_CHANGE = ~0 +}; + +typedef struct SpvReflectNumericTraits { + struct Scalar { + uint32_t width; + uint32_t signedness; + } scalar; + + struct Vector { + uint32_t component_count; + } vector; + + struct Matrix { + uint32_t column_count; + uint32_t row_count; + uint32_t stride; // Measured in bytes + } matrix; +} SpvReflectNumericTraits; + +typedef struct SpvReflectImageTraits { + SpvDim dim; + uint32_t depth; + uint32_t arrayed; + uint32_t ms; // 0: single-sampled; 1: multisampled + uint32_t sampled; + SpvImageFormat image_format; +} SpvReflectImageTraits; + +typedef enum SpvReflectArrayDimType { + SPV_REFLECT_ARRAY_DIM_RUNTIME = 0, // OpTypeRuntimeArray +} SpvReflectArrayDimType; + +typedef struct SpvReflectArrayTraits { + uint32_t dims_count; + // Each entry is either: + // - specialization constant dimension + // - OpTypeRuntimeArray + // - the array length otherwise + uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; + // Stores Ids for dimensions that are specialization constants + uint32_t spec_constant_op_ids[SPV_REFLECT_MAX_ARRAY_DIMS]; + uint32_t stride; // Measured in bytes +} SpvReflectArrayTraits; + +typedef struct SpvReflectBindingArrayTraits { + uint32_t dims_count; + uint32_t dims[SPV_REFLECT_MAX_ARRAY_DIMS]; +} SpvReflectBindingArrayTraits; + +/*! @struct SpvReflectTypeDescription + @brief Information about an OpType* instruction +*/ +typedef struct SpvReflectTypeDescription { + uint32_t id; + SpvOp op; + const char* type_name; + // Non-NULL if type is member of a struct + const char* struct_member_name; + + // The storage class (SpvStorageClass) if the type, and -1 if it does not have a storage class. + int storage_class; + SpvReflectTypeFlags type_flags; + SpvReflectDecorationFlags decoration_flags; + + struct Traits { + SpvReflectNumericTraits numeric; + SpvReflectImageTraits image; + SpvReflectArrayTraits array; + } traits; + + // If underlying type is a struct (ex. array of structs) + // this gives access to the OpTypeStruct + struct SpvReflectTypeDescription* struct_type_description; + + // Some pointers to SpvReflectTypeDescription are really + // just copies of another reference to the same OpType + uint32_t copied; + + // @deprecated use struct_type_description instead + uint32_t member_count; + // @deprecated use struct_type_description instead + struct SpvReflectTypeDescription* members; +} SpvReflectTypeDescription; + + +/*! @struct SpvReflectInterfaceVariable + @brief The OpVariable that is either an Input or Output to the module +*/ +typedef struct SpvReflectInterfaceVariable { + uint32_t spirv_id; + const char* name; + uint32_t location; + uint32_t component; + SpvStorageClass storage_class; + const char* semantic; + SpvReflectDecorationFlags decoration_flags; + + // The builtin id (SpvBuiltIn) if the variable is a builtin, and -1 otherwise. + int built_in; + SpvReflectNumericTraits numeric; + SpvReflectArrayTraits array; + + uint32_t member_count; + struct SpvReflectInterfaceVariable* members; + + SpvReflectFormat format; + + // NOTE: SPIR-V shares type references for variables + // that have the same underlying type. This means + // that the same type name will appear for multiple + // variables. + SpvReflectTypeDescription* type_description; + + struct { + uint32_t location; + } word_offset; +} SpvReflectInterfaceVariable; + +/*! @struct SpvReflectBlockVariable + +*/ +typedef struct SpvReflectBlockVariable { + uint32_t spirv_id; + const char* name; + // For Push Constants, this is the lowest offset of all memebers + uint32_t offset; // Measured in bytes + uint32_t absolute_offset; // Measured in bytes + uint32_t size; // Measured in bytes + uint32_t padded_size; // Measured in bytes + SpvReflectDecorationFlags decoration_flags; + SpvReflectNumericTraits numeric; + SpvReflectArrayTraits array; + SpvReflectVariableFlags flags; + + uint32_t member_count; + struct SpvReflectBlockVariable* members; + + SpvReflectTypeDescription* type_description; + + struct { + uint32_t offset; + } word_offset; + +} SpvReflectBlockVariable; + +/*! @struct SpvReflectDescriptorBinding + +*/ +typedef struct SpvReflectDescriptorBinding { + uint32_t spirv_id; + const char* name; + uint32_t binding; + uint32_t input_attachment_index; + uint32_t set; + SpvReflectDescriptorType descriptor_type; + SpvReflectResourceType resource_type; + SpvReflectImageTraits image; + SpvReflectBlockVariable block; + SpvReflectBindingArrayTraits array; + uint32_t count; + uint32_t accessed; + uint32_t uav_counter_id; + struct SpvReflectDescriptorBinding* uav_counter_binding; + uint32_t byte_address_buffer_offset_count; + uint32_t* byte_address_buffer_offsets; + + SpvReflectTypeDescription* type_description; + + struct { + uint32_t binding; + uint32_t set; + } word_offset; + + SpvReflectDecorationFlags decoration_flags; + // Requires SPV_GOOGLE_user_type + SpvReflectUserType user_type; +} SpvReflectDescriptorBinding; + +/*! @struct SpvReflectDescriptorSet + +*/ +typedef struct SpvReflectDescriptorSet { + uint32_t set; + uint32_t binding_count; + SpvReflectDescriptorBinding** bindings; +} SpvReflectDescriptorSet; + +typedef enum SpvReflectExecutionModeValue { + SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT = (int)0xFFFFFFFF // specialization constant +} SpvReflectExecutionModeValue; + +/*! @struct SpvReflectEntryPoint + + */ +typedef struct SpvReflectEntryPoint { + const char* name; + uint32_t id; + + SpvExecutionModel spirv_execution_model; + SpvReflectShaderStageFlagBits shader_stage; + + uint32_t input_variable_count; + SpvReflectInterfaceVariable** input_variables; + uint32_t output_variable_count; + SpvReflectInterfaceVariable** output_variables; + uint32_t interface_variable_count; + SpvReflectInterfaceVariable* interface_variables; + + uint32_t descriptor_set_count; + SpvReflectDescriptorSet* descriptor_sets; + + uint32_t used_uniform_count; + uint32_t* used_uniforms; + uint32_t used_push_constant_count; + uint32_t* used_push_constants; + + uint32_t execution_mode_count; + SpvExecutionMode* execution_modes; + + struct LocalSize { + uint32_t x; + uint32_t y; + uint32_t z; + } local_size; + uint32_t invocations; // valid for geometry + uint32_t output_vertices; // valid for geometry, tesselation +} SpvReflectEntryPoint; + +/*! @struct SpvReflectCapability + +*/ +typedef struct SpvReflectCapability { + SpvCapability value; + uint32_t word_offset; +} SpvReflectCapability; + + +/*! @struct SpvReflectSpecId + +*/ +typedef struct SpvReflectSpecializationConstant { + uint32_t spirv_id; + uint32_t constant_id; + const char* name; + SpvReflectTypeDescription* type_description; + + // Size of the default value in bytes (always a multiple of 4). + // Will be 4 for 8/16/32-bit constants and 8 for 64-bit constants. + uint32_t default_value_size; + + // Pointer to the raw default value data. + // The interpretation of this data depends on type_description->op: + // - SpvOpSpecConstantTrue: size = 4, data = uint32_t(1) + // - SpvOpSpecConstantFalse: size = 4, data = uint32_t(0) + // - SpvOpSpecConstant: data contains the bit pattern of the default value + // * The type will be a scalar integer or float. + // * Types 32 bits wide or smaller take one word. + // * Larger types take multiple words, with low-order words appearing first. + void* default_value; +} SpvReflectSpecializationConstant; + +/*! @struct SpvReflectShaderModule + +*/ +typedef struct SpvReflectShaderModule { + SpvReflectGenerator generator; + const char* entry_point_name; + uint32_t entry_point_id; + uint32_t entry_point_count; + SpvReflectEntryPoint* entry_points; + SpvSourceLanguage source_language; + uint32_t source_language_version; + const char* source_file; + const char* source_source; + uint32_t capability_count; + SpvReflectCapability* capabilities; + SpvExecutionModel spirv_execution_model; // Uses value(s) from first entry point + SpvReflectShaderStageFlagBits shader_stage; // Uses value(s) from first entry point + uint32_t descriptor_binding_count; // Uses value(s) from first entry point + SpvReflectDescriptorBinding* descriptor_bindings; // Uses value(s) from first entry point + uint32_t descriptor_set_count; // Uses value(s) from first entry point + SpvReflectDescriptorSet descriptor_sets[SPV_REFLECT_MAX_DESCRIPTOR_SETS]; // Uses value(s) from first entry point + uint32_t input_variable_count; // Uses value(s) from first entry point + SpvReflectInterfaceVariable** input_variables; // Uses value(s) from first entry point + uint32_t output_variable_count; // Uses value(s) from first entry point + SpvReflectInterfaceVariable** output_variables; // Uses value(s) from first entry point + uint32_t interface_variable_count; // Uses value(s) from first entry point + SpvReflectInterfaceVariable* interface_variables; // Uses value(s) from first entry point + uint32_t push_constant_block_count; // Uses value(s) from first entry point + SpvReflectBlockVariable* push_constant_blocks; // Uses value(s) from first entry point + uint32_t spec_constant_count; // Uses value(s) from first entry point + SpvReflectSpecializationConstant* spec_constants; // Uses value(s) from first entry point + + struct Internal { + SpvReflectModuleFlags module_flags; + size_t spirv_size; + uint32_t* spirv_code; + uint32_t spirv_word_count; + + size_t type_description_count; + SpvReflectTypeDescription* type_descriptions; + } * _internal; + +} SpvReflectShaderModule; + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! @fn spvReflectCreateShaderModule + + @param size Size in bytes of SPIR-V code. + @param p_code Pointer to SPIR-V code. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @return SPV_REFLECT_RESULT_SUCCESS on success. + +*/ +SpvReflectResult spvReflectCreateShaderModule( + size_t size, + const void* p_code, + SpvReflectShaderModule* p_module +); + +/*! @fn spvReflectCreateShaderModule2 + + @param flags Flags for module creations. + @param size Size in bytes of SPIR-V code. + @param p_code Pointer to SPIR-V code. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @return SPV_REFLECT_RESULT_SUCCESS on success. + +*/ +SpvReflectResult spvReflectCreateShaderModule2( + SpvReflectModuleFlags flags, + size_t size, + const void* p_code, + SpvReflectShaderModule* p_module +); + +SPV_REFLECT_DEPRECATED("renamed to spvReflectCreateShaderModule") +SpvReflectResult spvReflectGetShaderModule( + size_t size, + const void* p_code, + SpvReflectShaderModule* p_module +); + + +/*! @fn spvReflectDestroyShaderModule + + @param p_module Pointer to an instance of SpvReflectShaderModule. + +*/ +void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module); + + +/*! @fn spvReflectGetCodeSize + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @return Returns the size of the SPIR-V in bytes + +*/ +uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module); + + +/*! @fn spvReflectGetCode + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @return Returns a const pointer to the compiled SPIR-V bytecode. + +*/ +const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module); + +/*! @fn spvReflectGetEntryPoint + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point Name of the requested entry point. + @return Returns a const pointer to the requested entry point, + or NULL if it's not found. +*/ +const SpvReflectEntryPoint* spvReflectGetEntryPoint( + const SpvReflectShaderModule* p_module, + const char* entry_point +); + +/*! @fn spvReflectEnumerateDescriptorBindings + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_bindings is NULL, the module's descriptor binding + count (across all descriptor sets) will be stored here. + If pp_bindings is not NULL, *p_count must contain the + module's descriptor binding count. + @param pp_bindings If NULL, the module's total descriptor binding count + will be written to *p_count. + If non-NULL, pp_bindings must point to an array with + *p_count entries, where pointers to the module's + descriptor bindings will be written. The caller must not + free the binding pointers written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateDescriptorBindings( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectDescriptorBinding** pp_bindings +); + +/*! @fn spvReflectEnumerateEntryPointDescriptorBindings + @brief Creates a listing of all descriptor bindings that are used in the + static call tree of the given entry point. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The name of the entry point to get the descriptor bindings for. + @param p_count If pp_bindings is NULL, the entry point's descriptor binding + count (across all descriptor sets) will be stored here. + If pp_bindings is not NULL, *p_count must contain the + entry points's descriptor binding count. + @param pp_bindings If NULL, the entry point's total descriptor binding count + will be written to *p_count. + If non-NULL, pp_bindings must point to an array with + *p_count entries, where pointers to the entry point's + descriptor bindings will be written. The caller must not + free the binding pointers written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectDescriptorBinding** pp_bindings +); + +/*! @fn spvReflectEnumerateDescriptorSets + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_sets is NULL, the module's descriptor set + count will be stored here. + If pp_sets is not NULL, *p_count must contain the + module's descriptor set count. + @param pp_sets If NULL, the module's total descriptor set count + will be written to *p_count. + If non-NULL, pp_sets must point to an array with + *p_count entries, where pointers to the module's + descriptor sets will be written. The caller must not + free the descriptor set pointers written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateDescriptorSets( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectDescriptorSet** pp_sets +); + +/*! @fn spvReflectEnumerateEntryPointDescriptorSets + @brief Creates a listing of all descriptor sets and their bindings that are + used in the static call tree of a given entry point. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The name of the entry point to get the descriptor bindings for. + @param p_count If pp_sets is NULL, the module's descriptor set + count will be stored here. + If pp_sets is not NULL, *p_count must contain the + module's descriptor set count. + @param pp_sets If NULL, the module's total descriptor set count + will be written to *p_count. + If non-NULL, pp_sets must point to an array with + *p_count entries, where pointers to the module's + descriptor sets will be written. The caller must not + free the descriptor set pointers written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectDescriptorSet** pp_sets +); + + +/*! @fn spvReflectEnumerateInterfaceVariables + @brief If the module contains multiple entry points, this will only get + the interface variables for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the module's interface variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the module's interface variable count. + @param pp_variables If NULL, the module's interface variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the module's + interface variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateInterfaceVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + +/*! @fn spvReflectEnumerateEntryPointInterfaceVariables + @brief Enumerate the interface variables for a given entry point. + @param entry_point The name of the entry point to get the interface variables for. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the entry point's interface variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the entry point's interface variable count. + @param pp_variables If NULL, the entry point's interface variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the entry point's + interface variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + + +/*! @fn spvReflectEnumerateInputVariables + @brief If the module contains multiple entry points, this will only get + the input variables for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the module's input variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the module's input variable count. + @param pp_variables If NULL, the module's input variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the module's + input variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateInputVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + +/*! @fn spvReflectEnumerateEntryPointInputVariables + @brief Enumerate the input variables for a given entry point. + @param entry_point The name of the entry point to get the input variables for. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the entry point's input variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the entry point's input variable count. + @param pp_variables If NULL, the entry point's input variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the entry point's + input variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointInputVariables( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + + +/*! @fn spvReflectEnumerateOutputVariables + @brief Note: If the module contains multiple entry points, this will only get + the output variables for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the module's output variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the module's output variable count. + @param pp_variables If NULL, the module's output variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the module's + output variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateOutputVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + +/*! @fn spvReflectEnumerateEntryPointOutputVariables + @brief Enumerate the output variables for a given entry point. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The name of the entry point to get the output variables for. + @param p_count If pp_variables is NULL, the entry point's output variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the entry point's output variable count. + @param pp_variables If NULL, the entry point's output variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the entry point's + output variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointOutputVariables( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + + +/*! @fn spvReflectEnumeratePushConstantBlocks + @brief Note: If the module contains multiple entry points, this will only get + the push constant blocks for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_blocks is NULL, the module's push constant + block count will be stored here. + If pp_blocks is not NULL, *p_count must + contain the module's push constant block count. + @param pp_blocks If NULL, the module's push constant block count + will be written to *p_count. + If non-NULL, pp_blocks must point to an + array with *p_count entries, where pointers to + the module's push constant blocks will be written. + The caller must not free the block variables written + to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumeratePushConstantBlocks( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks +); +SPV_REFLECT_DEPRECATED("renamed to spvReflectEnumeratePushConstantBlocks") +SpvReflectResult spvReflectEnumeratePushConstants( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks +); + +/*! @fn spvReflectEnumerateEntryPointPushConstantBlocks + @brief Enumerate the push constant blocks used in the static call tree of a + given entry point. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_blocks is NULL, the entry point's push constant + block count will be stored here. + If pp_blocks is not NULL, *p_count must + contain the entry point's push constant block count. + @param pp_blocks If NULL, the entry point's push constant block count + will be written to *p_count. + If non-NULL, pp_blocks must point to an + array with *p_count entries, where pointers to + the entry point's push constant blocks will be written. + The caller must not free the block variables written + to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks +); + + +/*! @fn spvReflectEnumerateSpecializationConstants + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_blocks is NULL, the module's specialization constant + count will be stored here. If pp_blocks is not NULL, *p_count + must contain the module's specialization constant count. + @param pp_constants If NULL, the module's specialization constant count + will be written to *p_count. If non-NULL, pp_blocks must + point to an array with *p_count entries, where pointers to + the module's specialization constant blocks will be written. + The caller must not free the variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the failure. +*/ +SpvReflectResult spvReflectEnumerateSpecializationConstants( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectSpecializationConstant** pp_constants +); + +/*! @fn spvReflectGetDescriptorBinding + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param binding_number The "binding" value of the requested descriptor + binding. + @param set_number The "set" value of the requested descriptor binding. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains a descriptor binding that + matches the provided [binding_number, set_number] + values, a pointer to that binding is returned. The + caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note If the module contains multiple desriptor bindings + with the same set and binding numbers, there are + no guarantees about which binding will be returned. + +*/ +const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding( + const SpvReflectShaderModule* p_module, + uint32_t binding_number, + uint32_t set_number, + SpvReflectResult* p_result +); + +/*! @fn spvReflectGetEntryPointDescriptorBinding + @brief Get the descriptor binding with the given binding number and set + number that is used in the static call tree of a certain entry + point. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the binding from. + @param binding_number The "binding" value of the requested descriptor + binding. + @param set_number The "set" value of the requested descriptor binding. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains a descriptor binding that + matches the provided [binding_number, set_number] + values, a pointer to that binding is returned. The + caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note If the entry point contains multiple desriptor bindings + with the same set and binding numbers, there are + no guarantees about which binding will be returned. + +*/ +const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t binding_number, + uint32_t set_number, + SpvReflectResult* p_result +); + + +/*! @fn spvReflectGetDescriptorSet + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param set_number The "set" value of the requested descriptor set. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains a descriptor set with the + provided set_number, a pointer to that set is + returned. The caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. + +*/ +const SpvReflectDescriptorSet* spvReflectGetDescriptorSet( + const SpvReflectShaderModule* p_module, + uint32_t set_number, + SpvReflectResult* p_result +); + +/*! @fn spvReflectGetEntryPointDescriptorSet + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the descriptor set from. + @param set_number The "set" value of the requested descriptor set. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains a descriptor set with the + provided set_number, a pointer to that set is + returned. The caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. + +*/ +const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t set_number, + SpvReflectResult* p_result +); + + +/* @fn spvReflectGetInputVariableByLocation + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param location The "location" value of the requested input variable. + A location of 0xFFFFFFFF will always return NULL + with *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains an input interface variable + with the provided location value, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation( + const SpvReflectShaderModule* p_module, + uint32_t location, + SpvReflectResult* p_result +); +SPV_REFLECT_DEPRECATED("renamed to spvReflectGetInputVariableByLocation") +const SpvReflectInterfaceVariable* spvReflectGetInputVariable( + const SpvReflectShaderModule* p_module, + uint32_t location, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetEntryPointInputVariableByLocation + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the input variable from. + @param location The "location" value of the requested input variable. + A location of 0xFFFFFFFF will always return NULL + with *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains an input interface variable + with the provided location value, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t location, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetInputVariableBySemantic + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param semantic The "semantic" value of the requested input variable. + A semantic of NULL will return NULL. + A semantic of "" will always return NULL with + *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains an input interface variable + with the provided semantic, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic( + const SpvReflectShaderModule* p_module, + const char* semantic, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetEntryPointInputVariableBySemantic + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the input variable from. + @param semantic The "semantic" value of the requested input variable. + A semantic of NULL will return NULL. + A semantic of "" will always return NULL with + *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains an input interface variable + with the provided semantic, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic( + const SpvReflectShaderModule* p_module, + const char* entry_point, + const char* semantic, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetOutputVariableByLocation + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param location The "location" value of the requested output variable. + A location of 0xFFFFFFFF will always return NULL + with *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains an output interface variable + with the provided location value, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation( + const SpvReflectShaderModule* p_module, + uint32_t location, + SpvReflectResult* p_result +); +SPV_REFLECT_DEPRECATED("renamed to spvReflectGetOutputVariableByLocation") +const SpvReflectInterfaceVariable* spvReflectGetOutputVariable( + const SpvReflectShaderModule* p_module, + uint32_t location, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetEntryPointOutputVariableByLocation + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the output variable from. + @param location The "location" value of the requested output variable. + A location of 0xFFFFFFFF will always return NULL + with *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains an output interface variable + with the provided location value, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t location, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetOutputVariableBySemantic + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param semantic The "semantic" value of the requested output variable. + A semantic of NULL will return NULL. + A semantic of "" will always return NULL with + *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the module contains an output interface variable + with the provided semantic, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic( + const SpvReflectShaderModule* p_module, + const char* semantic, + SpvReflectResult* p_result +); + +/* @fn spvReflectGetEntryPointOutputVariableBySemantic + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the output variable from. + @param semantic The "semantic" value of the requested output variable. + A semantic of NULL will return NULL. + A semantic of "" will always return NULL with + *p_result == ELEMENT_NOT_FOUND. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the entry point contains an output interface variable + with the provided semantic, a pointer to that + variable is returned. The caller must not free this + pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. +@note + +*/ +const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic( + const SpvReflectShaderModule* p_module, + const char* entry_point, + const char* semantic, + SpvReflectResult* p_result +); + +/*! @fn spvReflectGetPushConstantBlock + + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param index The index of the desired block within the module's + array of push constant blocks. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the provided index is within range, a pointer to + the corresponding push constant block is returned. + The caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. + +*/ +const SpvReflectBlockVariable* spvReflectGetPushConstantBlock( + const SpvReflectShaderModule* p_module, + uint32_t index, + SpvReflectResult* p_result +); +SPV_REFLECT_DEPRECATED("renamed to spvReflectGetPushConstantBlock") +const SpvReflectBlockVariable* spvReflectGetPushConstant( + const SpvReflectShaderModule* p_module, + uint32_t index, + SpvReflectResult* p_result +); + +/*! @fn spvReflectGetEntryPointPushConstantBlock + @brief Get the push constant block corresponding to the given entry point. + As by the Vulkan specification there can be no more than one push + constant block used by a given entry point, so if there is one it will + be returned, otherwise NULL will be returned. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param entry_point The entry point to get the push constant block from. + @param p_result If successful, SPV_REFLECT_RESULT_SUCCESS will be + written to *p_result. Otherwise, a error code + indicating the cause of the failure will be stored + here. + @return If the provided index is within range, a pointer to + the corresponding push constant block is returned. + The caller must not free this pointer. + If no match can be found, or if an unrelated error + occurs, the return value will be NULL. Detailed + error results are written to *pResult. + +*/ +const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock( + const SpvReflectShaderModule* p_module, + const char* entry_point, + SpvReflectResult* p_result +); + + +/*! @fn spvReflectChangeDescriptorBindingNumbers + @brief Assign new set and/or binding numbers to a descriptor binding. + In addition to updating the reflection data, this function modifies + the underlying SPIR-V bytecode. The updated code can be retrieved + with spvReflectGetCode(). If the binding is used in multiple + entry points within the module, it will be changed in all of them. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_binding Pointer to the descriptor binding to modify. + @param new_binding_number The new binding number to assign to the + provided descriptor binding. + To leave the binding number unchanged, pass + SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE. + @param new_set_number The new set number to assign to the + provided descriptor binding. Successfully changing + a descriptor binding's set number invalidates all + existing SpvReflectDescriptorBinding and + SpvReflectDescriptorSet pointers from this module. + To leave the set number unchanged, pass + SPV_REFLECT_SET_NUMBER_DONT_CHANGE. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of + the failure. +*/ +SpvReflectResult spvReflectChangeDescriptorBindingNumbers( + SpvReflectShaderModule* p_module, + const SpvReflectDescriptorBinding* p_binding, + uint32_t new_binding_number, + uint32_t new_set_number +); +SPV_REFLECT_DEPRECATED("Renamed to spvReflectChangeDescriptorBindingNumbers") +SpvReflectResult spvReflectChangeDescriptorBindingNumber( + SpvReflectShaderModule* p_module, + const SpvReflectDescriptorBinding* p_descriptor_binding, + uint32_t new_binding_number, + uint32_t optional_new_set_number +); + +/*! @fn spvReflectChangeDescriptorSetNumber + @brief Assign a new set number to an entire descriptor set (including + all descriptor bindings in that set). + In addition to updating the reflection data, this function modifies + the underlying SPIR-V bytecode. The updated code can be retrieved + with spvReflectGetCode(). If the descriptor set is used in + multiple entry points within the module, it will be modified in all + of them. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_set Pointer to the descriptor binding to modify. + @param new_set_number The new set number to assign to the + provided descriptor set, and all its descriptor + bindings. Successfully changing a descriptor + binding's set number invalidates all existing + SpvReflectDescriptorBinding and + SpvReflectDescriptorSet pointers from this module. + To leave the set number unchanged, pass + SPV_REFLECT_SET_NUMBER_DONT_CHANGE. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of + the failure. +*/ +SpvReflectResult spvReflectChangeDescriptorSetNumber( + SpvReflectShaderModule* p_module, + const SpvReflectDescriptorSet* p_set, + uint32_t new_set_number +); + +/*! @fn spvReflectChangeInputVariableLocation + @brief Assign a new location to an input interface variable. + In addition to updating the reflection data, this function modifies + the underlying SPIR-V bytecode. The updated code can be retrieved + with spvReflectGetCode(). + It is the caller's responsibility to avoid assigning the same + location to multiple input variables. If the input variable is used + by multiple entry points in the module, it will be changed in all of + them. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_input_variable Pointer to the input variable to update. + @param new_location The new location to assign to p_input_variable. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of + the failure. + +*/ +SpvReflectResult spvReflectChangeInputVariableLocation( + SpvReflectShaderModule* p_module, + const SpvReflectInterfaceVariable* p_input_variable, + uint32_t new_location +); + + +/*! @fn spvReflectChangeOutputVariableLocation + @brief Assign a new location to an output interface variable. + In addition to updating the reflection data, this function modifies + the underlying SPIR-V bytecode. The updated code can be retrieved + with spvReflectGetCode(). + It is the caller's responsibility to avoid assigning the same + location to multiple output variables. If the output variable is used + by multiple entry points in the module, it will be changed in all of + them. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_output_variable Pointer to the output variable to update. + @param new_location The new location to assign to p_output_variable. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of + the failure. + +*/ +SpvReflectResult spvReflectChangeOutputVariableLocation( + SpvReflectShaderModule* p_module, + const SpvReflectInterfaceVariable* p_output_variable, + uint32_t new_location +); + + +/*! @fn spvReflectSourceLanguage + + @param source_lang The source language code. + @return Returns string of source language specified in \a source_lang. + The caller must not free the memory associated with this string. +*/ +const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang); + +/*! @fn spvReflectBlockVariableTypeName + + @param p_var Pointer to block variable. + @return Returns string of block variable's type description type name + or NULL if p_var is NULL. +*/ +const char* spvReflectBlockVariableTypeName( + const SpvReflectBlockVariable* p_var +); + +#if defined(__cplusplus) +}; +#endif + +#if defined(__cplusplus) && !defined(SPIRV_REFLECT_DISABLE_CPP_BINDINGS) +#include +#include +#include + +namespace spv_reflect { + +/*! \class ShaderModule + +*/ +class ShaderModule { +public: + ShaderModule(); + ShaderModule(size_t size, const void* p_code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE); + ShaderModule(const std::vector& code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE); + ShaderModule(const std::vector& code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE); + ~ShaderModule(); + + ShaderModule(ShaderModule&& other); + ShaderModule& operator=(ShaderModule&& other); + + SpvReflectResult GetResult() const; + + const SpvReflectShaderModule& GetShaderModule() const; + + uint32_t GetCodeSize() const; + const uint32_t* GetCode() const; + + const char* GetEntryPointName() const; + + const char* GetSourceFile() const; + + uint32_t GetEntryPointCount() const; + const char* GetEntryPointName(uint32_t index) const; + SpvReflectShaderStageFlagBits GetEntryPointShaderStage(uint32_t index) const; + + SpvReflectShaderStageFlagBits GetShaderStage() const; + SPV_REFLECT_DEPRECATED("Renamed to GetShaderStage") + SpvReflectShaderStageFlagBits GetVulkanShaderStage() const { + return GetShaderStage(); + } + + SpvReflectResult EnumerateDescriptorBindings(uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const; + SpvReflectResult EnumerateEntryPointDescriptorBindings(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const; + SpvReflectResult EnumerateDescriptorSets( uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ; + SpvReflectResult EnumerateEntryPointDescriptorSets(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ; + SpvReflectResult EnumerateInterfaceVariables(uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointInterfaceVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateInputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointInputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateOutputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointOutputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumeratePushConstantBlocks(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const; + SpvReflectResult EnumerateEntryPointPushConstantBlocks(const char* entry_point, uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const; + SPV_REFLECT_DEPRECATED("Renamed to EnumeratePushConstantBlocks") + SpvReflectResult EnumeratePushConstants(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const { + return EnumeratePushConstantBlocks(p_count, pp_blocks); + } + SpvReflectResult EnumerateSpecializationConstants(uint32_t* p_count, SpvReflectSpecializationConstant** pp_constants) const; + + const SpvReflectDescriptorBinding* GetDescriptorBinding(uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const; + const SpvReflectDescriptorBinding* GetEntryPointDescriptorBinding(const char* entry_point, uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const; + const SpvReflectDescriptorSet* GetDescriptorSet(uint32_t set_number, SpvReflectResult* p_result = nullptr) const; + const SpvReflectDescriptorSet* GetEntryPointDescriptorSet(const char* entry_point, uint32_t set_number, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetInputVariableByLocation(uint32_t location, SpvReflectResult* p_result = nullptr) const; + SPV_REFLECT_DEPRECATED("Renamed to GetInputVariableByLocation") + const SpvReflectInterfaceVariable* GetInputVariable(uint32_t location, SpvReflectResult* p_result = nullptr) const { + return GetInputVariableByLocation(location, p_result); + } + const SpvReflectInterfaceVariable* GetEntryPointInputVariableByLocation(const char* entry_point, uint32_t location, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetInputVariableBySemantic(const char* semantic, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetEntryPointInputVariableBySemantic(const char* entry_point, const char* semantic, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetOutputVariableByLocation(uint32_t location, SpvReflectResult* p_result = nullptr) const; + SPV_REFLECT_DEPRECATED("Renamed to GetOutputVariableByLocation") + const SpvReflectInterfaceVariable* GetOutputVariable(uint32_t location, SpvReflectResult* p_result = nullptr) const { + return GetOutputVariableByLocation(location, p_result); + } + const SpvReflectInterfaceVariable* GetEntryPointOutputVariableByLocation(const char* entry_point, uint32_t location, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetOutputVariableBySemantic(const char* semantic, SpvReflectResult* p_result = nullptr) const; + const SpvReflectInterfaceVariable* GetEntryPointOutputVariableBySemantic(const char* entry_point, const char* semantic, SpvReflectResult* p_result = nullptr) const; + const SpvReflectBlockVariable* GetPushConstantBlock(uint32_t index, SpvReflectResult* p_result = nullptr) const; + SPV_REFLECT_DEPRECATED("Renamed to GetPushConstantBlock") + const SpvReflectBlockVariable* GetPushConstant(uint32_t index, SpvReflectResult* p_result = nullptr) const { + return GetPushConstantBlock(index, p_result); + } + const SpvReflectBlockVariable* GetEntryPointPushConstantBlock(const char* entry_point, SpvReflectResult* p_result = nullptr) const; + + SpvReflectResult ChangeDescriptorBindingNumbers(const SpvReflectDescriptorBinding* p_binding, + uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE, + uint32_t optional_new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE); + SPV_REFLECT_DEPRECATED("Renamed to ChangeDescriptorBindingNumbers") + SpvReflectResult ChangeDescriptorBindingNumber(const SpvReflectDescriptorBinding* p_binding, uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE, + uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + return ChangeDescriptorBindingNumbers(p_binding, new_binding_number, new_set_number); + } + SpvReflectResult ChangeDescriptorSetNumber(const SpvReflectDescriptorSet* p_set, uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE); + SpvReflectResult ChangeInputVariableLocation(const SpvReflectInterfaceVariable* p_input_variable, uint32_t new_location); + SpvReflectResult ChangeOutputVariableLocation(const SpvReflectInterfaceVariable* p_output_variable, uint32_t new_location); + +private: + // Make noncopyable + ShaderModule(const ShaderModule&); + ShaderModule& operator=(const ShaderModule&); + +private: + mutable SpvReflectResult m_result = SPV_REFLECT_RESULT_NOT_READY; + SpvReflectShaderModule m_module = {}; +}; + + +// ================================================================================================= +// ShaderModule +// ================================================================================================= + +/*! @fn ShaderModule + +*/ +inline ShaderModule::ShaderModule() {} + + +/*! @fn ShaderModule + + @param size + @param p_code + +*/ +inline ShaderModule::ShaderModule(size_t size, const void* p_code, SpvReflectModuleFlags flags) { + m_result = spvReflectCreateShaderModule2( + flags, + size, + p_code, + &m_module); +} + +/*! @fn ShaderModule + + @param code + +*/ +inline ShaderModule::ShaderModule(const std::vector& code, SpvReflectModuleFlags flags) { + m_result = spvReflectCreateShaderModule2( + flags, + code.size(), + code.data(), + &m_module); +} + +/*! @fn ShaderModule + + @param code + +*/ +inline ShaderModule::ShaderModule(const std::vector& code, SpvReflectModuleFlags flags) { + m_result = spvReflectCreateShaderModule2( + flags, + code.size() * sizeof(uint32_t), + code.data(), + &m_module); +} + +/*! @fn ~ShaderModule + +*/ +inline ShaderModule::~ShaderModule() { + spvReflectDestroyShaderModule(&m_module); +} + + +inline ShaderModule::ShaderModule(ShaderModule&& other) +{ + *this = std::move(other); +} + +inline ShaderModule& ShaderModule::operator=(ShaderModule&& other) +{ + m_result = std::move(other.m_result); + m_module = std::move(other.m_module); + + other.m_module = {}; + return *this; +} + +/*! @fn GetResult + + @return + +*/ +inline SpvReflectResult ShaderModule::GetResult() const { + return m_result; +} + + +/*! @fn GetShaderModule + + @return + +*/ +inline const SpvReflectShaderModule& ShaderModule::GetShaderModule() const { + return m_module; +} + + +/*! @fn GetCodeSize + + @return + + */ +inline uint32_t ShaderModule::GetCodeSize() const { + return spvReflectGetCodeSize(&m_module); +} + + +/*! @fn GetCode + + @return + +*/ +inline const uint32_t* ShaderModule::GetCode() const { + return spvReflectGetCode(&m_module); +} + + +/*! @fn GetEntryPoint + + @return Returns entry point + +*/ +inline const char* ShaderModule::GetEntryPointName() const { + return this->GetEntryPointName(0); +} + +/*! @fn GetSourceFile + + @return Returns source file + +*/ +inline const char* ShaderModule::GetSourceFile() const { + return m_module.source_file; +} + +/*! @fn GetEntryPointCount + + @param + @return +*/ +inline uint32_t ShaderModule::GetEntryPointCount() const { + return m_module.entry_point_count; +} + +/*! @fn GetEntryPointName + + @param index + @return +*/ +inline const char* ShaderModule::GetEntryPointName(uint32_t index) const { + return m_module.entry_points[index].name; +} + +/*! @fn GetEntryPointShaderStage + + @param index + @return Returns the shader stage for the entry point at \b index +*/ +inline SpvReflectShaderStageFlagBits ShaderModule::GetEntryPointShaderStage(uint32_t index) const { + return m_module.entry_points[index].shader_stage; +} + +/*! @fn GetShaderStage + + @return Returns shader stage for the first entry point + +*/ +inline SpvReflectShaderStageFlagBits ShaderModule::GetShaderStage() const { + return m_module.shader_stage; +} + +/*! @fn EnumerateDescriptorBindings + + @param count + @param p_binding_numbers + @param pp_bindings + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateDescriptorBindings( + uint32_t* p_count, + SpvReflectDescriptorBinding** pp_bindings +) const +{ + m_result = spvReflectEnumerateDescriptorBindings( + &m_module, + p_count, + pp_bindings); + return m_result; +} + +/*! @fn EnumerateEntryPointDescriptorBindings + + @param entry_point + @param count + @param pp_bindings + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorBindings( + const char* entry_point, + uint32_t* p_count, + SpvReflectDescriptorBinding** pp_bindings +) const +{ + m_result = spvReflectEnumerateEntryPointDescriptorBindings( + &m_module, + entry_point, + p_count, + pp_bindings); + return m_result; +} + + +/*! @fn EnumerateDescriptorSets + + @param count + @param pp_sets + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateDescriptorSets( + uint32_t* p_count, + SpvReflectDescriptorSet** pp_sets +) const +{ + m_result = spvReflectEnumerateDescriptorSets( + &m_module, + p_count, + pp_sets); + return m_result; +} + +/*! @fn EnumerateEntryPointDescriptorSets + + @param entry_point + @param count + @param pp_sets + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorSets( + const char* entry_point, + uint32_t* p_count, + SpvReflectDescriptorSet** pp_sets +) const +{ + m_result = spvReflectEnumerateEntryPointDescriptorSets( + &m_module, + entry_point, + p_count, + pp_sets); + return m_result; +} + + +/*! @fn EnumerateInterfaceVariables + + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateInterfaceVariables( + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateInterfaceVariables( + &m_module, + p_count, + pp_variables); + return m_result; +} + +/*! @fn EnumerateEntryPointInterfaceVariables + + @param entry_point + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointInterfaceVariables( + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateEntryPointInterfaceVariables( + &m_module, + entry_point, + p_count, + pp_variables); + return m_result; +} + + +/*! @fn EnumerateInputVariables + + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateInputVariables( + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateInputVariables( + &m_module, + p_count, + pp_variables); + return m_result; +} + +/*! @fn EnumerateEntryPointInputVariables + + @param entry_point + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointInputVariables( + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateEntryPointInputVariables( + &m_module, + entry_point, + p_count, + pp_variables); + return m_result; +} + + +/*! @fn EnumerateOutputVariables + + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateOutputVariables( + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateOutputVariables( + &m_module, + p_count, + pp_variables); + return m_result; +} + +/*! @fn EnumerateEntryPointOutputVariables + + @param entry_point + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointOutputVariables( + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateEntryPointOutputVariables( + &m_module, + entry_point, + p_count, + pp_variables); + return m_result; +} + + +/*! @fn EnumeratePushConstantBlocks + + @param count + @param pp_blocks + @return + +*/ +inline SpvReflectResult ShaderModule::EnumeratePushConstantBlocks( + uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks +) const +{ + m_result = spvReflectEnumeratePushConstantBlocks( + &m_module, + p_count, + pp_blocks); + return m_result; +} + +/*! @fn EnumerateSpecializationConstants + @param p_count + @param pp_constants + @return +*/ +inline SpvReflectResult ShaderModule::EnumerateSpecializationConstants( + uint32_t* p_count, + SpvReflectSpecializationConstant** pp_constants +) const +{ + m_result = spvReflectEnumerateSpecializationConstants( + &m_module, + p_count, + pp_constants + ); + return m_result; +} + +/*! @fn EnumerateEntryPointPushConstantBlocks + + @param entry_point + @param count + @param pp_blocks + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointPushConstantBlocks( + const char* entry_point, + uint32_t* p_count, + SpvReflectBlockVariable** pp_blocks +) const +{ + m_result = spvReflectEnumerateEntryPointPushConstantBlocks( + &m_module, + entry_point, + p_count, + pp_blocks); + return m_result; +} + + +/*! @fn GetDescriptorBinding + + @param binding_number + @param set_number + @param p_result + @return + +*/ +inline const SpvReflectDescriptorBinding* ShaderModule::GetDescriptorBinding( + uint32_t binding_number, + uint32_t set_number, + SpvReflectResult* p_result +) const +{ + return spvReflectGetDescriptorBinding( + &m_module, + binding_number, + set_number, + p_result); +} + +/*! @fn GetEntryPointDescriptorBinding + + @param entry_point + @param binding_number + @param set_number + @param p_result + @return + +*/ +inline const SpvReflectDescriptorBinding* ShaderModule::GetEntryPointDescriptorBinding( + const char* entry_point, + uint32_t binding_number, + uint32_t set_number, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointDescriptorBinding( + &m_module, + entry_point, + binding_number, + set_number, + p_result); +} + + +/*! @fn GetDescriptorSet + + @param set_number + @param p_result + @return + +*/ +inline const SpvReflectDescriptorSet* ShaderModule::GetDescriptorSet( + uint32_t set_number, + SpvReflectResult* p_result +) const +{ + return spvReflectGetDescriptorSet( + &m_module, + set_number, + p_result); +} + +/*! @fn GetEntryPointDescriptorSet + + @param entry_point + @param set_number + @param p_result + @return + +*/ +inline const SpvReflectDescriptorSet* ShaderModule::GetEntryPointDescriptorSet( + const char* entry_point, + uint32_t set_number, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointDescriptorSet( + &m_module, + entry_point, + set_number, + p_result); +} + + +/*! @fn GetInputVariable + + @param location + @param p_result + @return + +*/ +inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableByLocation( + uint32_t location, + SpvReflectResult* p_result +) const +{ + return spvReflectGetInputVariableByLocation( + &m_module, + location, + p_result); +} +inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableBySemantic( + const char* semantic, + SpvReflectResult* p_result +) const +{ + return spvReflectGetInputVariableBySemantic( + &m_module, + semantic, + p_result); +} + +/*! @fn GetEntryPointInputVariable + + @param entry_point + @param location + @param p_result + @return + +*/ +inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableByLocation( + const char* entry_point, + uint32_t location, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointInputVariableByLocation( + &m_module, + entry_point, + location, + p_result); +} +inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableBySemantic( + const char* entry_point, + const char* semantic, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointInputVariableBySemantic( + &m_module, + entry_point, + semantic, + p_result); +} + + +/*! @fn GetOutputVariable + + @param location + @param p_result + @return + +*/ +inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableByLocation( + uint32_t location, + SpvReflectResult* p_result +) const +{ + return spvReflectGetOutputVariableByLocation( + &m_module, + location, + p_result); +} +inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableBySemantic( + const char* semantic, + SpvReflectResult* p_result +) const +{ + return spvReflectGetOutputVariableBySemantic(&m_module, + semantic, + p_result); +} + +/*! @fn GetEntryPointOutputVariable + + @param entry_point + @param location + @param p_result + @return + +*/ +inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableByLocation( + const char* entry_point, + uint32_t location, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointOutputVariableByLocation( + &m_module, + entry_point, + location, + p_result); +} +inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableBySemantic( + const char* entry_point, + const char* semantic, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointOutputVariableBySemantic( + &m_module, + entry_point, + semantic, + p_result); +} + + +/*! @fn GetPushConstant + + @param index + @param p_result + @return + +*/ +inline const SpvReflectBlockVariable* ShaderModule::GetPushConstantBlock( + uint32_t index, + SpvReflectResult* p_result +) const +{ + return spvReflectGetPushConstantBlock( + &m_module, + index, + p_result); +} + +/*! @fn GetEntryPointPushConstant + + @param entry_point + @param index + @param p_result + @return + +*/ +inline const SpvReflectBlockVariable* ShaderModule::GetEntryPointPushConstantBlock( + const char* entry_point, + SpvReflectResult* p_result +) const +{ + return spvReflectGetEntryPointPushConstantBlock( + &m_module, + entry_point, + p_result); +} + + +/*! @fn ChangeDescriptorBindingNumbers + + @param p_binding + @param new_binding_number + @param new_set_number + @return + +*/ +inline SpvReflectResult ShaderModule::ChangeDescriptorBindingNumbers( + const SpvReflectDescriptorBinding* p_binding, + uint32_t new_binding_number, + uint32_t new_set_number +) +{ + return spvReflectChangeDescriptorBindingNumbers( + &m_module, + p_binding, + new_binding_number, + new_set_number); +} + + +/*! @fn ChangeDescriptorSetNumber + + @param p_set + @param new_set_number + @return + +*/ +inline SpvReflectResult ShaderModule::ChangeDescriptorSetNumber( + const SpvReflectDescriptorSet* p_set, + uint32_t new_set_number +) +{ + return spvReflectChangeDescriptorSetNumber( + &m_module, + p_set, + new_set_number); +} + + +/*! @fn ChangeInputVariableLocation + + @param p_input_variable + @param new_location + @return + +*/ +inline SpvReflectResult ShaderModule::ChangeInputVariableLocation( + const SpvReflectInterfaceVariable* p_input_variable, + uint32_t new_location) +{ + return spvReflectChangeInputVariableLocation( + &m_module, + p_input_variable, + new_location); +} + + +/*! @fn ChangeOutputVariableLocation + + @param p_input_variable + @param new_location + @return + +*/ +inline SpvReflectResult ShaderModule::ChangeOutputVariableLocation( + const SpvReflectInterfaceVariable* p_output_variable, + uint32_t new_location) +{ + return spvReflectChangeOutputVariableLocation( + &m_module, + p_output_variable, + new_location); +} + +} // namespace spv_reflect +#endif // defined(__cplusplus) && !defined(SPIRV_REFLECT_DISABLE_CPP_WRAPPER) +#endif // SPIRV_REFLECT_H + +// clang-format on diff --git a/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv new file mode 100644 index 0000000..5e4ea59 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv.yaml b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv.yaml new file mode 100644 index 0000000..4649512 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.spv.yaml @@ -0,0 +1,357 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 14 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 22 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 30 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 38 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 46 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 10 + name: "a" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 76 # VK_FORMAT_R16_SFLOAT + type_description: *td0 + word_offset: { location: 122 } + - &iv1 + spirv_id: 18 + name: "b" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 90 # VK_FORMAT_R16G16B16_SFLOAT + type_description: *td1 + word_offset: { location: 130 } + - &iv2 + spirv_id: 26 + name: "c" + location: 2 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 74 # VK_FORMAT_R16_UINT + type_description: *td2 + word_offset: { location: 138 } + - &iv3 + spirv_id: 34 + name: "d" + location: 3 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 88 # VK_FORMAT_R16G16B16_UINT + type_description: *td3 + word_offset: { location: 146 } + - &iv4 + spirv_id: 42 + name: "e" + location: 4 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 75 # VK_FORMAT_R16_SINT + type_description: *td4 + word_offset: { location: 154 } + - &iv5 + spirv_id: 50 + name: "f" + location: 5 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 89 # VK_FORMAT_R16G16B16_SINT + type_description: *td5 + word_offset: { location: 162 } + - &iv6 + spirv_id: 8 + name: "_a" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 76 # VK_FORMAT_R16_SFLOAT + type_description: *td0 + word_offset: { location: 118 } + - &iv7 + spirv_id: 16 + name: "_b" + location: 1 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 90 # VK_FORMAT_R16G16B16_SFLOAT + type_description: *td1 + word_offset: { location: 126 } + - &iv8 + spirv_id: 24 + name: "_c" + location: 2 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 74 # VK_FORMAT_R16_UINT + type_description: *td2 + word_offset: { location: 134 } + - &iv9 + spirv_id: 32 + name: "_d" + location: 3 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 88 # VK_FORMAT_R16G16B16_UINT + type_description: *td3 + word_offset: { location: 142 } + - &iv10 + spirv_id: 40 + name: "_e" + location: 4 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 75 # VK_FORMAT_R16_SINT + type_description: *td4 + word_offset: { location: 150 } + - &iv11 + spirv_id: 48 + name: "_f" + location: 5 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 16, signedness: 1 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 89 # VK_FORMAT_R16G16B16_SINT + type_description: *td5 + word_offset: { location: 158 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 6, + input_variables: + - *iv0 # "a" + - *iv1 # "b" + - *iv2 # "c" + - *iv3 # "d" + - *iv4 # "e" + - *iv5 # "f" + output_variable_count: 6, + output_variables: + - *iv6 # "_a" + - *iv7 # "_b" + - *iv8 # "_c" + - *iv9 # "_d" + - *iv10 # "_e" + - *iv11 # "_f" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.vert b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.vert new file mode 100644 index 0000000..4a018ae --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/16bit/vert_in_out_16.vert @@ -0,0 +1,27 @@ +#version 450 +#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require +#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require + +layout(location = 0) in float16_t a; +layout(location = 1) in f16vec3 b; +layout(location = 2) in uint16_t c; +layout(location = 3) in u16vec3 d; +layout(location = 4) in int16_t e; +layout(location = 5) in i16vec3 f; + +layout(location = 0) out float16_t _a; +layout(location = 1) out f16vec3 _b; +layout(location = 2) out uint16_t _c; +layout(location = 3) out u16vec3 _d; +layout(location = 4) out int16_t _e; +layout(location = 5) out i16vec3 _f; + +void main() +{ + _a = a * float16_t(2.0); + _b = b * f16vec3(2.0); + _c = c * 2us; + _d = d * u16vec3(2); + _e = e * 2s; + _f = f * i16vec3(2); +} diff --git a/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv b/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv new file mode 100644 index 0000000..400c365 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv.yaml b/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv.yaml new file mode 100644 index 0000000..360f5d4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/access_chains/array_length_from_access_chain.spv.yaml @@ -0,0 +1,152 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 4 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 3 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 4 + absolute_offset: 4 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 43, set: 39 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.slang b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.slang new file mode 100644 index 0000000..6514f21 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.slang @@ -0,0 +1,13 @@ +uniform uint* data_ptr; // creates a ptr chain access + +struct Data{ + int x; +} +uniform Data* data_struct; + +[numthreads(1,1,1)] +void computeMain() +{ + data_ptr[0] = 1; + data_struct->x = 1; +} diff --git a/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv new file mode 100644 index 0000000..8ab03e9 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv.yaml new file mode 100644 index 0000000..7f78149 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/access_chains/pointer_access_chain_phy_storage_buffer.spv.yaml @@ -0,0 +1,204 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 32 + type_name: + struct_member_name: + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 19 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 5 + op: 32 + type_name: + struct_member_name: + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 6 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td2 + - &td4 + id: 19 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv2 + name: + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 86, set: 90 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/build_all_shaders.py b/lib/All/SPIRV-Reflect/tests/build_all_shaders.py new file mode 100644 index 0000000..1203876 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/build_all_shaders.py @@ -0,0 +1,73 @@ +# Usage: +# python tests/build_all_shaders.py +import argparse +import os +import pathlib +import shutil +import subprocess +import sys + +def my_which(cmd): + if sys.hexversion >= 0x03030000: + return shutil.which(cmd) + else: + try: + subprocess.check_output([cmd], stderr=subprocess.STDOUT) + return cmd + except subprocess.CalledProcessError: + return cmd # that's fine, it exists though + except OSError: + return None + +shaders = [ + {'source':"glsl/built_in_format.glsl", 'entry':"main", 'stage':'vert'}, + {'source':"glsl/buffer_pointer.glsl", 'entry':"main", 'stage':'frag', 'target-env':'vulkan1.3'}, + {'source':"glsl/input_attachment.glsl", 'entry':"main", 'stage':'frag'}, + {'source':"glsl/texel_buffer.glsl", 'entry':"main", 'stage':'vert'}, + {'source':"glsl/storage_buffer.glsl", 'entry':"main", 'stage':'comp', 'target-env':'vulkan1.1'}, + {'source':"glsl/runtime_array_of_array_of_struct.glsl", 'entry':"main", 'stage':'comp'}, + + {'source':"hlsl/append_consume.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, + {'source':"hlsl/binding_array.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, + {'source':"hlsl/binding_types.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, + {'source':"hlsl/cbuffer.hlsl", 'entry':"main", 'profile':'vs_6_0', 'stage':'vert'}, + {'source':"hlsl/counter_buffers.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, + {'source':"hlsl/semantics.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, + {'source':"hlsl/user_type.hlsl", 'entry':"main", 'profile':'ps_6_0', 'stage':'frag'}, +] + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Compile test shaders") + parser.add_argument("--glslc", help="path to glslc compiler", default=my_which("glslc")) + parser.add_argument("--dxc", help="path to dxc compiler", default=my_which("dxc")) + parser.add_argument("--verbose", "-v", help="enable verbose output", action='store_true') + args = parser.parse_args() + + test_dir = pathlib.Path(__file__).parent.resolve() + root_dir = test_dir.parent.resolve() + + if not args.dxc: + print("WARNING: dxc not found in PATH; HLSL shaders will be compiled with glslc.") + if not args.glslc: + print("WARNING: glslc not found in PATH. This is a bad sign.") + for shader in shaders: + src_path = os.path.join(test_dir, shader['source']) + base, ext = os.path.splitext(src_path) + spv_path = base + ".spv" + if ext.lower() == ".glsl" or (ext.lower() == ".hlsl" and not args.dxc): + compile_cmd_args = [args.glslc, "-g", "-fshader-stage=" + shader['stage'], "-fentry-point=" + shader['entry'], "-o", spv_path, src_path] + if 'target-env' in shader: + compile_cmd_args.append("--target-env=" + shader['target-env']) + elif ext.lower() == ".hlsl": + compile_cmd_args = [args.dxc, "-spirv", "-Zi", "-fspv-reflect", "-O0", "-T", shader['profile'], "-E", shader['entry'], "-Fo", spv_path, src_path] + + print("%s -> %s" % (src_path, spv_path)) + if args.verbose: + print(" ".join(compile_cmd_args)) + + try: + compile_cmd_output = subprocess.check_output(compile_cmd_args, stderr = subprocess.STDOUT) + except subprocess.CalledProcessError as error: + print("Compilation failed for %s with error code %d:\n%s" % (src_path, error.returncode, error.output.decode('utf-8'))) + + print("") diff --git a/lib/All/SPIRV-Reflect/tests/build_golden_yaml.py b/lib/All/SPIRV-Reflect/tests/build_golden_yaml.py new file mode 100644 index 0000000..e030f29 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/build_golden_yaml.py @@ -0,0 +1,72 @@ +# Usage: +# Prereq: build spirv-reflect +# Prereq: build shader SPVs +# python tests/build_golden_yaml.py +import argparse +import os +import pathlib +import platform +import subprocess +import sys + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate golden YAML from test shader .spv files") + parser.add_argument("--verbose", "-v", help="enable verbose output", action='store_true') + args = parser.parse_args() + + print("""\ +WARNING: This script regenerates the golden YAML output for all test shaders. +The new YAML will be considered the expected correct output for future test +runs. Before commiting the updated YAML to GitHub, it is therefore critical +to carefully inspect the diffs between the old and new YAML output, to ensure +that all differences can be traced back to intentional changes to either the +reflection code or the test shaders. +""") + + test_dir = pathlib.Path(__file__).parent.resolve() + root_dir = test_dir.parent.resolve() + + spirv_reflect_exe_paths_windows = [ + os.path.join(root_dir, "bin", "Debug", "spirv-reflect.exe"), + os.path.join(root_dir, "bin", "Release", "spirv-reflect.exe"), + ] + spirv_reflect_exe_paths_unix = [ + os.path.join(root_dir, "bin", "spirv-reflect"), + ] + spirv_reflect_exe = None + if platform.system() == "Windows": + for path in spirv_reflect_exe_paths_windows: + if os.path.isfile(path): + spirv_reflect_exe = path + break + else: + for path in spirv_reflect_exe_paths_unix: + if os.path.isfile(path): + spirv_reflect_exe = path + break + + if spirv_reflect_exe is None: + exit("spirv-reflect executable not found!") + + spv_paths = [] + for root, dirs, files in os.walk(test_dir): + for f in files: + base, ext = os.path.splitext(f) + if ext.lower() == ".spv": + spv_paths.append(os.path.normpath(os.path.join(root, f))) + + for spv_path in spv_paths: + yaml_path = spv_path + ".yaml" + try: + # TODO Replace hard-coded EXE path with something less brittle. + yaml_cmd_args = [spirv_reflect_exe, "-y", "-v", "1", spv_path] + if args.verbose: + print(" ".join(yaml_cmd_args)) + subprocess.run(yaml_cmd_args, stdout=open(yaml_path, "w")) + subprocess.run(yaml_cmd_args) + print("%s -> %s" % (spv_path, yaml_path)) + except NameError: + print("spirv-reflect application not found; did you build it first?") + sys.exit() + except subprocess.CalledProcessError as error: + print("YAML generation failed with error code %d:\n%s" % (error.returncode, error.output.decode('utf-8'))) diff --git a/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.hlsl b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.hlsl new file mode 100644 index 0000000..de17f13 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.hlsl @@ -0,0 +1,198 @@ +struct ColorDesc { + float R; + float2 RG; + float3 RGB; + float4 RGBA; +}; + +cbuffer MyParams : register(b0) +{ + float4x4 MvpMatrix; + float4x4 NotUsedNormalMatrix; + float3 Offset; + float ScalarScale; + + float2 Vector2ScaleX; + float2 Vector2ScaleY; + float2 Vector2ScaleXY; + + float2 Vector2ScaleXXXX; + float2 Vector2ScaleXYXY; + + float3 Vector3ScaleX; + float3 Vector3ScaleY; + float3 Vector3ScaleZ; + float3 Vector3ScaleXZ; + float3 Vector3ScaleXYZ; + + float3 Vector3ScaleXX; + float3 Vector3ScaleYZX; + float3 Vector3ScaleZZZZ; + + float4 Vector4ScaleX; + float4 Vector4ScaleY; + float4 Vector4ScaleZ; + float4 Vector4ScaleW; + float4 Vector4ScaleXY; + float4 Vector4ScaleXZ; + float4 Vector4ScaleYZ; + float4 Vector4ScaleXZW; + float4 Vector4ScaleYZW; + float4 Vector4ScaleXYZW; + + float NotUsed1; + float2 NotUsed2; + float3 NotUsed3; + float3 MoreOffset; + float2 NotUsed4; + float3 NotUsed5; + float3 LastOffset; + float3 NotUsed6; + + float ScalarArray[4]; + float2 Vector2Array[4]; + float3 Vector3Array[4]; + float4 Vector4Array[4]; + + float2 Vector2ArrayX[4]; + float3 Vector3ArrayX[4]; + float4 Vector4ArrayX[4]; + + float2 NotUsedVectorArray[4]; + + ColorDesc ColorArray[8][7][6][5][4][3][2]; + float ScalarMultiDimArray[8][7][6][5][4][3][2]; + float2 Vector2MultiDimArray[8][7][6][5][4][3][2]; + float3 Vector3MultiDimArray[8][7][6][5][4][3][2]; + float4 Vector4MultiDimArray[8][7][6][5][4][3][2]; + float2 Vector2MultiDimArrayX[8][7][6][5][4][3][2]; + float3 Vector3MultiDimArrayX[8][7][6][5][4][3][2]; + float4 Vector4MultiDimArrayX[8][7][6][5][4][3][2]; + float2 NotUsedVector2MultiDimArrayY[8][7][6][5][4][3][2]; + float3 NotUsedVector3MultiDimArrayY[8][7][6][5][4][3][2]; + float4 NotUsedVector4MultiDimArrayY[8][7][6][5][4][3][2]; + float3 Vector3MultiDimArrayZ[8][7][6][5][4][3][2]; + float4 Vector4MultiDimArrayZ[8][7][6][5][4][3][2]; + + float2 Vector2MultiDimArrayXYX[8][7][6][5][4][3][2]; + float3 Vector3MultiDimArrayXYX[8][7][6][5][4][3][2]; + float4 Vector4MultiDimArrayXYX[8][7][6][5][4][3][2]; + +} + +struct NestedUsedParams { + float NotUsed; + float3 Offset; + float4x4 NotUsedMatrix; +}; + +struct NestedNotUsedParams { + float NotUsed1; + float2 NotUsed2; + float3 NotUsed3; +}; + +struct UsedParams { + float3 Position; + float3 NotUsedColor; + float3 Normal; + NestedNotUsedParams NotUsedNested; + NestedUsedParams UsedNested; + float NotUsed1; + ColorDesc ColorArray[4]; +}; + +struct NotUsedParams { + float NotUsed1; + float2 NotUsed2; + float3 NotUsed3; + NestedNotUsedParams NotUsedNested; +}; + +struct UsedComponents { + float3 ScaleByX; +}; + +struct Params2 { + float4 PostTransformOffset; + float NotUsedScale; + float3 Mask; + UsedParams Used; + NotUsedParams NotUsed; + UsedComponents Components; +}; + +ConstantBuffer MyParams2 : register(b1); + +float4 main(float3 Position : Position) : SV_POSITION +{ + float4 result = mul(MvpMatrix, float4(Position + Offset, 1)) + MyParams2.PostTransformOffset; + //float4 result = (float4)1; + + result.x *= ScalarScale; + + result.y *= Vector2ScaleX.x; + result.x *= Vector2ScaleY.y; + result.yx *= Vector2ScaleXY.xy; + + result.xyzw *= Vector2ScaleXXXX.xxxx; + result.xyzw *= Vector2ScaleXYXY.xyxy; + + result.z *= Vector3ScaleX.x; + result.y *= Vector3ScaleY.y; + result.x *= Vector3ScaleZ.z; + result.xy *= Vector3ScaleXZ.xz; + result.xyz *= Vector3ScaleXYZ.xyz; + + result.xy *= Vector3ScaleXX.xx; + result.xyz *= Vector3ScaleYZX.yzx; + result.xyzw *= Vector3ScaleZZZZ.zzzz; + + result.x *= Vector4ScaleX.w; + result.y *= Vector4ScaleY.y; + result.z *= Vector4ScaleZ.z; + result.w *= Vector4ScaleW.x; + result.xy *= Vector4ScaleXY.xy; + result.xz *= Vector4ScaleXZ.xz; + result.xy *= Vector4ScaleYZ.yz; + result.xyz *= Vector4ScaleXZW.xzw; + result.yzw *= Vector4ScaleYZW.yzw; + result.xyzw *= Vector4ScaleXYZW.xyzw; + + result *= ScalarArray[0]; + result.xy *= Vector2Array[1]; + result.xyz *= Vector3Array[2]; + result.xyzw *= Vector4Array[3]; + + result.x *= Vector2ArrayX[1].x; + result.x *= Vector3ArrayX[2].x; + result.x *= Vector4ArrayX[3].x; + + result.xyz *= ColorArray[7][6][5][4][3][2][1].RGB; + result.x *= ScalarMultiDimArray[7][6][5][4][3][2][1]; + result.xy *= Vector2MultiDimArray[7][6][5][4][3][2][1]; + result.xyz *= Vector3MultiDimArray[7][6][5][4][3][2][1]; + result.xyzw *= Vector4MultiDimArray[7][6][5][4][3][2][1]; + result.xy *= Vector2MultiDimArrayX[7][6][5][4][3][2][1].x; + result.xyz *= Vector3MultiDimArrayX[7][6][5][4][3][2][1].x; + result.xyzw *= Vector4MultiDimArrayX[7][6][5][4][3][2][1].x; + result.xyz *= Vector3MultiDimArrayZ[7][6][5][4][3][2][1].z; + result.xyzw *= Vector4MultiDimArrayZ[7][6][5][4][3][2][1].z; + + + result.xyz *= Vector2MultiDimArrayXYX[7][6][5][4][3][2][1].xyx; + result.xyz *= Vector3MultiDimArrayXYX[7][6][5][4][3][2][1].xyx; + result.xyz *= Vector4MultiDimArrayXYX[7][6][5][4][3][2][1].xyx; + + result.xyz *= MyParams2.Mask; + result.xyz *= MyParams2.Used.Position; + result.xyz += MyParams2.Used.Normal; + result.xyz += MoreOffset; + result.xyz += LastOffset; + result.xyz += MyParams2.Used.UsedNested.Offset; + result.xyz *= MyParams2.Components.ScaleByX.x; + result.xyzw += MyParams2.Used.ColorArray[3].RGBA; + result.y *= MyParams2.Used.ColorArray[3].RGB.x; + + return result; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv new file mode 100644 index 0000000..77ac3a7 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv.yaml b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv.yaml new file mode 100644 index 0000000..317b24c --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/cbuffer_unused/cbuffer_unused_001.spv.yaml @@ -0,0 +1,3496 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 107 + op: 24 + type_name: + struct_member_name: "MvpMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 107 + op: 24 + type_name: + struct_member_name: "NotUsedNormalMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 108 + op: 23 + type_name: + struct_member_name: "Offset" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 57 + op: 22 + type_name: + struct_member_name: "ScalarScale" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 109 + op: 23 + type_name: + struct_member_name: "Vector2ScaleX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 109 + op: 23 + type_name: + struct_member_name: "Vector2ScaleY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 109 + op: 23 + type_name: + struct_member_name: "Vector2ScaleXY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 109 + op: 23 + type_name: + struct_member_name: "Vector2ScaleXXXX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 109 + op: 23 + type_name: + struct_member_name: "Vector2ScaleXYXY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleXZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleXYZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleXX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleYZX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 108 + op: 23 + type_name: + struct_member_name: "Vector3ScaleZZZZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleW" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleXY" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleXZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleYZ" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleXZW" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleYZW" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 106 + op: 23 + type_name: + struct_member_name: "Vector4ScaleXYZW" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td27 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td28 + id: 109 + op: 23 + type_name: + struct_member_name: "NotUsed2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td29 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed3" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td30 + id: 108 + op: 23 + type_name: + struct_member_name: "MoreOffset" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td31 + id: 109 + op: 23 + type_name: + struct_member_name: "NotUsed4" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td32 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed5" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td33 + id: 108 + op: 23 + type_name: + struct_member_name: "LastOffset" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td34 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed6" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td35 + id: 14 + op: 28 + type_name: + struct_member_name: "ScalarArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td36 + id: 15 + op: 28 + type_name: + struct_member_name: "Vector2Array" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td37 + id: 16 + op: 28 + type_name: + struct_member_name: "Vector3Array" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td38 + id: 17 + op: 28 + type_name: + struct_member_name: "Vector4Array" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td39 + id: 15 + op: 28 + type_name: + struct_member_name: "Vector2ArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td40 + id: 16 + op: 28 + type_name: + struct_member_name: "Vector3ArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td41 + id: 17 + op: 28 + type_name: + struct_member_name: "Vector4ArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td42 + id: 15 + op: 28 + type_name: + struct_member_name: "NotUsedVectorArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 16 } + member_count: 0 + members: + - &td43 + id: 57 + op: 22 + type_name: + struct_member_name: "R" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td44 + id: 109 + op: 23 + type_name: + struct_member_name: "RG" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td45 + id: 108 + op: 23 + type_name: + struct_member_name: "RGB" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td46 + id: 106 + op: 23 + type_name: + struct_member_name: "RGBA" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td47 + id: 24 + op: 28 + type_name: "ColorDesc" + struct_member_name: "ColorArray" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 48 } + member_count: 4 + members: + - *td43 + - *td44 + - *td45 + - *td46 + - &td48 + id: 31 + op: 28 + type_name: + struct_member_name: "ScalarMultiDimArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td49 + id: 38 + op: 28 + type_name: + struct_member_name: "Vector2MultiDimArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td50 + id: 45 + op: 28 + type_name: + struct_member_name: "Vector3MultiDimArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td51 + id: 52 + op: 28 + type_name: + struct_member_name: "Vector4MultiDimArray" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td52 + id: 38 + op: 28 + type_name: + struct_member_name: "Vector2MultiDimArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td53 + id: 45 + op: 28 + type_name: + struct_member_name: "Vector3MultiDimArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td54 + id: 52 + op: 28 + type_name: + struct_member_name: "Vector4MultiDimArrayX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td55 + id: 38 + op: 28 + type_name: + struct_member_name: "NotUsedVector2MultiDimArrayY" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td56 + id: 45 + op: 28 + type_name: + struct_member_name: "NotUsedVector3MultiDimArrayY" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td57 + id: 52 + op: 28 + type_name: + struct_member_name: "NotUsedVector4MultiDimArrayY" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td58 + id: 45 + op: 28 + type_name: + struct_member_name: "Vector3MultiDimArrayZ" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td59 + id: 52 + op: 28 + type_name: + struct_member_name: "Vector4MultiDimArrayZ" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td60 + id: 38 + op: 28 + type_name: + struct_member_name: "Vector2MultiDimArrayXYX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td61 + id: 45 + op: 28 + type_name: + struct_member_name: "Vector3MultiDimArrayXYX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td62 + id: 52 + op: 28 + type_name: + struct_member_name: "Vector4MultiDimArrayXYX" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + member_count: 0 + members: + - &td63 + id: 4 + op: 30 + type_name: "type.MyParams" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 59 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - *td10 + - *td11 + - *td12 + - *td13 + - *td14 + - *td15 + - *td16 + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - *td24 + - *td25 + - *td26 + - *td27 + - *td28 + - *td29 + - *td30 + - *td31 + - *td32 + - *td33 + - *td34 + - *td35 + - *td36 + - *td37 + - *td38 + - *td39 + - *td40 + - *td41 + - *td42 + - *td47 + - *td48 + - *td49 + - *td50 + - *td51 + - *td52 + - *td53 + - *td54 + - *td55 + - *td56 + - *td57 + - *td58 + - *td59 + - *td60 + - *td61 + - *td62 + - &td64 + id: 106 + op: 23 + type_name: + struct_member_name: "PostTransformOffset" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td65 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsedScale" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td66 + id: 108 + op: 23 + type_name: + struct_member_name: "Mask" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td67 + id: 108 + op: 23 + type_name: + struct_member_name: "Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td68 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsedColor" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td69 + id: 108 + op: 23 + type_name: + struct_member_name: "Normal" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td70 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td71 + id: 109 + op: 23 + type_name: + struct_member_name: "NotUsed2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td72 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed3" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td73 + id: 9 + op: 30 + type_name: "NestedNotUsedParams" + struct_member_name: "NotUsedNested" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td70 + - *td71 + - *td72 + - &td74 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td75 + id: 108 + op: 23 + type_name: + struct_member_name: "Offset" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td76 + id: 107 + op: 24 + type_name: + struct_member_name: "NotUsedMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td77 + id: 10 + op: 30 + type_name: "NestedUsedParams" + struct_member_name: "UsedNested" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td74 + - *td75 + - *td76 + - &td78 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td79 + id: 57 + op: 22 + type_name: + struct_member_name: "R" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td80 + id: 109 + op: 23 + type_name: + struct_member_name: "RG" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td81 + id: 108 + op: 23 + type_name: + struct_member_name: "RGB" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td82 + id: 106 + op: 23 + type_name: + struct_member_name: "RGBA" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td83 + id: 53 + op: 28 + type_name: "ColorDesc" + struct_member_name: "ColorArray" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 48 } + member_count: 4 + members: + - *td79 + - *td80 + - *td81 + - *td82 + - &td84 + id: 8 + op: 30 + type_name: "UsedParams" + struct_member_name: "Used" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 7 + members: + - *td67 + - *td68 + - *td69 + - *td73 + - *td77 + - *td78 + - *td83 + - &td85 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td86 + id: 109 + op: 23 + type_name: + struct_member_name: "NotUsed2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td87 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed3" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td88 + id: 57 + op: 22 + type_name: + struct_member_name: "NotUsed1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td89 + id: 109 + op: 23 + type_name: + struct_member_name: "NotUsed2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td90 + id: 108 + op: 23 + type_name: + struct_member_name: "NotUsed3" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td91 + id: 9 + op: 30 + type_name: "NestedNotUsedParams" + struct_member_name: "NotUsedNested" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td88 + - *td89 + - *td90 + - &td92 + id: 11 + op: 30 + type_name: "NotUsedParams" + struct_member_name: "NotUsed" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td85 + - *td86 + - *td87 + - *td91 + - &td93 + id: 108 + op: 23 + type_name: + struct_member_name: "ScaleByX" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td94 + id: 12 + op: 30 + type_name: "UsedComponents" + struct_member_name: "Components" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td93 + - &td95 + id: 7 + op: 30 + type_name: "type.ConstantBuffer.Params2" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 6 + members: + - *td64 + - *td65 + - *td66 + - *td84 + - *td92 + - *td94 + - &td96 + id: 108 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td97 + id: 106 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "MvpMatrix" + offset: 0 + absolute_offset: 0 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "NotUsedNormalMatrix" + offset: 64 + absolute_offset: 64 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "Offset" + offset: 128 + absolute_offset: 128 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "ScalarScale" + offset: 140 + absolute_offset: 140 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "Vector2ScaleX" + offset: 144 + absolute_offset: 144 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "Vector2ScaleY" + offset: 152 + absolute_offset: 152 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "Vector2ScaleXY" + offset: 160 + absolute_offset: 160 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "Vector2ScaleXXXX" + offset: 168 + absolute_offset: 168 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "Vector2ScaleXYXY" + offset: 176 + absolute_offset: 176 + size: 8 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "Vector3ScaleX" + offset: 192 + absolute_offset: 192 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "Vector3ScaleY" + offset: 208 + absolute_offset: 208 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "Vector3ScaleZ" + offset: 224 + absolute_offset: 224 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "Vector3ScaleXZ" + offset: 240 + absolute_offset: 240 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "Vector3ScaleXYZ" + offset: 256 + absolute_offset: 256 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "Vector3ScaleXX" + offset: 272 + absolute_offset: 272 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "Vector3ScaleYZX" + offset: 288 + absolute_offset: 288 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "Vector3ScaleZZZZ" + offset: 304 + absolute_offset: 304 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "Vector4ScaleX" + offset: 320 + absolute_offset: 320 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td17 + - &bv18 + name: "Vector4ScaleY" + offset: 336 + absolute_offset: 336 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "Vector4ScaleZ" + offset: 352 + absolute_offset: 352 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "Vector4ScaleW" + offset: 368 + absolute_offset: 368 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "Vector4ScaleXY" + offset: 384 + absolute_offset: 384 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "Vector4ScaleXZ" + offset: 400 + absolute_offset: 400 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "Vector4ScaleYZ" + offset: 416 + absolute_offset: 416 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "Vector4ScaleXZW" + offset: 432 + absolute_offset: 432 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "Vector4ScaleYZW" + offset: 448 + absolute_offset: 448 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "Vector4ScaleXYZW" + offset: 464 + absolute_offset: 464 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td26 + - &bv27 + name: "NotUsed1" + offset: 480 + absolute_offset: 480 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td27 + - &bv28 + name: "NotUsed2" + offset: 484 + absolute_offset: 484 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv29 + name: "NotUsed3" + offset: 496 + absolute_offset: 496 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td29 + - &bv30 + name: "MoreOffset" + offset: 512 + absolute_offset: 512 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td30 + - &bv31 + name: "NotUsed4" + offset: 528 + absolute_offset: 528 + size: 8 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td31 + - &bv32 + name: "NotUsed5" + offset: 544 + absolute_offset: 544 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td32 + - &bv33 + name: "LastOffset" + offset: 560 + absolute_offset: 560 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td33 + - &bv34 + name: "NotUsed6" + offset: 576 + absolute_offset: 576 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td34 + - &bv35 + name: "ScalarArray" + offset: 592 + absolute_offset: 592 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td35 + - &bv36 + name: "Vector2Array" + offset: 656 + absolute_offset: 656 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td36 + - &bv37 + name: "Vector3Array" + offset: 720 + absolute_offset: 720 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td37 + - &bv38 + name: "Vector4Array" + offset: 784 + absolute_offset: 784 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td38 + - &bv39 + name: "Vector2ArrayX" + offset: 848 + absolute_offset: 848 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td39 + - &bv40 + name: "Vector3ArrayX" + offset: 912 + absolute_offset: 912 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td40 + - &bv41 + name: "Vector4ArrayX" + offset: 976 + absolute_offset: 976 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td41 + - &bv42 + name: "NotUsedVectorArray" + offset: 1040 + absolute_offset: 1040 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td42 + - &bv43 + name: "R" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td43 + - &bv44 + name: "RG" + offset: 4 + absolute_offset: 0 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td44 + - &bv45 + name: "RGB" + offset: 16 + absolute_offset: 0 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td45 + - &bv46 + name: "RGBA" + offset: 32 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td46 + - &bv47 + name: "ColorArray" + offset: 1104 + absolute_offset: 1104 + size: 1935360 + padded_size: 1935360 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 48 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv43 + - *bv44 + - *bv45 + - *bv46 + type_description: *td47 + - &bv48 + name: "ScalarMultiDimArray" + offset: 1936464 + absolute_offset: 1936464 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td48 + - &bv49 + name: "Vector2MultiDimArray" + offset: 2581584 + absolute_offset: 2581584 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td49 + - &bv50 + name: "Vector3MultiDimArray" + offset: 3226704 + absolute_offset: 3226704 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td50 + - &bv51 + name: "Vector4MultiDimArray" + offset: 3871824 + absolute_offset: 3871824 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td51 + - &bv52 + name: "Vector2MultiDimArrayX" + offset: 4516944 + absolute_offset: 4516944 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td52 + - &bv53 + name: "Vector3MultiDimArrayX" + offset: 5162064 + absolute_offset: 5162064 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td53 + - &bv54 + name: "Vector4MultiDimArrayX" + offset: 5807184 + absolute_offset: 5807184 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td54 + - &bv55 + name: "NotUsedVector2MultiDimArrayY" + offset: 6452304 + absolute_offset: 6452304 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td55 + - &bv56 + name: "NotUsedVector3MultiDimArrayY" + offset: 7097424 + absolute_offset: 7097424 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td56 + - &bv57 + name: "NotUsedVector4MultiDimArrayY" + offset: 7742544 + absolute_offset: 7742544 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td57 + - &bv58 + name: "Vector3MultiDimArrayZ" + offset: 8387664 + absolute_offset: 8387664 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td58 + - &bv59 + name: "Vector4MultiDimArrayZ" + offset: 9032784 + absolute_offset: 9032784 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td59 + - &bv60 + name: "Vector2MultiDimArrayXYX" + offset: 9677904 + absolute_offset: 9677904 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td60 + - &bv61 + name: "Vector3MultiDimArrayXYX" + offset: 10323024 + absolute_offset: 10323024 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td61 + - &bv62 + name: "Vector4MultiDimArrayXYX" + offset: 10968144 + absolute_offset: 10968144 + size: 645120 + padded_size: 645120 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 7, dims: [8,7,6,5,4,3,2,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td62 + - &bv63 + name: "MyParams" + offset: 0 + absolute_offset: 0 + size: 11613264 + padded_size: 11613264 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 59 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + - *bv10 + - *bv11 + - *bv12 + - *bv13 + - *bv14 + - *bv15 + - *bv16 + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + - *bv24 + - *bv25 + - *bv26 + - *bv27 + - *bv28 + - *bv29 + - *bv30 + - *bv31 + - *bv32 + - *bv33 + - *bv34 + - *bv35 + - *bv36 + - *bv37 + - *bv38 + - *bv39 + - *bv40 + - *bv41 + - *bv42 + - *bv47 + - *bv48 + - *bv49 + - *bv50 + - *bv51 + - *bv52 + - *bv53 + - *bv54 + - *bv55 + - *bv56 + - *bv57 + - *bv58 + - *bv59 + - *bv60 + - *bv61 + - *bv62 + type_description: *td63 + - &bv64 + name: "PostTransformOffset" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td64 + - &bv65 + name: "NotUsedScale" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td65 + - &bv66 + name: "Mask" + offset: 20 + absolute_offset: 20 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td66 + - &bv67 + name: "Position" + offset: 0 + absolute_offset: 32 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td67 + - &bv68 + name: "NotUsedColor" + offset: 16 + absolute_offset: 48 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td68 + - &bv69 + name: "Normal" + offset: 32 + absolute_offset: 64 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td69 + - &bv70 + name: "NotUsed1" + offset: 0 + absolute_offset: 80 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td70 + - &bv71 + name: "NotUsed2" + offset: 4 + absolute_offset: 84 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td71 + - &bv72 + name: "NotUsed3" + offset: 16 + absolute_offset: 96 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td72 + - &bv73 + name: "NotUsedNested" + offset: 48 + absolute_offset: 80 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv70 + - *bv71 + - *bv72 + type_description: *td73 + - &bv74 + name: "NotUsed" + offset: 0 + absolute_offset: 112 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td74 + - &bv75 + name: "Offset" + offset: 4 + absolute_offset: 116 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td75 + - &bv76 + name: "NotUsedMatrix" + offset: 16 + absolute_offset: 128 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td76 + - &bv77 + name: "UsedNested" + offset: 80 + absolute_offset: 112 + size: 80 + padded_size: 80 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv74 + - *bv75 + - *bv76 + type_description: *td77 + - &bv78 + name: "NotUsed1" + offset: 160 + absolute_offset: 192 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td78 + - &bv79 + name: "R" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td79 + - &bv80 + name: "RG" + offset: 4 + absolute_offset: 0 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td80 + - &bv81 + name: "RGB" + offset: 16 + absolute_offset: 0 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td81 + - &bv82 + name: "RGBA" + offset: 32 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td82 + - &bv83 + name: "ColorArray" + offset: 176 + absolute_offset: 208 + size: 192 + padded_size: 192 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 48 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv79 + - *bv80 + - *bv81 + - *bv82 + type_description: *td83 + - &bv84 + name: "Used" + offset: 32 + absolute_offset: 32 + size: 368 + padded_size: 368 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 7 + members: + - *bv67 + - *bv68 + - *bv69 + - *bv73 + - *bv77 + - *bv78 + - *bv83 + type_description: *td84 + - &bv85 + name: "NotUsed1" + offset: 0 + absolute_offset: 400 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td85 + - &bv86 + name: "NotUsed2" + offset: 4 + absolute_offset: 404 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td86 + - &bv87 + name: "NotUsed3" + offset: 16 + absolute_offset: 416 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td87 + - &bv88 + name: "NotUsed1" + offset: 0 + absolute_offset: 432 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td88 + - &bv89 + name: "NotUsed2" + offset: 4 + absolute_offset: 436 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td89 + - &bv90 + name: "NotUsed3" + offset: 16 + absolute_offset: 448 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td90 + - &bv91 + name: "NotUsedNested" + offset: 32 + absolute_offset: 432 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv88 + - *bv89 + - *bv90 + type_description: *td91 + - &bv92 + name: "NotUsed" + offset: 400 + absolute_offset: 400 + size: 64 + padded_size: 64 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv85 + - *bv86 + - *bv87 + - *bv91 + type_description: *td92 + - &bv93 + name: "ScaleByX" + offset: 0 + absolute_offset: 464 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td93 + - &bv94 + name: "Components" + offset: 464 + absolute_offset: 464 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv93 + type_description: *td94 + - &bv95 + name: "MyParams2" + offset: 0 + absolute_offset: 0 + size: 480 + padded_size: 480 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 6 + members: + - *bv64 + - *bv65 + - *bv66 + - *bv84 + - *bv92 + - *bv94 + type_description: *td95 +all_descriptor_bindings: + - &db0 + spirv_id: 6 + name: "MyParams" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv63 # "MyParams" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td63 + word_offset: { binding: 708, set: 704 } + - &db1 + spirv_id: 13 + name: "MyParams2" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv95 # "MyParams2" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td95 + word_offset: { binding: 716, set: 712 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "in.var.Position" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td96 + word_offset: { location: 700 } + - &iv1 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td97 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "MyParams" + - *db1 # "MyParams2" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "MyParams" + - *db1 # "MyParams2" + input_variable_count: 1, + input_variables: + - *iv0 # "in.var.Position" + output_variable_count: 1, + output_variables: + - *iv1 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/ci_database.py b/lib/All/SPIRV-Reflect/tests/ci_database.py new file mode 100644 index 0000000..7fe17ff --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/ci_database.py @@ -0,0 +1,22 @@ +import os +import sys +import argparse +import subprocess + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='run SPIRV-Database in CI') + # Main reason for passing dir in is so GitHub Actions can group things, otherwise logs get VERY long for a single action + parser.add_argument('--dir', action='store', required=True, type=str, help='path to SPIR-V files') + args = parser.parse_args() + + root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + exe_path = os.path.join(root_dir, 'bin/spirv-reflect') + + for currentpath, folders, files in os.walk(args.dir): + for file in files: + spirv_file = os.path.join(currentpath, file) + command = f'{exe_path} {spirv_file} -ci' + exit_code = subprocess.call(command.split()) + if exit_code != 0: + print(f'ERROR for {spirv_file}') + sys.exit(1) \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/CMakeLists.txt b/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/CMakeLists.txt new file mode 100644 index 0000000..66a530a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.16) + +project(noncopyable) + +list(APPEND SPIRV_REFLECT_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../../spirv_reflect.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../../spirv_reflect.c +) + +add_executable(noncopyable ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${COMMON_FILES} ${SPIRV_REFLECT_FILES}) +target_include_directories(noncopyable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../..) +set_target_properties(noncopyable PROPERTIES CXX_STANDARD 11) + +if(WIN32) + target_compile_definitions(noncopyable PRIVATE _CRT_SECURE_NO_WARNINGS) + set_target_properties(noncopyable PROPERTIES FOLDER "tests") +endif() diff --git a/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/main.cpp b/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/main.cpp new file mode 100644 index 0000000..ab68a06 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/cpp/noncopyable/main.cpp @@ -0,0 +1,7 @@ +#include "spirv_reflect.h" + +int main(int argc, char** argv) { + spv_reflect::ShaderModule shaderModule; + shaderModule = spv_reflect::ShaderModule(); + return 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.glsl b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.glsl new file mode 100644 index 0000000..8156cca --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.glsl @@ -0,0 +1,15 @@ +#version 450 core + +layout(set = 0, binding = 0) buffer buf +{ + uint buf_Data[]; +}; + +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +void main() +{ + buf_Data[0] = buf_Data[32]; + buf_Data[100] = buf_Data[132]; + buf_Data[200] = buf_Data[232]; +} diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv new file mode 100644 index 0000000..a80b744 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv.yaml b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv.yaml new file mode 100644 index 0000000..5cd6192 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/comp_local_size.spv.yaml @@ -0,0 +1,117 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 29 + type_name: + struct_member_name: "buf_Data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 8 + op: 30 + type_name: "buf" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 +all_block_variables: + - &bv0 + name: "buf_Data" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 10 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 65, set: 61 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.glsl b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.glsl new file mode 100644 index 0000000..41014cc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.glsl @@ -0,0 +1,13 @@ +#version 450 core +layout (points, invocations = 2) in; +layout (line_strip, max_vertices = 2) out; + +void main() { + gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); + EmitVertex(); + + gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0); + EmitVertex(); + + EndPrimitive(); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv new file mode 100644 index 0000000..cbc454c Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv.yaml b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv.yaml new file mode 100644 index 0000000..acdb216 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/entry_exec_mode/geom_inv_out_vert.spv.yaml @@ -0,0 +1,395 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 17 + op: 28 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - &td5 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td8 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td9 + id: 11 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td5 + - *td6 + - *td7 + - *td8 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv4 + spirv_id: 19 + name: "gl_in" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 4 + members: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td4 + word_offset: { location: 0 } + - &iv5 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv6 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td6 + word_offset: { location: 0 } + - &iv7 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td7 + word_offset: { location: 0 } + - &iv8 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td8 + word_offset: { location: 0 } + - &iv9 + spirv_id: 13 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td9 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 3 # Geometry + shader_stage: 0x00000008 # GS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv4 # "gl_in" + output_variable_count: 1, + output_variables: + - *iv9 # "" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv new file mode 100644 index 0000000..2b5b824 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv.yaml b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv.yaml new file mode 100644 index 0000000..034a1a0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id.spv.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv new file mode 100644 index 0000000..24b4d87 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv.yaml b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv.yaml new file mode 100644 index 0000000..034a1a0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/execution_mode/local_size_id_spec.spv.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.glsl new file mode 100644 index 0000000..ee58081 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.glsl @@ -0,0 +1,32 @@ +#version 450 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer t1; +layout(buffer_reference) buffer t2; +layout(buffer_reference) buffer t3; +layout(buffer_reference) buffer t4; + +layout(buffer_reference, std430) buffer t1 { + t4 i_1; +}; + +layout(buffer_reference, std430) buffer t2 { + t4 i_2; +}; + +layout(buffer_reference, std430) buffer t3 { + t2 i_3; +}; + +layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 { + layout(offset = 0) int j; + t1 k_1; + t2 k_2; + t3 k_3; +} x; + +layout(set = 0, binding = 0, std430) buffer t5 { + t4 m; +} s5; + +void main() {} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv new file mode 100644 index 0000000..7d41c09 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv.yaml new file mode 100644 index 0000000..2eb538a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_0.spv.yaml @@ -0,0 +1,1319 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 32 + type_name: + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td2 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 11 + op: 32 + type_name: + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td4 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td6 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td5 + - &td7 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "m" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td0 + - *td2 + - *td4 + - *td6 + - &td8 + id: 18 + op: 30 + type_name: "t5" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 7 + op: 32 + type_name: + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td12 + id: 11 + op: 32 + type_name: + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td13 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td12 + - &td14 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td15 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td14 + - &td16 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td10 + - *td11 + - *td13 + - *td15 + - &td17 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td16 + - &td18 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 11 + op: 32 + type_name: + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td20 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td19 + - &td21 + id: 11 + op: 32 + type_name: + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td22 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td21 + - &td23 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td24 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td23 + - &td25 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td18 + - *td20 + - *td22 + - *td24 + - &td26 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td27 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td28 + id: 11 + op: 32 + type_name: + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td29 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td28 + - &td30 + id: 11 + op: 32 + type_name: + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td31 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td30 + - &td32 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td33 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td32 + - &td34 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td27 + - *td29 + - *td31 + - *td33 + - &td35 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td36 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td37 + id: 11 + op: 32 + type_name: + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td38 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td37 + - &td39 + id: 8 + op: 32 + type_name: + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td40 + id: 8 + op: 32 + type_name: + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td41 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td40 + - &td42 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td36 + - *td38 + - *td39 + - *td41 + - &td43 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td42 + - &td44 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td45 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td46 + id: 7 + op: 32 + type_name: + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td47 + id: 11 + op: 32 + type_name: + struct_member_name: "i_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td48 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td47 + - &td49 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "i_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td50 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td49 + - &td51 + id: 11 + op: 32 + type_name: "t4" + struct_member_name: "i_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td45 + - *td46 + - *td48 + - *td50 + - &td52 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k_1" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td51 + - &td53 + id: 8 + op: 32 + type_name: "t2" + struct_member_name: "k_2" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td54 + id: 9 + op: 32 + type_name: "t3" + struct_member_name: "k_3" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td55 + id: 10 + op: 30 + type_name: "t4" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td44 + - *td52 + - *td53 + - *td54 +all_block_variables: + - &bv0 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv1 + name: "k_1" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td17 + - &bv2 + name: "k_2" + offset: 16 + absolute_offset: 16 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td26 + - &bv3 + name: "k_3" + offset: 24 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td35 + - &bv4 + name: "m" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + type_description: *td7 + - &bv5 + name: "s5" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv4 + type_description: *td8 + - &bv6 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td44 + - &bv7 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv8 + name: "k_2" + offset: 16 + absolute_offset: 16 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td26 + - &bv9 + name: "k_3" + offset: 24 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td35 + - &bv10 + name: "i_1" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv7 + - [recursive] + - *bv8 + - *bv9 + type_description: *td25 + - &bv11 + name: "k_1" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv10 + type_description: *td52 + - &bv12 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv6 + - *bv11 + - [recursive] + - [recursive] + type_description: *td55 +all_descriptor_bindings: + - &db0 + spirv_id: 20 + name: "s5" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "s5" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 225, set: 221 } + - &db1 + spirv_id: 17 + name: "x" + binding: 2 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv12 # "x" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td55 + word_offset: { binding: 209, set: 205 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "s5" + - *db1 # "x" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "s5" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.glsl new file mode 100644 index 0000000..31f246e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.glsl @@ -0,0 +1,26 @@ +#version 450 +// Taken from glslang/Test/spv.bufferhandle4.frag +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer t4; + +layout(buffer_reference, std430) buffer t3 { + int h; + t4 i; +}; + +layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 { + layout(offset = 0) int j; + t3 k; +} x; + +layout(set = 0, binding = 0, std430) buffer t5 { + t4 m; +} s5; + +void main() { + x.k.h = s5.m.k.i.k.i.k.h; + + bool b = true; + s5.m = b ? s5.m : s5.m.k.i; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv new file mode 100644 index 0000000..35b9639 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv.yaml new file mode 100644 index 0000000..fa05b2f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_1.spv.yaml @@ -0,0 +1,706 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 21 + type_name: + struct_member_name: "h" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 9 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td3 + id: 7 + op: 32 + type_name: "t3" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td1 + - *td2 + - &td4 + id: 9 + op: 32 + type_name: "t4" + struct_member_name: "m" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td3 + - &td5 + id: 19 + op: 30 + type_name: "t5" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 6 + op: 21 + type_name: + struct_member_name: "h" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 7 + op: 32 + type_name: + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td10 + id: 9 + op: 32 + type_name: "t4" + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td8 + - *td9 + - &td11 + id: 7 + op: 32 + type_name: "t3" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td7 + - *td10 + - &td12 + id: 6 + op: 21 + type_name: + struct_member_name: "h" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 6 + op: 21 + type_name: + struct_member_name: "h" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 9 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td16 + id: 7 + op: 32 + type_name: "t3" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td14 + - *td15 + - &td17 + id: 9 + op: 32 + type_name: "t4" + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td13 + - *td16 + - &td18 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 6 + op: 21 + type_name: + struct_member_name: "h" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 7 + op: 32 + type_name: + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td22 + id: 9 + op: 32 + type_name: "t4" + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td20 + - *td21 + - &td23 + id: 7 + op: 32 + type_name: "t3" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td19 + - *td22 + - &td24 + id: 8 + op: 30 + type_name: "t4" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td18 + - *td23 +all_block_variables: + - &bv0 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv1 + name: "h" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv2 + name: "k" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv1 + - [recursive] + type_description: *td11 + - &bv3 + name: "m" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv2 + type_description: *td4 + - &bv4 + name: "s5" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td5 + - &bv5 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv6 + name: "h" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv7 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv8 + name: "i" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv7 + - [recursive] + type_description: *td17 + - &bv9 + name: "k" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv6 + - *bv8 + type_description: *td23 + - &bv10 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv5 + - *bv9 + type_description: *td24 +all_descriptor_bindings: + - &db0 + spirv_id: 21 + name: "s5" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # "s5" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 171, set: 167 } + - &db1 + spirv_id: 13 + name: "x" + binding: 2 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv10 # "x" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td24 + word_offset: { binding: 155, set: 151 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "s5" + - *db1 # "x" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "s5" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.glsl new file mode 100644 index 0000000..8688091 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.glsl @@ -0,0 +1,30 @@ +#version 450 core +// Taken from glslang/Test/spv.bufferhandle6.frag +#extension GL_EXT_buffer_reference : enable +layout (push_constant, std430) uniform Block { int identity[32]; } pc; +layout(r32ui, set = 3, binding = 0) uniform uimage2D image0_0; +layout(buffer_reference) buffer T1; +layout(set = 3, binding = 1, buffer_reference) buffer T1 { + layout(offset = 0) int a[2]; // stride = 4 for std430, 16 for std140 + layout(offset = 32) int b; + layout(offset = 48) T1 c[2]; // stride = 8 for std430, 16 for std140 + layout(offset = 80) T1 d; +} x; +void main() +{ + int accum = 0, temp; + accum |= x.a[0] - 0; + accum |= x.a[pc.identity[1]] - 1; + accum |= x.b - 2; + accum |= x.c[0].a[0] - 3; + accum |= x.c[0].a[pc.identity[1]] - 4; + accum |= x.c[0].b - 5; + accum |= x.c[pc.identity[1]].a[0] - 6; + accum |= x.c[pc.identity[1]].a[pc.identity[1]] - 7; + accum |= x.c[pc.identity[1]].b - 8; + accum |= x.d.a[0] - 9; + accum |= x.d.a[pc.identity[1]] - 10; + accum |= x.d.b - 11; + uvec4 color = (accum != 0) ? uvec4(0,0,0,0) : uvec4(1,0,0,1); + imageStore(image0_0, ivec2(gl_FragCoord.x, gl_FragCoord.y), color); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv new file mode 100644 index 0000000..439b640 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv.yaml new file mode 100644 index 0000000..6cb52cd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_2.spv.yaml @@ -0,0 +1,836 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 147 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010004 # EXTERNAL_IMAGE INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 33 } # dim=2D image_format=R32ui + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 12 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td6 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 17 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - [forward pointer] + - &td8 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td9 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 17 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - [forward pointer] + - &td11 + id: 13 + op: 32 + type_name: + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td12 + id: 13 + op: 32 + type_name: "T1" + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td8 + - *td9 + - *td10 + - *td11 + - &td13 + id: 17 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - *td5 + - *td6 + - *td7 + - *td12 + - &td14 + id: 13 + op: 32 + type_name: "T1" + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td15 + id: 14 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - *td3 + - *td4 + - *td13 + - *td14 + - &td16 + id: 13 + op: 32 + type_name: "T1" + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td17 + id: 15 + op: 30 + type_name: "T1" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td1 + - *td2 + - *td15 + - *td16 + - &td18 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td19 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td21 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 17 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - [forward pointer] + - &td23 + id: 16 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td24 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 17 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - [forward pointer] + - &td26 + id: 13 + op: 32 + type_name: + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td27 + id: 13 + op: 32 + type_name: "T1" + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td23 + - *td24 + - *td25 + - *td26 + - &td28 + id: 17 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 4 + members: + - *td20 + - *td21 + - *td22 + - *td27 + - &td29 + id: 13 + op: 32 + type_name: "T1" + struct_member_name: "d" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - [forward pointer] + - &td30 + id: 29 + op: 28 + type_name: + struct_member_name: "identity" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [32,], stride: 4 } + member_count: 0 + members: + - &td31 + id: 30 + op: 30 + type_name: "Block" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td30 + - &td32 + id: 152 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: "a" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "b" + offset: 32 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "a" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv4 + name: "b" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv5 + name: "c" + offset: 48 + absolute_offset: 48 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv3 + - *bv4 + - [recursive] + - [recursive] + type_description: *td15 + - &bv6 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv1 + - *bv2 + - *bv5 + - [recursive] + type_description: *td17 + - &bv7 + name: "identity" + offset: 0 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [32,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td30 + - &bv8 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv7 + type_description: *td31 +all_descriptor_bindings: + - &db0 + spirv_id: 149 + name: "image0_0" + binding: 0 + input_attachment_index: 0 + set: 3 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 33 } # dim=2D image_format=R32ui + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 227, set: 223 } + - &db1 + spirv_id: 21 + name: "x" + binding: 1 + input_attachment_index: 0 + set: 3 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # "x" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 207, set: 203 } +all_interface_variables: + - &iv0 + spirv_id: 154 + name: "gl_FragCoord" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td32 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "image0_0" + - *db1 # "x" + descriptor_set_count: 1 + descriptor_sets: + - set: 3 + binding_count: 2 + bindings: + - *db0 # "image0_0" + - *db1 # "x" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_FragCoord" + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv8 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.glsl new file mode 100644 index 0000000..79c4b0c --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.glsl @@ -0,0 +1,19 @@ +#version 450 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer t1; + +layout(buffer_reference, std430) buffer t1 { + t1 i; +}; + +layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 { + layout(offset = 0) int j; + t1 k; +} x; + +layout(set = 0, binding = 0, std430) buffer t5 { + t4 m; +} s5; + +void main() {} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv new file mode 100644 index 0000000..1a35e31 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv.yaml new file mode 100644 index 0000000..7084090 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_3.spv.yaml @@ -0,0 +1,441 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td2 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 12 + op: 32 + type_name: "t4" + struct_member_name: "m" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td2 + - &td4 + id: 13 + op: 30 + type_name: "t5" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 7 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td7 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 7 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td9 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td8 + - &td10 + id: 6 + op: 21 + type_name: + struct_member_name: "j" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 7 + op: 32 + type_name: + struct_member_name: "i" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td12 + id: 7 + op: 32 + type_name: "t1" + struct_member_name: "k" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td11 + - &td13 + id: 8 + op: 30 + type_name: "t4" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td10 + - *td12 +all_block_variables: + - &bv0 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv1 + name: "k" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td7 + - &bv2 + name: "m" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td3 + - &bv3 + name: "s5" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv2 + type_description: *td4 + - &bv4 + name: "j" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv5 + name: "k" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td12 + - &bv6 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv4 + - *bv5 + type_description: *td13 +all_descriptor_bindings: + - &db0 + spirv_id: 16 + name: "s5" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "s5" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 159, set: 155 } + - &db1 + spirv_id: 11 + name: "x" + binding: 2 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # "x" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td13 + word_offset: { binding: 130, set: 126 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "s5" + - *db1 # "x" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "s5" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.glsl new file mode 100644 index 0000000..87700a9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.glsl @@ -0,0 +1,34 @@ +#version 460 core +#extension GL_EXT_buffer_reference : require +#extension GL_EXT_shader_explicit_arithmetic_types_float32 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require +#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require + +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer ReadVecf +{ + float32_t values[]; +}; + +layout(buffer_reference, buffer_reference_align = 4) writeonly buffer WriteVecf +{ + float32_t values[]; +}; + +layout(push_constant, std430) uniform Parameters +{ + ReadVecf a; + ReadVecf b; + WriteVecf c; + uint64_t n; +} params; + +void main() +{ + uint32_t idx = gl_GlobalInvocationID.x; + uint32_t stride = gl_NumWorkGroups.x * gl_WorkGroupSize.x; + for (; idx < params.n; idx += stride) { + params.c.values[idx] = params.a.values[idx] + params.b.values[idx]; + } +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv new file mode 100644 index 0000000..a21e6cc Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv.yaml new file mode 100644 index 0000000..4103601 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_4.spv.yaml @@ -0,0 +1,345 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 34 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 30 + op: 32 + type_name: "ReadVecf" + struct_member_name: "a" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 30 + op: 32 + type_name: "ReadVecf" + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td3 + id: 36 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 31 + op: 32 + type_name: "WriteVecf" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 28 + op: 21 + type_name: + struct_member_name: "n" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 64, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 32 + op: 30 + type_name: "Parameters" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td1 + - *td2 + - *td4 + - *td5 + - &td7 + id: 34 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td8 + id: 36 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td9 + id: 9 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "values" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td7 + - &bv1 + name: "a" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "values" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000200 # NON_READABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td8 + - &bv3 + name: "c" + offset: 16 + absolute_offset: 16 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td4 + - &bv4 + name: "n" + offset: 24 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 64, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv5 + name: "params" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv1 + - [recursive] + - *bv3 + - *bv4 + type_description: *td6 +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 11 + name: "gl_GlobalInvocationID" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td9 + word_offset: { location: 0 } + - &iv1 + spirv_id: 17 + name: "gl_NumWorkGroups" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 24 # NumWorkgroups + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td9 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 2, + input_variables: + - *iv0 # "gl_GlobalInvocationID" + - *iv1 # "gl_NumWorkGroups" + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv5 # "params" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.glsl new file mode 100644 index 0000000..ee751d6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.glsl @@ -0,0 +1,19 @@ +#version 460 core +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer t2 { + int values[]; +}; + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer t1 { + t2 c; +}; + +layout(push_constant, std430) uniform Parameters { + t1 a; + t2 b; +} params; + +void main() { + params.a.c.values[0] = params.b.values[0] + 1; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv new file mode 100644 index 0000000..3a6eab6 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv.yaml new file mode 100644 index 0000000..fe5a1f9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_5.spv.yaml @@ -0,0 +1,238 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 7 + op: 32 + type_name: "t2" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 6 + op: 32 + type_name: "t1" + struct_member_name: "a" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 7 + op: 32 + type_name: "t2" + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td4 + id: 8 + op: 30 + type_name: "Parameters" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td2 + - *td3 + - &td5 + id: 11 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td6 + id: 7 + op: 32 + type_name: "t2" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td5 + - &td7 + id: 11 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "values" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td7 + - &bv1 + name: "c" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td6 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: "params" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv2 + - [recursive] + type_description: *td4 +all_descriptor_bindings: +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv3 # "params" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.glsl new file mode 100644 index 0000000..1d4e5ac --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.glsl @@ -0,0 +1,36 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +#extension GL_ARB_enhanced_layouts : require +#extension GL_EXT_nonuniform_qualifier : require +#extension GL_KHR_shader_subgroup_arithmetic : require +layout(row_major) uniform; +layout(row_major) buffer; + +struct BDAGlobals_t_0 { + vec4 g_vTest; + vec4 g_vTest2; +}; + +layout(buffer_reference, std430, buffer_reference_align = 16) readonly buffer BufferPointer_BDAGlobals_t_0_1 { + BDAGlobals_t_0 _data; +}; + +struct GlobalsBDAPushConstant_t_0 { + BufferPointer_BDAGlobals_t_0_1 g_GlobalsBDAPerStage_0[6]; +}; + +layout(push_constant) +layout(std140) uniform _S2 { + BufferPointer_BDAGlobals_t_0_1 g_GlobalsBDAPerStage_0[6]; +} g_GlobalsBDAPushConstant_0; + +struct PS_OUTPUT_0 { + vec4 vColor_1; +}; + +layout(location = 0) out vec4 _S149; + +void main() { + _S149 = g_GlobalsBDAPushConstant_0.g_GlobalsBDAPerStage_0[0]._data.g_vTest; + return; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv new file mode 100644 index 0000000..00ec6bf Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv.yaml new file mode 100644 index 0000000..983ee66 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_6.spv.yaml @@ -0,0 +1,290 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "g_vTest" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "g_vTest2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 15 + op: 30 + type_name: "BDAGlobals_t_0" + struct_member_name: "_data" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 13 + op: 28 + type_name: "BufferPointer_BDAGlobals_t_0_1" + struct_member_name: "g_GlobalsBDAPerStage_0" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [6,], stride: 16 } + member_count: 1 + members: + - *td2 + - &td4 + id: 14 + op: 30 + type_name: "_S2" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 7 + op: 23 + type_name: + struct_member_name: "g_vTest" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 7 + op: 23 + type_name: + struct_member_name: "g_vTest2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 15 + op: 30 + type_name: "BDAGlobals_t_0" + struct_member_name: "_data" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td5 + - *td6 + - &td8 + id: 7 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "g_vTest" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv1 + name: "g_vTest2" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv2 + name: "_data" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td7 + - &bv3 + name: "g_GlobalsBDAPerStage_0" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: "g_GlobalsBDAPushConstant_0" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 9 + name: "_S149" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td8 + word_offset: { location: 144 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "_S149" + push_constant_count: 1, + push_constants: + - *bv4 # "g_GlobalsBDAPushConstant_0" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.glsl new file mode 100644 index 0000000..ced8bcc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.glsl @@ -0,0 +1,23 @@ +#version 460 core +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer t2 { + int values[]; +}; + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer t1 { + t2 c; +}; + +layout(buffer_reference, buffer_reference_align = 4) readonly buffer t0 { + t1 a; + t2 b; +}; + +layout(push_constant, std430) uniform Parameters { + t0 x; +} params; + +void main() { + params.x.a.c.values[0] = params.x.b.values[0] + 1; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv new file mode 100644 index 0000000..10dad80 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv.yaml new file mode 100644 index 0000000..eacf371 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_7.spv.yaml @@ -0,0 +1,344 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 13 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 9 + op: 32 + type_name: "t2" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 8 + op: 32 + type_name: "t1" + struct_member_name: "a" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 9 + op: 32 + type_name: "t2" + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] + - &td4 + id: 6 + op: 32 + type_name: "t0" + struct_member_name: "x" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td2 + - *td3 + - &td5 + id: 7 + op: 30 + type_name: "Parameters" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 13 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 9 + op: 32 + type_name: "t2" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 8 + op: 32 + type_name: "t1" + struct_member_name: "a" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 13 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td10 + id: 9 + op: 32 + type_name: "t2" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td9 + - &td11 + id: 13 + op: 29 + type_name: + struct_member_name: "values" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td12 + id: 9 + op: 32 + type_name: "t2" + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - [forward pointer] +all_block_variables: + - &bv0 + name: "values" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td11 + - &bv1 + name: "c" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td10 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td8 + - &bv3 + name: "x" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv2 + - [recursive] + type_description: *td4 + - &bv4 + name: "params" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td5 +all_descriptor_bindings: +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv4 # "params" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.glsl new file mode 100644 index 0000000..34305b1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.glsl @@ -0,0 +1,9 @@ +#version 450 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer T1; +layout(set = 3, binding = 1, buffer_reference) buffer T1 { + layout(offset = 48) T1 c[2]; // stride = 8 for std430, 16 for std140 +} x; + +void main() {} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv new file mode 100644 index 0000000..aa419ad Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv.yaml new file mode 100644 index 0000000..53d8de2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_8.spv.yaml @@ -0,0 +1,191 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 1 + members: + - [forward pointer] + - &td1 + id: 11 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 1 + members: + - *td0 + - &td2 + id: 9 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 1 + members: + - *td1 + - &td3 + id: 10 + op: 30 + type_name: "T1" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 11 + op: 28 + type_name: + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 1 + members: + - [forward pointer] + - &td5 + id: 11 + op: 28 + type_name: "T1" + struct_member_name: "c" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 8 } + member_count: 1 + members: + - *td4 +all_block_variables: + - &bv0 + name: "c" + offset: 48 + absolute_offset: 48 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - [recursive] + type_description: *td2 + - &bv1 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 15 + name: "x" + binding: 1 + input_attachment_index: 0 + set: 3 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "x" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 115, set: 111 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "x" + descriptor_set_count: 1 + descriptor_sets: + - set: 3 + binding_count: 1 + bindings: + - *db0 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.glsl new file mode 100644 index 0000000..d84bf5d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.glsl @@ -0,0 +1,16 @@ +#version 460 +#extension GL_EXT_buffer_reference2: require +#extension GL_EXT_scalar_block_layout : enable + +layout(buffer_reference, scalar) readonly buffer VertexBufferPtr { + vec4 v[]; +}; + +// Has a OpTypeRuntimeArray +layout(binding = 1, set = 0, scalar) readonly buffer Vertices { + VertexBufferPtr vertex_buffers[]; +}; + +void main() { + gl_Position = vertex_buffers[gl_VertexIndex].v[gl_VertexIndex]; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv new file mode 100644 index 0000000..1f6a633 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv.yaml new file mode 100644 index 0000000..3d3dcd8 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_9.spv.yaml @@ -0,0 +1,389 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 19 + op: 29 + type_name: + struct_member_name: "v" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 16 } + member_count: 0 + members: + - &td1 + id: 17 + op: 29 + type_name: "VertexBufferPtr" + struct_member_name: "vertex_buffers" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x70080000 # ARRAY STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 8 } + member_count: 1 + members: + - *td0 + - &td2 + id: 18 + op: 30 + type_name: "Vertices" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 19 + op: 29 + type_name: + struct_member_name: "v" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 16 } + member_count: 0 + members: + - &td4 + id: 14 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td8 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td9 + id: 11 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td5 + - *td6 + - *td7 + - *td8 +all_block_variables: + - &bv0 + name: "v" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv1 + name: "vertex_buffers" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 23 + name: "" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 191, set: 187 } +all_interface_variables: + - &iv0 + spirv_id: 25 + name: "gl_VertexIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 42 # VertexIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td4 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td6 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td7 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td8 + word_offset: { location: 0 } + - &iv5 + spirv_id: 13 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td9 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_VertexIndex" + output_variable_count: 1, + output_variables: + - *iv5 # "" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.glsl new file mode 100644 index 0000000..2e589eb --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.glsl @@ -0,0 +1,16 @@ +#version 460 +#extension GL_EXT_buffer_reference2 : require +#extension GL_EXT_buffer_reference_uvec2 : require + +layout(buffer_reference) buffer VertexBuffer; +layout(buffer_reference, buffer_reference_align = 16, std430) buffer VertexBuffer { + int x; +}; + +layout(push_constant, std430) uniform PerFrameData { + uvec2 bufferId; +} pc; + +void main() { + VertexBuffer(pc.bufferId).x = 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv new file mode 100644 index 0000000..4fd10f8 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv.yaml new file mode 100644 index 0000000..5b21db1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_pc.spv.yaml @@ -0,0 +1,96 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "bufferId" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 8 + op: 30 + type_name: "PerFrameData" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 +all_block_variables: + - &bv0 + name: "bufferId" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv1 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.glsl new file mode 100644 index 0000000..a58dbc6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.glsl @@ -0,0 +1,16 @@ +#version 460 +#extension GL_EXT_buffer_reference2 : require +#extension GL_EXT_buffer_reference_uvec2 : require + +layout(buffer_reference) buffer VertexBuffer; +layout(buffer_reference, buffer_reference_align = 16, std430) buffer VertexBuffer { + int x; +}; + +layout(set = 0, binding = 0) buffer T1 { + uvec2 bufferId; +} ssbo; + +void main() { + VertexBuffer(ssbo.bufferId).x = 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv new file mode 100644 index 0000000..2289761 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv.yaml new file mode 100644 index 0000000..4d5da4b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_handle_uvec2_ssbo.spv.yaml @@ -0,0 +1,117 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "bufferId" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 8 + op: 30 + type_name: "T1" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 +all_block_variables: + - &bv0 + name: "bufferId" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "ssbo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 10 + name: "ssbo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "ssbo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 118, set: 114 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "ssbo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "ssbo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.glsl b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.glsl new file mode 100644 index 0000000..aae16d5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.glsl @@ -0,0 +1,22 @@ +#version 460 core + +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference, buffer_reference_align = 16) buffer Data { + float g0; + float g1; + float g2; +}; + +layout(push_constant) uniform PushData { + Data data_ptr; +} push; + +layout(location = 0, index = 0) out vec4 Color; + +void main() +{ + float f1 = push.data_ptr.g1; + Color = vec4(f1, 0.0, 0.0, 0.0); +} + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv new file mode 100644 index 0000000..dc7f2f7 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv.yaml new file mode 100644 index 0000000..da95763 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.spv.yaml @@ -0,0 +1,288 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 22 + type_name: + struct_member_name: "g0" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 22 + type_name: + struct_member_name: "g1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 7 + op: 22 + type_name: + struct_member_name: "g2" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 32 + type_name: "Data" + struct_member_name: "data_ptr" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 + - &td4 + id: 11 + op: 30 + type_name: "PushData" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 7 + op: 22 + type_name: + struct_member_name: "g0" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 7 + op: 22 + type_name: + struct_member_name: "g1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 7 + op: 22 + type_name: + struct_member_name: "g2" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 24 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "g0" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv1 + name: "g1" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv2 + name: "g2" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv3 + name: "data_ptr" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 + - &bv4 + name: "push" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 26 + name: "Color" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td8 + word_offset: { location: 240 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 5 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "Color" + push_constant_count: 1, + push_constants: + - *bv4 # "push" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.txt b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.txt new file mode 100644 index 0000000..4c8737a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/buffer_pointer.txt @@ -0,0 +1,38 @@ +generator : Khronos Glslang Reference Front End +source lang : GLSL +source lang ver : 460 +source file : buffer_pointer.glsl +entry point : main (stage=PS) + + + Output variables: 1 + + 0: + spirv id : 26 + location : 0 + type : float4 + semantic : + name : Color + qualifier : + + + Push constant blocks: 1 + + 0: + spirv id : 14 + name : push (PushData) + // size = 16, padded size = 16 + struct PushData { + + // abs offset = 0, rel offset = 0, size = 8, padded size = 16 + ref struct Data { + float g0; // abs offset = 0, rel offset = 0, size = 4, padded +size = 4 UNUSED + float g1; // abs offset = 4, rel offset = 4, size = 4, padded +size = 4 + float g2; // abs offset = 8, rel offset = 8, size = 4, padded +size = 8 UNUSED + } data_ptr; + + } push; + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.glsl b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.glsl new file mode 100644 index 0000000..879e990 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.glsl @@ -0,0 +1,9 @@ +#version 450 +#pragma shader_stage(vertex) + +layout (location = 0) out vec3 texcoord; + +void main() { + gl_Position = vec4(gl_VertexIndex, 0, 0, 1); + texcoord = vec3(0,0,0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv new file mode 100644 index 0000000..c69440d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv.yaml new file mode 100644 index 0000000..f3525da --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/built_in_format.spv.yaml @@ -0,0 +1,283 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td5 + id: 11 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td1 + - *td2 + - *td3 + - *td4 + - &td6 + id: 25 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 17 + name: "gl_VertexIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 42 # VertexIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv5 + spirv_id: 13 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td5 + word_offset: { location: 0 } + - &iv6 + spirv_id: 27 + name: "texcoord" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td6 + word_offset: { location: 126 } +module: + generator: 13 # Google Shaderc over Glslang + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv0 # "gl_VertexIndex" + output_variable_count: 2, + output_variables: + - *iv5 # "" + - *iv6 # "texcoord" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.glsl b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.glsl new file mode 100644 index 0000000..ac23caa --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.glsl @@ -0,0 +1,22 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +struct B { + float a; +}; +layout (binding = 0) uniform Test { + B b; +} test; +float dothing(const in B b) { + return b.a; +} +layout(location = 0) out vec4 outColor; +void main() { + outColor = vec4(0); + // this is fine + outColor.z = test.b.a; + // this line causes SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE + outColor.z = dothing(test.b); +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv new file mode 100644 index 0000000..772b58d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv.yaml new file mode 100644 index 0000000..b19c475 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/fn_struct_param.spv.yaml @@ -0,0 +1,188 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 22 + op: 30 + type_name: "B" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 23 + op: 30 + type_name: "Test" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 17 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "test" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 25 + name: "test" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "test" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 126, set: 122 } +all_interface_variables: + - &iv0 + spirv_id: 19 + name: "outColor" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 105 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "test" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "test" + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "outColor" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.glsl b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.glsl new file mode 100644 index 0000000..485e2c4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.glsl @@ -0,0 +1,36 @@ +#version 450 core + +struct structX +{ + int x1_; + int x2_; +}; + +struct structY +{ + int y1_; + structX y2_[2]; +}; + +struct structZ +{ + structX z_[2][2]; +}; + +layout(location = 0) flat in structY in_a; + +layout(location = 5) flat in structX int_b[2]; + +layout(location = 10) in inC { + structX c_[2]; +} in_c; + +layout(location = 14) flat in structX int_d[2][2]; + +layout(location = 22) in inE { + structZ e_[2]; +} in_e; + +layout(location = 38) flat in int in_f[2][2]; + +void main() { } diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv new file mode 100644 index 0000000..50d6e40 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv.yaml new file mode 100644 index 0000000..b71ebba --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/frag_array_input.spv.yaml @@ -0,0 +1,760 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "y1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 21 + type_name: + struct_member_name: "x1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "x2_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 28 + type_name: "structX" + struct_member_name: "y2_" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *td1 + - *td2 + - &td4 + id: 11 + op: 30 + type_name: "structY" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td3 + - &td5 + id: 6 + op: 21 + type_name: + struct_member_name: "x1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 6 + op: 21 + type_name: + struct_member_name: "x2_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 10 + op: 28 + type_name: "structX" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *td5 + - *td6 + - &td8 + id: 6 + op: 21 + type_name: + struct_member_name: "x1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 6 + op: 21 + type_name: + struct_member_name: "x2_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 10 + op: 28 + type_name: "structX" + struct_member_name: "c_" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *td8 + - *td9 + - &td11 + id: 16 + op: 30 + type_name: "inC" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td10 + - &td12 + id: 6 + op: 21 + type_name: + struct_member_name: "x1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 6 + op: 21 + type_name: + struct_member_name: "x2_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 19 + op: 28 + type_name: "structX" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 2, dims: [2,2,], stride: 0 } + member_count: 2 + members: + - *td12 + - *td13 + - &td15 + id: 6 + op: 21 + type_name: + struct_member_name: "x1_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 6 + op: 21 + type_name: + struct_member_name: "x2_" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 19 + op: 28 + type_name: "structX" + struct_member_name: "z_" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 2, dims: [2,2,], stride: 0 } + member_count: 2 + members: + - *td15 + - *td16 + - &td18 + id: 23 + op: 28 + type_name: "structZ" + struct_member_name: "e_" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 1 + members: + - *td17 + - &td19 + id: 24 + op: 30 + type_name: "inE" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td18 + - &td20 + id: 28 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 2, dims: [2,2,], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *iv1 # + - *iv2 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 13 + name: "in_a" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000040 # FLAT + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *iv0 # + - *iv3 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td4 + word_offset: { location: 113 } + - &iv5 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv6 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv7 + spirv_id: 15 + name: "int_b" + location: 5 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000040 # FLAT + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *iv5 # + - *iv6 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td7 + word_offset: { location: 120 } + - &iv8 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv9 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv10 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 2 + members: + - *iv8 # + - *iv9 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td10 + word_offset: { location: 0 } + - &iv11 + spirv_id: 18 + name: "in_c" + location: 10 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000001 # BLOCK + built_in: 0 # [Position] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *iv10 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td11 + word_offset: { location: 127 } + - &iv12 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv13 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv14 + spirv_id: 21 + name: "int_d" + location: 14 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000040 # FLAT + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 2, dims: [2,2,], stride: 0 } + member_count: 2 + members: + - *iv12 # + - *iv13 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td14 + word_offset: { location: 134 } + - &iv15 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv16 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 1 + members: + - *iv15 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td18 + word_offset: { location: 0 } + - &iv17 + spirv_id: 26 + name: "in_e" + location: 22 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000001 # BLOCK + built_in: 0 # [Position] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *iv16 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td19 + word_offset: { location: 141 } + - &iv18 + spirv_id: 30 + name: "in_f" + location: 38 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000040 # FLAT + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 2, dims: [2,2,], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td20 + word_offset: { location: 148 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 6, + input_variables: + - *iv4 # "in_a" + - *iv7 # "int_b" + - *iv11 # "in_c" + - *iv14 # "int_d" + - *iv17 # "in_e" + - *iv18 # "in_f" + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.glsl b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.glsl new file mode 100644 index 0000000..fd4902f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.glsl @@ -0,0 +1,20 @@ +#version 320 es +#extension GL_EXT_fragment_shader_barycentric : require + +precision highp float; + +layout(location = 0) pervertexEXT in float vertexIDs[3]; +layout(location = 1) pervertexEXT in float vertexIDs2[3]; + +layout(location = 1) out float value; + +void main () { + value = (gl_BaryCoordNoPerspEXT.x * vertexIDs[0] + + gl_BaryCoordNoPerspEXT.y * vertexIDs[1] + + gl_BaryCoordNoPerspEXT.z * vertexIDs[2]); + + value += (gl_BaryCoordNoPerspEXT.x * vertexIDs2[0] + + gl_BaryCoordNoPerspEXT.y * vertexIDs2[1] + + gl_BaryCoordNoPerspEXT.z * vertexIDs2[2]); + +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv new file mode 100644 index 0000000..76a4b33 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv.yaml new file mode 100644 index 0000000..526f693 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/frag_barycentric.spv.yaml @@ -0,0 +1,154 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 18 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 11 + name: "gl_BaryCoordNoPerspEXT" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5287 # ??? (5287) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 20 + name: "vertexIDs" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000800 # PER_VERTEX + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td1 + word_offset: { location: 90 } + - &iv2 + spirv_id: 44 + name: "vertexIDs2" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000800 # PER_VERTEX + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td1 + word_offset: { location: 97 } + - &iv3 + spirv_id: 8 + name: "value" + location: 1 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 82 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 1 # ESSL + source_language_version: 320 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 3, + input_variables: + - *iv0 # "gl_BaryCoordNoPerspEXT" + - *iv1 # "vertexIDs" + - *iv2 # "vertexIDs2" + output_variable_count: 1, + output_variables: + - *iv3 # "value" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.glsl b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.glsl new file mode 100644 index 0000000..80cdfa4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.glsl @@ -0,0 +1,16 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput MyInputAttachment0; +layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput MyInputAttachment1; +layout (input_attachment_index = 4, set = 0, binding = 2) uniform subpassInput MyInputAttachment4; + +layout (location = 0) out vec4 oColor; + +void main() { + oColor = subpassLoad(MyInputAttachment0) + + subpassLoad(MyInputAttachment1) + + subpassLoad(MyInputAttachment4); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv new file mode 100644 index 0000000..248e960 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv.yaml new file mode 100644 index 0000000..6ef7eae --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.spv.yaml @@ -0,0 +1,188 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 6, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 0 } # dim=SubpassData image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "MyInputAttachment0" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 10 # VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + resource_type: 0 # UNDEFINED + image: { dim: 6, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 0 } # dim=SubpassData image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 106, set: 102 } + - &db1 + spirv_id: 19 + name: "MyInputAttachment1" + binding: 1 + input_attachment_index: 1 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 10 # VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + resource_type: 0 # UNDEFINED + image: { dim: 6, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 0 } # dim=SubpassData image_format=Unknown + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 118, set: 114 } + - &db2 + spirv_id: 23 + name: "MyInputAttachment4" + binding: 2 + input_attachment_index: 4 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 10 # VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + resource_type: 0 # UNDEFINED + image: { dim: 6, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 0 } # dim=SubpassData image_format=Unknown + block: *bv2 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 130, set: 126 } +all_interface_variables: + - &iv0 + spirv_id: 9 + name: "oColor" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 98 } +module: + generator: 13 # Google Shaderc over Glslang + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 3 + descriptor_bindings: + - *db0 # "MyInputAttachment0" + - *db1 # "MyInputAttachment1" + - *db2 # "MyInputAttachment4" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 3 + bindings: + - *db0 # "MyInputAttachment0" + - *db1 # "MyInputAttachment1" + - *db2 # "MyInputAttachment4" + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "oColor" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.txt b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.txt new file mode 100644 index 0000000..a002639 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/input_attachment.txt @@ -0,0 +1,48 @@ +generator : Google Shaderc over Glslang +entry point : main +source lang : GLSL +source lang ver : 450 +source file : +shader stage : PS + + + Output variables: 1 + + 0: + spirv id : 9 + location : 0 + type : float4 + semantic : + name : oColor + qualifier : + + + Descriptor bindings: 3 + + Binding 0.0 + spirv id : 12 + set : 0 + binding : 0 + type : VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT (UNDEFINED) + count : 1 + accessed : true + name : MyInputAttachment0 + + Binding 0.1 + spirv id : 19 + set : 0 + binding : 1 + type : VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT (UNDEFINED) + count : 1 + accessed : true + name : MyInputAttachment1 + + Binding 0.2 + spirv id : 23 + set : 0 + binding : 2 + type : VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT (UNDEFINED) + count : 1 + accessed : true + name : MyInputAttachment4 + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.glsl b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.glsl new file mode 100644 index 0000000..c4f3d4e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.glsl @@ -0,0 +1,13 @@ +#version 450 +#pragma shader_stage(vertex) + +layout (location = 0) out vec3 texcoord; +layout (location = 1) out vec4 colors[4]; +layout (location = 6) out vec3 normals[4][3][2]; + +void main() { + gl_Position = vec4(gl_VertexIndex, 0, 0, 1); + texcoord = vec3(0,0,0); + colors[1] = vec4(0); + normals[3][2][1] = vec3(0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv new file mode 100644 index 0000000..4c2d9ff Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv.yaml new file mode 100644 index 0000000..513d4b0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/io_vars_vs.spv.yaml @@ -0,0 +1,355 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td5 + id: 11 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td1 + - *td2 + - *td3 + - *td4 + - &td6 + id: 25 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 30 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + - &td8 + id: 40 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 3, dims: [4,3,2,], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 17 + name: "gl_VertexIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 42 # VertexIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv5 + spirv_id: 13 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td5 + word_offset: { location: 0 } + - &iv6 + spirv_id: 27 + name: "texcoord" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td6 + word_offset: { location: 118 } + - &iv7 + spirv_id: 32 + name: "colors" + location: 1 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td7 + word_offset: { location: 122 } + - &iv8 + spirv_id: 42 + name: "normals" + location: 6 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 3, dims: [4,3,2,], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td8 + word_offset: { location: 126 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv0 # "gl_VertexIndex" + output_variable_count: 4, + output_variables: + - *iv5 # "" + - *iv6 # "texcoord" + - *iv7 # "colors" + - *iv8 # "normals" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.glsl b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.glsl new file mode 100644 index 0000000..8b84f79 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.glsl @@ -0,0 +1,67 @@ +/* +Build with DXC using -Od to preserve unused types: + + glslangValidator.exe -Od -V -R --aml --amb -e main -S frag -o matrix_major_order_glsl.spv matrix_major_order_glsl.glsl + +*/ +#version 450 + +// +// NOTE: GLSL does not have 1xN or Nx1 matrices +// + +// ----------------------------------------------------------------------------- +// Matrices without row / column major decoration +// ----------------------------------------------------------------------------- + +uniform mat2x2 mat_2x2; +uniform mat2x3 mat_2x3; +uniform mat2x4 mat_2x4; + +uniform mat3x2 mat_3x2; +uniform mat3x3 mat_3x3; +uniform mat3x4 mat_3x4; + +uniform mat4x2 mat_4x2; +uniform mat4x3 mat_4x3; +uniform mat4x4 mat_4x4; + +// ----------------------------------------------------------------------------- +// Matrices with row major decoration +// ----------------------------------------------------------------------------- + +layout(row_major) uniform mat2x2 row_major_my_mat_2x2; +layout(row_major) uniform mat2x3 row_major_my_mat_2x3; +layout(row_major) uniform mat2x4 row_major_my_mat_2x4; + +layout(row_major) uniform mat3x2 row_major_my_mat_3x2; +layout(row_major) uniform mat3x3 row_major_my_mat_3x3; +layout(row_major) uniform mat3x4 row_major_my_mat_3x4; + +layout(row_major) uniform mat4x2 row_major_my_mat_4x2; +layout(row_major) uniform mat4x3 row_major_my_mat_4x3; +layout(row_major) uniform mat4x4 row_major_my_mat_4x4; + +// ----------------------------------------------------------------------------- +// Matrices with column major decoration +// ----------------------------------------------------------------------------- + +layout(column_major) uniform mat2x2 column_major_my_mat_2x2; +layout(column_major) uniform mat2x3 column_major_my_mat_2x3; +layout(column_major) uniform mat2x4 column_major_my_mat_2x4; + +layout(column_major) uniform mat3x2 column_major_my_mat_3x2; +layout(column_major) uniform mat3x3 column_major_my_mat_3x3; +layout(column_major) uniform mat3x4 column_major_my_mat_3x4; + +layout(column_major) uniform mat4x2 column_major_my_mat_4x2; +layout(column_major) uniform mat4x3 column_major_my_mat_4x3; +layout(column_major) uniform mat4x4 column_major_my_mat_4x4; + +layout(location = 1) in vec4 my_input; +layout(location = 0) out vec4 my_output; + +void main() +{ + my_output = my_input; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv new file mode 100644 index 0000000..80b2b1a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv.yaml new file mode 100644 index 0000000..37f998e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/matrix_major_order_glsl.spv.yaml @@ -0,0 +1,1082 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 24 + type_name: + struct_member_name: "mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 16 + op: 24 + type_name: + struct_member_name: "mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 17 + op: 24 + type_name: + struct_member_name: "mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 18 + op: 24 + type_name: + struct_member_name: "mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 19 + op: 24 + type_name: + struct_member_name: "mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 20 + op: 24 + type_name: + struct_member_name: "mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 21 + op: 24 + type_name: + struct_member_name: "mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 22 + op: 24 + type_name: + struct_member_name: "mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 23 + op: 24 + type_name: + struct_member_name: "mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 14 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 16 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 17 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 18 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 19 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 20 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 21 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 22 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 23 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 14 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 16 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 17 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 18 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 19 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 20 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 21 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 22 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 23 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td27 + id: 24 + op: 30 + type_name: "gl_DefaultUniformBlock" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 27 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - *td10 + - *td11 + - *td12 + - *td13 + - *td14 + - *td15 + - *td16 + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - *td24 + - *td25 + - *td26 + - &td28 + id: 7 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "mat_2x2" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "mat_2x3" + offset: 32 + absolute_offset: 32 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "mat_2x4" + offset: 64 + absolute_offset: 64 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "mat_3x2" + offset: 96 + absolute_offset: 96 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "mat_3x3" + offset: 144 + absolute_offset: 144 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "mat_3x4" + offset: 192 + absolute_offset: 192 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "mat_4x2" + offset: 240 + absolute_offset: 240 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "mat_4x3" + offset: 304 + absolute_offset: 304 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "mat_4x4" + offset: 368 + absolute_offset: 368 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "row_major_my_mat_2x2" + offset: 432 + absolute_offset: 432 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "row_major_my_mat_2x3" + offset: 464 + absolute_offset: 464 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "row_major_my_mat_2x4" + offset: 512 + absolute_offset: 512 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "row_major_my_mat_3x2" + offset: 576 + absolute_offset: 576 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "row_major_my_mat_3x3" + offset: 608 + absolute_offset: 608 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "row_major_my_mat_3x4" + offset: 656 + absolute_offset: 656 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "row_major_my_mat_4x2" + offset: 720 + absolute_offset: 720 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "row_major_my_mat_4x3" + offset: 752 + absolute_offset: 752 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "row_major_my_mat_4x4" + offset: 800 + absolute_offset: 800 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td17 + - &bv18 + name: "column_major_my_mat_2x2" + offset: 864 + absolute_offset: 864 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "column_major_my_mat_2x3" + offset: 896 + absolute_offset: 896 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "column_major_my_mat_2x4" + offset: 928 + absolute_offset: 928 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "column_major_my_mat_3x2" + offset: 960 + absolute_offset: 960 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "column_major_my_mat_3x3" + offset: 1008 + absolute_offset: 1008 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "column_major_my_mat_3x4" + offset: 1056 + absolute_offset: 1056 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "column_major_my_mat_4x2" + offset: 1104 + absolute_offset: 1104 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "column_major_my_mat_4x3" + offset: 1168 + absolute_offset: 1168 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "column_major_my_mat_4x4" + offset: 1232 + absolute_offset: 1232 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td26 + - &bv27 + name: "" + offset: 0 + absolute_offset: 0 + size: 1296 + padded_size: 1296 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 27 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + - *bv10 + - *bv11 + - *bv12 + - *bv13 + - *bv14 + - *bv15 + - *bv16 + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + - *bv24 + - *bv25 + - *bv26 + type_description: *td27 +all_descriptor_bindings: + - &db0 + spirv_id: 26 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv27 # "" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td27 + word_offset: { binding: 657, set: 653 } +all_interface_variables: + - &iv0 + spirv_id: 11 + name: "my_input" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td28 + word_offset: { location: 268 } + - &iv1 + spirv_id: 9 + name: "my_output" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td28 + word_offset: { location: 264 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 1, + input_variables: + - *iv0 # "my_input" + output_variable_count: 1, + output_variables: + - *iv1 # "my_output" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.glsl b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.glsl new file mode 100644 index 0000000..164a447 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.glsl @@ -0,0 +1,16 @@ +/* +Compile: + glslangValidator.exe -V -S comp -o non_writable_image.spv non_writable_image.glsl +*/ +#version 450 +#pragma shader_stage(compute) + +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +layout(set = 0, binding = 0, rgba32f) uniform readonly image2D input_image; +layout(set = 0, binding = 1, rgba32f) uniform writeonly image2D output_image; + +void main() { + ivec2 p = ivec2(gl_GlobalInvocationID.xy); + imageStore(output_image, p, imageLoad(input_image, p)); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv new file mode 100644 index 0000000..fbfe925 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv.yaml new file mode 100644 index 0000000..a1db6c3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/non_writable_image.spv.yaml @@ -0,0 +1,153 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 19 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 24 + name: "input_image" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 79, set: 75 } + - &db1 + spirv_id: 21 + name: "output_image" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000200 # NON_READABLE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 68, set: 64 } +all_interface_variables: + - &iv0 + spirv_id: 13 + name: "gl_GlobalInvocationID" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "input_image" + - *db1 # "output_image" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "input_image" + - *db1 # "output_image" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_GlobalInvocationID" + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.glsl b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.glsl new file mode 100644 index 0000000..194f267 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.glsl @@ -0,0 +1,21 @@ +/* +Compile: + glslangValidator.exe -V -S comp -o readonly_writeonly.spv readonly_writeonly.glsl +*/ +#version 450 +#pragma shader_stage(compute) + +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +const int kArraySize = 64; + +layout(set = 0, binding = 0) buffer storage_buffer { + readonly float a[kArraySize]; + writeonly float b[kArraySize]; + writeonly readonly float bar[kArraySize]; +} foo; + +void main() { + uint idx = gl_GlobalInvocationID.x; + foo.b[idx] = foo.a[idx]; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv new file mode 100644 index 0000000..7803a22 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv.yaml new file mode 100644 index 0000000..8c4f94e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/readonly_writeonly.spv.yaml @@ -0,0 +1,223 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 18 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 19 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 20 + op: 28 + type_name: + struct_member_name: "bar" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 4 } + member_count: 0 + members: + - &td3 + id: 21 + op: 30 + type_name: "storage_buffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 + - &td4 + id: 9 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 256 + padded_size: 256 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 256 + absolute_offset: 256 + size: 256 + padded_size: 256 + decorations: 0x00000200 # NON_READABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "bar" + offset: 512 + absolute_offset: 512 + size: 256 + padded_size: 256 + decorations: 0x00000280 # NON_WRITABLE NON_READABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "foo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 23 + name: "foo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "foo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 124, set: 120 } +all_interface_variables: + - &iv0 + spirv_id: 11 + name: "gl_GlobalInvocationID" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "foo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "foo" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_GlobalInvocationID" + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.glsl b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.glsl new file mode 100644 index 0000000..c9a5e67 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.glsl @@ -0,0 +1,24 @@ +#version 450 +#pragma shader_stage(compute) + +#extension GL_EXT_nonuniform_qualifier : enable + +layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in; + +struct Foo { + int a; + int b; +}; + +layout(set = 0, binding = 0) buffer InutBuffer { + Foo input_values[][3]; +}; + +layout(set = 0, binding = 1) buffer OutputBuffer { + Foo output_values[][3]; +}; + +void main() { + uint index = gl_GlobalInvocationID.x; + output_values[index] = input_values[index]; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv new file mode 100644 index 0000000..6f366ae Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv.yaml new file mode 100644 index 0000000..39119c1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/runtime_array_of_array_of_struct.spv.yaml @@ -0,0 +1,380 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 17 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 17 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 28 + op: 29 + type_name: "Foo" + struct_member_name: "input_values" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 2, dims: [0,3,], stride: 8 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 29 + op: 30 + type_name: "InutBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 17 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 17 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 21 + op: 29 + type_name: "Foo" + struct_member_name: "output_values" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 2, dims: [0,3,], stride: 8 } + member_count: 2 + members: + - *td4 + - *td5 + - &td7 + id: 22 + op: 30 + type_name: "OutputBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 10 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "input_values" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 + - &bv3 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "b" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "output_values" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv4 + - *bv5 + type_description: *td6 + - &bv7 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv6 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 31 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 349, set: 345 } + - &db1 + spirv_id: 24 + name: "" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 325, set: 321 } +all_interface_variables: + - &iv0 + spirv_id: 12 + name: "gl_GlobalInvocationID" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td8 + word_offset: { location: 0 } +module: + generator: 13 # Google Shaderc over Glslang + entry_point_name: "main" + entry_point_id: 5 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "" + - *db1 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "" + - *db1 # "" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_GlobalInvocationID" + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.glsl b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.glsl new file mode 100644 index 0000000..5b64169 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.glsl @@ -0,0 +1,19 @@ +#version 450 +#pragma shader_stage(compute) + +layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in; + +const int kArraySize = 64; + +layout(set = 0, binding = 0) buffer InputBuffer { + float input_values[kArraySize]; +}; + +layout(set = 0, binding = 1) buffer OutputBuffer { + float output_values[kArraySize]; +}; + +void main() { + uint index = gl_GlobalInvocationID.x; + output_values[index] = input_values[index]; +} diff --git a/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv new file mode 100644 index 0000000..aebbc94 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv.yaml new file mode 100644 index 0000000..25c98f7 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.spv.yaml @@ -0,0 +1,240 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 26 + op: 28 + type_name: + struct_member_name: "input_values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 27 + op: 30 + type_name: "InputBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 19 + op: 28 + type_name: + struct_member_name: "output_values" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 4 } + member_count: 0 + members: + - &td3 + id: 20 + op: 30 + type_name: "OutputBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 10 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "input_values" + offset: 0 + absolute_offset: 0 + size: 256 + padded_size: 256 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "output_values" + offset: 0 + absolute_offset: 0 + size: 256 + padded_size: 256 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 29 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 294, set: 290 } + - &db1 + spirv_id: 22 + name: "" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 274, set: 270 } +all_interface_variables: + - &iv0 + spirv_id: 12 + name: "gl_GlobalInvocationID" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 13 # Google Shaderc over Glslang + entry_point_name: "main" + entry_point_id: 5 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "" + - *db1 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "" + - *db1 # "" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_GlobalInvocationID" + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.txt b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.txt new file mode 100644 index 0000000..7ebb239 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/storage_buffer.txt @@ -0,0 +1,49 @@ +generator : Google Shaderc over Glslang +source lang : GLSL +source lang ver : 450 +source file : glsl/storage_buffer.glsl +entry point : main +local size : (32, 1, 1) + + + Input variables: 1 + + 0: + spirv id : 12 + location : (built-in) GlobalInvocationId + type : uint3 + semantic : + name : gl_GlobalInvocationID + qualifier : + + + Descriptor bindings: 2 + + Binding 0.0 + spirv id : 29 + set : 0 + binding : 0 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : true + name : (InputBuffer) + // size = 0, padded size = 0 + struct InputBuffer { + float input_values[64]; // abs offset = 0, rel offset = 0, size = 256, padded size = 256, array stride = 4 + } ; + + + Binding 0.1 + spirv id : 22 + set : 0 + binding : 1 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : true + name : (OutputBuffer) + // size = 0, padded size = 0 + struct OutputBuffer { + float output_values[64]; // abs offset = 0, rel offset = 0, size = 256, padded size = 256, array stride = 4 + } ; + + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.glsl b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.glsl new file mode 100644 index 0000000..f35bfc6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.glsl @@ -0,0 +1,17 @@ +#version 460 + +layout(binding = 0, std430) uniform UniformBufferObject { + layout(offset = 0) float a; + layout(offset = 4) float b; + layout(offset = 8) float c; + layout(offset = 16) float d; +} ubo; + +layout(binding = 0, std430) uniform UniformBufferObject2 { + layout(offset = 4) float b; + layout(offset = 0) float a; + layout(offset = 16) float c; + layout(offset = 8) float d; +} ubo2; + +void main() {} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv new file mode 100644 index 0000000..a42d06e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv.yaml new file mode 100644 index 0000000..cdad1c5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/struct_offset_order.spv.yaml @@ -0,0 +1,414 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 22 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 6 + op: 22 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 7 + op: 30 + type_name: "UniformBufferObject" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - &td5 + id: 6 + op: 22 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 6 + op: 22 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 6 + op: 22 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 6 + op: 22 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 10 + op: 30 + type_name: "UniformBufferObject2" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td5 + - *td6 + - *td7 + - *td8 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "d" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "ubo" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "b" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "c" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "d" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "ubo2" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv5 + - *bv6 + - *bv7 + - *bv8 + type_description: *td9 +all_descriptor_bindings: + - &db0 + spirv_id: 9 + name: "ubo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # "ubo" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 126, set: 122 } + - &db1 + spirv_id: 12 + name: "ubo2" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv9 # "ubo2" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td9 + word_offset: { binding: 157, set: 153 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "ubo" + - *db1 # "ubo2" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "ubo" + - *db1 # "ubo2" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.glsl b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.glsl new file mode 100644 index 0000000..51861ac --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.glsl @@ -0,0 +1,12 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#pragma shader_stage(vertex) +layout (set = 0, binding = 1) uniform isamplerBuffer texel_buffer_i; +layout (set = 0, binding = 2) uniform samplerBuffer texel_buffer_f; + +void main() { + int i = texelFetch(texel_buffer_i, gl_InstanceIndex).x; + float f = texelFetch(texel_buffer_f, gl_InstanceIndex).x; + gl_Position = vec4(i, f, 0, 1); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv new file mode 100644 index 0000000..9ae2cee Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv.yaml new file mode 100644 index 0000000..36860dc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.spv.yaml @@ -0,0 +1,354 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 27 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00050004 # EXTERNAL_SAMPLED_IMAGE EXTERNAL_IMAGE INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Buffer image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 27 + op: 27 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00050008 # EXTERNAL_SAMPLED_IMAGE EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Buffer image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 33 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 23 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 37 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td6 + id: 37 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td7 + id: 38 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td3 + - *td4 + - *td5 + - *td6 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "texel_buffer_i" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 4 # VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + resource_type: 4 # SRV + image: { dim: 5, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Buffer image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 136, set: 132 } + - &db1 + spirv_id: 29 + name: "texel_buffer_f" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 4 # VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + resource_type: 4 # SRV + image: { dim: 5, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Buffer image_format=Unknown + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 148, set: 144 } +all_interface_variables: + - &iv0 + spirv_id: 15 + name: "gl_InstanceIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 43 # InstanceIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td2 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td6 + word_offset: { location: 0 } + - &iv5 + spirv_id: 40 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td7 + word_offset: { location: 0 } +module: + generator: 13 # Google Shaderc over Glslang + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "texel_buffer_i" + - *db1 # "texel_buffer_f" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "texel_buffer_i" + - *db1 # "texel_buffer_f" + input_variable_count: 1, + input_variables: + - *iv0 # "gl_InstanceIndex" + output_variable_count: 1, + output_variables: + - *iv5 # "" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.txt b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.txt new file mode 100644 index 0000000..dc3c5e6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/texel_buffer.txt @@ -0,0 +1,50 @@ +generator : Google Shaderc over Glslang +entry point : main +source lang : GLSL +source lang ver : 450 +source file : +shader stage : VS + + + Input variables: 1 + + 0: + spirv id : 15 + location : (built-in) InstanceIndex + type : int + semantic : + name : gl_InstanceIndex + qualifier : + + + Output variables: 1 + + 0: + spirv id : 40 + location : (built-in) ??? + type : + semantic : + name : + qualifier : + + + Descriptor bindings: 2 + + Binding 0.1 + spirv id : 12 + set : 0 + binding : 1 + type : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER (SRV) + count : 1 + accessed : true + name : texel_buffer_i + + Binding 0.2 + spirv id : 29 + set : 0 + binding : 2 + type : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER (SRV) + count : 1 + accessed : true + name : texel_buffer_f + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.glsl b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.glsl new file mode 100644 index 0000000..985f3ac --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.glsl @@ -0,0 +1,17 @@ +#version 450 +#extension GL_QCOM_image_processing : require + +layout(set = 0, binding = 0) uniform texture2D inTex; +layout(set = 0, binding = 3) uniform sampler linearSampler; +layout(set = 0, binding = 1) uniform texture2DArray kernelTex; +layout(set = 0, binding = 4) uniform sampler weightSampler; + +layout(location = 0) out vec4 fragColor; +layout(location = 0) in vec2 uv; + +void main() +{ + vec4 _32 = textureWeightedQCOM(sampler2D(inTex, linearSampler), uv, sampler2DArray(kernelTex, weightSampler)); + fragColor = _32; +} + diff --git a/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv new file mode 100644 index 0000000..94fb0fd Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv.yaml b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv.yaml new file mode 100644 index 0000000..a297c8a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/glsl/weight_texture_qcom.spv.yaml @@ -0,0 +1,293 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 24 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 14 + op: 26 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00020000 # EXTERNAL_SAMPLER + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 20 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 7 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "inTex" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 91, set: 87 } + - &db1 + spirv_id: 26 + name: "kernelTex" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00002000 # WEIGHT_TEXTURE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 0, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 111, set: 107 } + - &db2 + spirv_id: 16 + name: "linearSampler" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 0 # VK_DESCRIPTOR_TYPE_SAMPLER + resource_type: 1 # SAMPLER + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 99, set: 95 } + - &db3 + spirv_id: 28 + name: "weightSampler" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 0 # VK_DESCRIPTOR_TYPE_SAMPLER + resource_type: 1 # SAMPLER + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 119, set: 115 } +all_interface_variables: + - &iv0 + spirv_id: 22 + name: "uv" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td3 + word_offset: { location: 103 } + - &iv1 + spirv_id: 9 + name: "fragColor" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td4 + word_offset: { location: 83 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 4 + descriptor_bindings: + - *db0 # "inTex" + - *db1 # "kernelTex" + - *db2 # "linearSampler" + - *db3 # "weightSampler" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 4 + bindings: + - *db0 # "inTex" + - *db1 # "kernelTex" + - *db2 # "linearSampler" + - *db3 # "weightSampler" + input_variable_count: 1, + input_variables: + - *iv0 # "uv" + output_variable_count: 1, + output_variables: + - *iv1 # "fragColor" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.hlsl new file mode 100644 index 0000000..ae52808 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.hlsl @@ -0,0 +1,14 @@ + +struct Data { + uint rgba; +}; + +ConsumeStructuredBuffer BufferIn : register(u0, space1); +AppendStructuredBuffer BufferOut : register(u1, space2); + +float4 main(float4 sv_pos : SV_Position) : SV_TARGET +{ + Data val = BufferIn.Consume(); + BufferOut.Append(val); + return float4(1, 0, 0, 0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv new file mode 100644 index 0000000..266aaf3 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv.yaml new file mode 100644 index 0000000..6cddd99 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.spv.yaml @@ -0,0 +1,472 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 2 + op: 21 + type_name: + struct_member_name: "rgba" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 4 + op: 29 + type_name: "Data" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 1 + members: + - *td0 + - &td2 + id: 5 + op: 30 + type_name: "type.ConsumeStructuredBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 8 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 9 + op: 30 + type_name: "type.ACSBuffer.counter" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 2 + op: 21 + type_name: + struct_member_name: "rgba" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 4 + op: 29 + type_name: "Data" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 1 + members: + - *td5 + - &td7 + id: 12 + op: 30 + type_name: "type.AppendStructuredBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 22 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "rgba" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "BufferIn" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "counter.var.BufferOut" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 + - &bv5 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv6 + name: "counter.var.BufferIn" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv5 + type_description: *td4 + - &bv7 + name: "rgba" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv8 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv7 + type_description: *td6 + - &bv9 + name: "BufferOut" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv8 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 11 + name: "counter.var.BufferIn" + binding: 1 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # "counter.var.BufferIn" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 320, set: 316 } + - &db1 + spirv_id: 7 + name: "BufferIn" + binding: 0 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "BufferIn" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 11 + uav_counter_binding: *db0 # "counter.var.BufferIn" + type_description: *td2 + word_offset: { binding: 304, set: 300 } + - &db2 + spirv_id: 15 + name: "counter.var.BufferOut" + binding: 0 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # "counter.var.BufferOut" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 328, set: 324 } + - *db0 + - &db3 + spirv_id: 14 + name: "BufferOut" + binding: 1 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv9 # "BufferOut" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 15 + uav_counter_binding: *db2 # "counter.var.BufferOut" + type_description: *td7 + word_offset: { binding: 312, set: 308 } +all_interface_variables: + - &iv0 + spirv_id: 26 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_Position" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td8 + word_offset: { location: 0 } + - &iv1 + spirv_id: 30 + name: "out.var.SV_TARGET" + location: 0 + storage_class: 3 # Output + semantic: "SV_TARGET" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td8 + word_offset: { location: 296 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 19 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 4 + descriptor_bindings: + - *db1 # "BufferIn" + - *db2 # "counter.var.BufferOut" + - *db0 # "counter.var.BufferIn" + - *db3 # "BufferOut" + descriptor_set_count: 2 + descriptor_sets: + - set: 1 + binding_count: 2 + bindings: + - *db1 # "BufferIn" + - *db0 # "counter.var.BufferIn" + - set: 2 + binding_count: 2 + bindings: + - *db2 # "counter.var.BufferOut" + - *db3 # "BufferOut" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 1, + output_variables: + - *iv1 # "out.var.SV_TARGET" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.txt b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.txt new file mode 100644 index 0000000..04b78cd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/append_consume.txt @@ -0,0 +1,100 @@ +generator : Google spiregg +entry point : main +source lang : HLSL +source lang ver : 600 +source file : hlsl/append_consume.hlsl +shader stage : PS + + + Input variables: 1 + + 0: + spirv id : 26 + location : (built-in) FragCoord + type : float4 + semantic : SV_Position + name : + qualifier : + + + Output variables: 1 + + 0: + spirv id : 30 + location : 0 + type : float4 + semantic : SV_TARGET + name : out.var.SV_TARGET + qualifier : + + + Descriptor bindings: 4 + + Binding 1.0 + spirv id : 7 + set : 1 + binding : 0 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=1, binding=1, name=counter.var.BufferIn); + accessed : true + name : BufferIn (type.ConsumeStructuredBuffer.Data) + // size = 0, padded size = 0 + struct type.ConsumeStructuredBuffer.Data { + + // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + struct Data { + uint rgba; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } ; + + } BufferIn; + + + Binding 1.1 + spirv id : 11 + set : 1 + binding : 1 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : true + name : counter.var.BufferIn (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.BufferIn; + + + Binding 2.0 + spirv id : 15 + set : 2 + binding : 0 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : true + name : counter.var.BufferOut (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.BufferOut; + + + Binding 2.1 + spirv id : 14 + set : 2 + binding : 1 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=2, binding=0, name=counter.var.BufferOut); + accessed : true + name : BufferOut (type.AppendStructuredBuffer.Data) + // size = 0, padded size = 0 + struct type.AppendStructuredBuffer.Data { + + // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + struct Data { + uint rgba; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } ; + + } BufferOut; + + diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.hlsl new file mode 100644 index 0000000..e84ce26 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.hlsl @@ -0,0 +1,12 @@ +StructuredBuffer Input[16] : register(t0); +RWStructuredBuffer Output : register(u1); + +[numthreads(16, 16, 1)] +void main(uint3 tid : SV_DispatchThreadID) +{ + float3 value = (float3)0; + for (int i = 0; i < 16; ++i) { + value += Input[tid.x][i]; + } + Output[tid.x] = value; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv new file mode 100644 index 0000000..c1db8a1 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv.yaml new file mode 100644 index 0000000..fbc3421 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/array_of_structured_buffer.spv.yaml @@ -0,0 +1,240 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 12 } + member_count: 0 + members: + - &td1 + id: 18 + op: 28 + type_name: "type.StructuredBuffer.v3float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [16,], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 7 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 12 } + member_count: 0 + members: + - &td3 + id: 5 + op: 30 + type_name: "type.RWStructuredBuffer.v3float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Input" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "Output" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 4 + name: "Input" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "Input" + array: { dims_count: 1, dims: [16,] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 68, set: 64 } + - &db1 + spirv_id: 6 + name: "Output" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "Output" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 76, set: 72 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "Input" + - *db1 # "Output" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "Input" + - *db1 # "Output" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.hlsl new file mode 100644 index 0000000..dd5b728 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.hlsl @@ -0,0 +1,10 @@ + +//SamplerState MySampler[4][3][2][1] : register(s0); +SamplerState MySampler[6] : register(s0); +Texture2D MyTexture[2] : register(t8); + +float4 main(float4 sv_pos : SV_POSITION) : SV_TARGET { + float4 ret0 = MyTexture[0].Sample(MySampler[0], float2(0, 0)); + float4 ret1 = MyTexture[1].Sample(MySampler[3], float2(0, 0)); + return ret0 + ret1; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv new file mode 100644 index 0000000..8a6f600 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv.yaml new file mode 100644 index 0000000..14ee29e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.spv.yaml @@ -0,0 +1,189 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 5 + op: 28 + type_name: "type.sampler" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20020000 # ARRAY EXTERNAL_SAMPLER + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [6,], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 28 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + - &td2 + id: 19 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 7 + name: "MySampler" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 0 # VK_DESCRIPTOR_TYPE_SAMPLER + resource_type: 1 # SAMPLER + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 1, dims: [6,] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 219, set: 215 } + - &db1 + spirv_id: 13 + name: "MyTexture" + binding: 8 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv1 # + array: { dims_count: 1, dims: [2,] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 227, set: 223 } +all_interface_variables: + - &iv0 + spirv_id: 23 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_POSITION" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv1 + spirv_id: 27 + name: "out.var.SV_TARGET" + location: 0 + storage_class: 3 # Output + semantic: "SV_TARGET" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td2 + word_offset: { location: 211 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 17 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "MySampler" + - *db1 # "MyTexture" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "MySampler" + - *db1 # "MyTexture" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 1, + output_variables: + - *iv1 # "out.var.SV_TARGET" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.txt b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.txt new file mode 100644 index 0000000..987b2cf --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_array.txt @@ -0,0 +1,52 @@ +generator : Google spiregg +entry point : main +source lang : HLSL +source lang ver : 600 +source file : hlsl/binding_array.hlsl +shader stage : PS + + + Input variables: 1 + + 0: + spirv id : 23 + location : (built-in) FragCoord + type : float4 + semantic : SV_POSITION + name : + qualifier : + + + Output variables: 1 + + 0: + spirv id : 27 + location : 0 + type : float4 + semantic : SV_TARGET + name : out.var.SV_TARGET + qualifier : + + + Descriptor bindings: 2 + + Binding 0.0 + spirv id : 7 + set : 0 + binding : 0 + type : VK_DESCRIPTOR_TYPE_SAMPLER (SAMPLER) + count : 6 + array : [6] + accessed : true + name : MySampler (type.sampler) + + Binding 0.8 + spirv id : 13 + set : 0 + binding : 8 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 2 + array : [2] + accessed : true + name : MyTexture (type.2d.image) + diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.hlsl new file mode 100644 index 0000000..0d45077 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.hlsl @@ -0,0 +1,60 @@ +/* +Build with DXC using -O0 to preserve unused types: + + dxc -spirv -O0 -T ps_5_0 -Fo binding_types.spv binding_types.hlsl + +*/ + +cbuffer MyCBuffer { + float x; +}; + +struct Data { float x; }; +ConstantBuffer MyConstantBuffer; + +Texture1D MyTexture1D; +Texture2D MyTexture2D; +Texture3D MyTexture3D; + +Texture1DArray MyTexture1DArray; +Texture2DArray MyTexture2DArray; + +RWTexture1D MyRWTexture1D; +RWTexture2D MyRWTexture2D; +RWTexture3D MyRWTexture3D; + +RWTexture1DArray MyRWTexture1DArray; +RWTexture2DArray MyRWTexture2DArray; + +Texture2DMS MyTexture2DMS; +Texture2DMSArray MyTexture2DMSArray; + +TextureCube MyTextureCube; +TextureCubeArray MyTextureCubeArray; + +tbuffer MyTBuffer { + float q; +}; + +struct Data2 { + float4 x; +}; + +TextureBuffer MyTextureBuffer; + +Buffer MyBuffer; +RWBuffer MyRWBuffer; + +StructuredBuffer MyStructuredBuffer; +RWStructuredBuffer MyRWStructuredBuffer; + +AppendStructuredBuffer MyAppendStructuredBuffer; +ConsumeStructuredBuffer MyConsumeStructuredBuffer; + +ByteAddressBuffer MyByteAddressBuffer; +RWByteAddressBuffer MyRWByteAddressBuffer; + +float4 main(float4 P : SV_POSITION) : SV_TARGET +{ + return float4(0, 0, 0, 0); +} diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv new file mode 100644 index 0000000..e38980c Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv.yaml new file mode 100644 index 0000000..65c727d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.spv.yaml @@ -0,0 +1,1981 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 2 + op: 22 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 3 + op: 30 + type_name: "type.MyCBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 2 + op: 22 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 6 + op: 30 + type_name: "type.ConstantBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 9 + op: 25 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 12 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 15 + op: 25 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 18 + op: 25 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 21 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 24 + op: 25 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=1D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 27 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 30 + op: 25 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=3D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 33 + op: 25 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 1 } # dim=1D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 36 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 39 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 42 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 45 + op: 25 + type_name: "type.cube.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 48 + op: 25 + type_name: "type.cube.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 2 + op: 22 + type_name: + struct_member_name: "q" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 51 + op: 30 + type_name: "type.MyTBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td18 + - &td20 + id: 54 + op: 23 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 55 + op: 30 + type_name: "type.TextureBuffer.Data2" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td20 + - &td22 + id: 58 + op: 25 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 1 } # dim=Buffer image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 61 + op: 25 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=Buffer image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 64 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td25 + id: 65 + op: 30 + type_name: "type.StructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td24 + - &td26 + id: 64 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td27 + id: 68 + op: 30 + type_name: "type.RWStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td26 + - &td28 + id: 71 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td29 + id: 72 + op: 30 + type_name: "type.ACSBuffer.counter" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td28 + - &td30 + id: 64 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td31 + id: 75 + op: 30 + type_name: "type.AppendStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td30 + - &td32 + id: 64 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td33 + id: 79 + op: 30 + type_name: "type.ConsumeStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td32 + - &td34 + id: 84 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td35 + id: 85 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td34 + - &td36 + id: 84 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td37 + id: 88 + op: 30 + type_name: "type.RWByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td36 + - &td38 + id: 54 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "MyCBuffer" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "MyConstantBuffer" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv5 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv6 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv7 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv8 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv9 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv10 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv11 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv12 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv13 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv14 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv15 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv16 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv17 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv18 + name: "q" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "MyTBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv18 + type_description: *td19 + - &bv20 + name: "x" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "MyTextureBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv20 + type_description: *td21 + - &bv22 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv23 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv24 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "MyStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv24 + type_description: *td25 + - &bv26 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td26 + - &bv27 + name: "MyRWStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv26 + type_description: *td27 + - &bv28 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv29 + name: "counter.var.MyRWStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv28 + type_description: *td29 + - &bv30 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td30 + - &bv31 + name: "MyAppendStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv30 + type_description: *td31 + - &bv32 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv33 + name: "counter.var.MyAppendStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv32 + type_description: *td29 + - &bv34 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td32 + - &bv35 + name: "MyConsumeStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv34 + type_description: *td33 + - &bv36 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv37 + name: "counter.var.MyConsumeStructuredBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv36 + type_description: *td29 + - &bv38 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td34 + - &bv39 + name: "MyByteAddressBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv38 + type_description: *td35 + - &bv40 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td36 + - &bv41 + name: "MyRWByteAddressBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv40 + type_description: *td37 +all_descriptor_bindings: + - &db0 + spirv_id: 5 + name: "MyCBuffer" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "MyCBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 940, set: 936 } + - &db1 + spirv_id: 8 + name: "MyConstantBuffer" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "MyConstantBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 948, set: 944 } + - &db2 + spirv_id: 11 + name: "MyTexture1D" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 956, set: 952 } + - &db3 + spirv_id: 14 + name: "MyTexture2D" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv5 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 964, set: 960 } + - &db4 + spirv_id: 17 + name: "MyTexture3D" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + block: *bv6 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td6 + word_offset: { binding: 972, set: 968 } + - &db5 + spirv_id: 20 + name: "MyTexture1DArray" + binding: 5 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 980, set: 976 } + - &db6 + spirv_id: 23 + name: "MyTexture2DArray" + binding: 6 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv8 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 988, set: 984 } + - &db7 + spirv_id: 26 + name: "MyRWTexture1D" + binding: 7 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=1D image_format=Rgba32f + block: *bv9 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td9 + word_offset: { binding: 996, set: 992 } + - &db8 + spirv_id: 29 + name: "MyRWTexture2D" + binding: 8 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + block: *bv10 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td10 + word_offset: { binding: 1004, set: 1000 } + - &db9 + spirv_id: 32 + name: "MyRWTexture3D" + binding: 9 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=3D image_format=Rgba32f + block: *bv11 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 1012, set: 1008 } + - &db10 + spirv_id: 35 + name: "MyRWTexture1DArray" + binding: 10 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 1 } # dim=1D image_format=Rgba32f + block: *bv12 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td12 + word_offset: { binding: 1020, set: 1016 } + - &db11 + spirv_id: 38 + name: "MyRWTexture2DArray" + binding: 11 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + block: *bv13 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td13 + word_offset: { binding: 1028, set: 1024 } + - &db12 + spirv_id: 41 + name: "MyTexture2DMS" + binding: 12 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv14 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td14 + word_offset: { binding: 1036, set: 1032 } + - &db13 + spirv_id: 44 + name: "MyTexture2DMSArray" + binding: 13 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv15 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td15 + word_offset: { binding: 1044, set: 1040 } + - &db14 + spirv_id: 47 + name: "MyTextureCube" + binding: 14 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv16 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td16 + word_offset: { binding: 1052, set: 1048 } + - &db15 + spirv_id: 50 + name: "MyTextureCubeArray" + binding: 15 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv17 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 1060, set: 1056 } + - &db16 + spirv_id: 53 + name: "MyTBuffer" + binding: 16 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv19 # "MyTBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td19 + word_offset: { binding: 1068, set: 1064 } + - &db17 + spirv_id: 57 + name: "MyTextureBuffer" + binding: 17 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv21 # "MyTextureBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td21 + word_offset: { binding: 1076, set: 1072 } + - &db18 + spirv_id: 60 + name: "MyBuffer" + binding: 18 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 4 # VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + resource_type: 4 # SRV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 1 } # dim=Buffer image_format=Rgba32f + block: *bv22 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td22 + word_offset: { binding: 1084, set: 1080 } + - &db19 + spirv_id: 63 + name: "MyRWBuffer" + binding: 19 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 5 # VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + resource_type: 8 # UAV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=Buffer image_format=Rgba32f + block: *bv23 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td23 + word_offset: { binding: 1092, set: 1088 } + - &db20 + spirv_id: 67 + name: "MyStructuredBuffer" + binding: 20 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv25 # "MyStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td25 + word_offset: { binding: 1100, set: 1096 } + - &db21 + spirv_id: 74 + name: "counter.var.MyRWStructuredBuffer" + binding: 22 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv29 # "counter.var.MyRWStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1116, set: 1112 } + - &db22 + spirv_id: 70 + name: "MyRWStructuredBuffer" + binding: 21 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv27 # "MyRWStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 74 + uav_counter_binding: *db21 # "counter.var.MyRWStructuredBuffer" + type_description: *td27 + word_offset: { binding: 1108, set: 1104 } + - *db21 + - &db23 + spirv_id: 78 + name: "counter.var.MyAppendStructuredBuffer" + binding: 24 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv33 # "counter.var.MyAppendStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1132, set: 1128 } + - &db24 + spirv_id: 77 + name: "MyAppendStructuredBuffer" + binding: 23 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv31 # "MyAppendStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 78 + uav_counter_binding: *db23 # "counter.var.MyAppendStructuredBuffer" + type_description: *td31 + word_offset: { binding: 1124, set: 1120 } + - *db23 + - &db25 + spirv_id: 82 + name: "counter.var.MyConsumeStructuredBuffer" + binding: 26 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv37 # "counter.var.MyConsumeStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1148, set: 1144 } + - &db26 + spirv_id: 81 + name: "MyConsumeStructuredBuffer" + binding: 25 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv35 # "MyConsumeStructuredBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 82 + uav_counter_binding: *db25 # "counter.var.MyConsumeStructuredBuffer" + type_description: *td33 + word_offset: { binding: 1140, set: 1136 } + - *db25 + - &db27 + spirv_id: 87 + name: "MyByteAddressBuffer" + binding: 27 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv39 # "MyByteAddressBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td35 + word_offset: { binding: 1156, set: 1152 } + - &db28 + spirv_id: 90 + name: "MyRWByteAddressBuffer" + binding: 28 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv41 # "MyRWByteAddressBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td37 + word_offset: { binding: 1164, set: 1160 } +all_interface_variables: + - &iv0 + spirv_id: 99 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_POSITION" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td38 + word_offset: { location: 0 } + - &iv1 + spirv_id: 103 + name: "out.var.SV_TARGET" + location: 0 + storage_class: 3 # Output + semantic: "SV_TARGET" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td38 + word_offset: { location: 932 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 94 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 29 + descriptor_bindings: + - *db0 # "MyCBuffer" + - *db1 # "MyConstantBuffer" + - *db2 # "MyTexture1D" + - *db3 # "MyTexture2D" + - *db4 # "MyTexture3D" + - *db5 # "MyTexture1DArray" + - *db6 # "MyTexture2DArray" + - *db7 # "MyRWTexture1D" + - *db8 # "MyRWTexture2D" + - *db9 # "MyRWTexture3D" + - *db10 # "MyRWTexture1DArray" + - *db11 # "MyRWTexture2DArray" + - *db12 # "MyTexture2DMS" + - *db13 # "MyTexture2DMSArray" + - *db14 # "MyTextureCube" + - *db15 # "MyTextureCubeArray" + - *db16 # "MyTBuffer" + - *db17 # "MyTextureBuffer" + - *db18 # "MyBuffer" + - *db19 # "MyRWBuffer" + - *db20 # "MyStructuredBuffer" + - *db22 # "MyRWStructuredBuffer" + - *db21 # "counter.var.MyRWStructuredBuffer" + - *db24 # "MyAppendStructuredBuffer" + - *db23 # "counter.var.MyAppendStructuredBuffer" + - *db26 # "MyConsumeStructuredBuffer" + - *db25 # "counter.var.MyConsumeStructuredBuffer" + - *db27 # "MyByteAddressBuffer" + - *db28 # "MyRWByteAddressBuffer" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 29 + bindings: + - *db0 # "MyCBuffer" + - *db1 # "MyConstantBuffer" + - *db2 # "MyTexture1D" + - *db3 # "MyTexture2D" + - *db4 # "MyTexture3D" + - *db5 # "MyTexture1DArray" + - *db6 # "MyTexture2DArray" + - *db7 # "MyRWTexture1D" + - *db8 # "MyRWTexture2D" + - *db9 # "MyRWTexture3D" + - *db10 # "MyRWTexture1DArray" + - *db11 # "MyRWTexture2DArray" + - *db12 # "MyTexture2DMS" + - *db13 # "MyTexture2DMSArray" + - *db14 # "MyTextureCube" + - *db15 # "MyTextureCubeArray" + - *db16 # "MyTBuffer" + - *db17 # "MyTextureBuffer" + - *db18 # "MyBuffer" + - *db19 # "MyRWBuffer" + - *db20 # "MyStructuredBuffer" + - *db22 # "MyRWStructuredBuffer" + - *db21 # "counter.var.MyRWStructuredBuffer" + - *db24 # "MyAppendStructuredBuffer" + - *db23 # "counter.var.MyAppendStructuredBuffer" + - *db26 # "MyConsumeStructuredBuffer" + - *db25 # "counter.var.MyConsumeStructuredBuffer" + - *db27 # "MyByteAddressBuffer" + - *db28 # "MyRWByteAddressBuffer" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 1, + output_variables: + - *iv1 # "out.var.SV_TARGET" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.txt b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.txt new file mode 100644 index 0000000..80d215e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types.txt @@ -0,0 +1,361 @@ +generator : Google spiregg +entry point : main +source lang : HLSL +source lang ver : 600 +source file : hlsl/binding_types.hlsl +shader stage : PS + + + Input variables: 1 + + 0: + spirv id : 99 + location : (built-in) FragCoord + type : float4 + semantic : SV_POSITION + name : + qualifier : + + + Output variables: 1 + + 0: + spirv id : 103 + location : 0 + type : float4 + semantic : SV_TARGET + name : out.var.SV_TARGET + qualifier : + + + Descriptor bindings: 29 + + Binding 0.0 + spirv id : 5 + set : 0 + binding : 0 + type : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER (CBV) + count : 1 + accessed : false + name : MyCBuffer (type.MyCBuffer) + // size = 16, padded size = 16 + struct type.MyCBuffer { + float x; // abs offset = 0, rel offset = 0, size = 4, padded size = 16 + } MyCBuffer; + + + Binding 0.1 + spirv id : 8 + set : 0 + binding : 1 + type : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER (CBV) + count : 1 + accessed : false + name : MyConstantBuffer (type.ConstantBuffer.Data) + // size = 16, padded size = 16 + struct type.ConstantBuffer.Data { + float x; // abs offset = 0, rel offset = 0, size = 4, padded size = 16 + } MyConstantBuffer; + + + Binding 0.2 + spirv id : 11 + set : 0 + binding : 2 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture1D (type.1d.image) + + Binding 0.3 + spirv id : 14 + set : 0 + binding : 3 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2D (type.2d.image) + + Binding 0.4 + spirv id : 17 + set : 0 + binding : 4 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture3D (type.3d.image) + + Binding 0.5 + spirv id : 20 + set : 0 + binding : 5 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture1DArray (type.1d.image.array) + + Binding 0.6 + spirv id : 23 + set : 0 + binding : 6 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DArray (type.2d.image.array) + + Binding 0.7 + spirv id : 26 + set : 0 + binding : 7 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture1D (type.1d.image) + + Binding 0.8 + spirv id : 29 + set : 0 + binding : 8 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture2D (type.2d.image) + + Binding 0.9 + spirv id : 32 + set : 0 + binding : 9 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture3D (type.3d.image) + + Binding 0.10 + spirv id : 35 + set : 0 + binding : 10 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture1DArray (type.1d.image.array) + + Binding 0.11 + spirv id : 38 + set : 0 + binding : 11 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture2DArray (type.2d.image.array) + + Binding 0.12 + spirv id : 41 + set : 0 + binding : 12 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DMS (type.2d.image) + + Binding 0.13 + spirv id : 44 + set : 0 + binding : 13 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DMSArray (type.2d.image.array) + + Binding 0.14 + spirv id : 47 + set : 0 + binding : 14 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTextureCube (type.cube.image) + + Binding 0.15 + spirv id : 50 + set : 0 + binding : 15 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTextureCubeArray (type.cube.image.array) + + Binding 0.16 + spirv id : 53 + set : 0 + binding : 16 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyTBuffer (type.MyTBuffer) + // size = 0, padded size = 0 + struct type.MyTBuffer { + float q; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } MyTBuffer; + + + Binding 0.17 + spirv id : 57 + set : 0 + binding : 17 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyTextureBuffer (type.TextureBuffer.Data2) + // size = 0, padded size = 0 + struct type.TextureBuffer.Data2 { + float4 x; // abs offset = 0, rel offset = 0, size = 16, padded size = 16 + } MyTextureBuffer; + + + Binding 0.18 + spirv id : 60 + set : 0 + binding : 18 + type : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER (SRV) + count : 1 + accessed : false + name : MyBuffer (type.buffer.image) + + Binding 0.19 + spirv id : 63 + set : 0 + binding : 19 + type : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER (UAV) + count : 1 + accessed : false + name : MyRWBuffer (type.buffer.image) + + Binding 0.20 + spirv id : 67 + set : 0 + binding : 20 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyStructuredBuffer (type.StructuredBuffer.float) + // size = 0, padded size = 0 + struct type.StructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyStructuredBuffer; + + + Binding 0.21 + spirv id : 70 + set : 0 + binding : 21 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=22, name=counter.var.MyRWStructuredBuffer); + accessed : false + name : MyRWStructuredBuffer (type.RWStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.RWStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyRWStructuredBuffer; + + + Binding 0.22 + spirv id : 74 + set : 0 + binding : 22 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyRWStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyRWStructuredBuffer; + + + Binding 0.23 + spirv id : 77 + set : 0 + binding : 23 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=24, name=counter.var.MyAppendStructuredBuffer); + accessed : false + name : MyAppendStructuredBuffer (type.AppendStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.AppendStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyAppendStructuredBuffer; + + + Binding 0.24 + spirv id : 78 + set : 0 + binding : 24 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyAppendStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyAppendStructuredBuffer; + + + Binding 0.25 + spirv id : 81 + set : 0 + binding : 25 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=26, name=counter.var.MyConsumeStructuredBuffer); + accessed : false + name : MyConsumeStructuredBuffer (type.ConsumeStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.ConsumeStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyConsumeStructuredBuffer; + + + Binding 0.26 + spirv id : 82 + set : 0 + binding : 26 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyConsumeStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyConsumeStructuredBuffer; + + + Binding 0.27 + spirv id : 87 + set : 0 + binding : 27 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyByteAddressBuffer (type.ByteAddressBuffer) + // size = 0, padded size = 0 + struct type.ByteAddressBuffer { + uint ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyByteAddressBuffer; + + + Binding 0.28 + spirv id : 90 + set : 0 + binding : 28 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : MyRWByteAddressBuffer (type.RWByteAddressBuffer) + // size = 0, padded size = 0 + struct type.RWByteAddressBuffer { + uint ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyRWByteAddressBuffer; + + diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/binding_types_hlsl_resource_types.txt b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types_hlsl_resource_types.txt new file mode 100644 index 0000000..80d215e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/binding_types_hlsl_resource_types.txt @@ -0,0 +1,361 @@ +generator : Google spiregg +entry point : main +source lang : HLSL +source lang ver : 600 +source file : hlsl/binding_types.hlsl +shader stage : PS + + + Input variables: 1 + + 0: + spirv id : 99 + location : (built-in) FragCoord + type : float4 + semantic : SV_POSITION + name : + qualifier : + + + Output variables: 1 + + 0: + spirv id : 103 + location : 0 + type : float4 + semantic : SV_TARGET + name : out.var.SV_TARGET + qualifier : + + + Descriptor bindings: 29 + + Binding 0.0 + spirv id : 5 + set : 0 + binding : 0 + type : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER (CBV) + count : 1 + accessed : false + name : MyCBuffer (type.MyCBuffer) + // size = 16, padded size = 16 + struct type.MyCBuffer { + float x; // abs offset = 0, rel offset = 0, size = 4, padded size = 16 + } MyCBuffer; + + + Binding 0.1 + spirv id : 8 + set : 0 + binding : 1 + type : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER (CBV) + count : 1 + accessed : false + name : MyConstantBuffer (type.ConstantBuffer.Data) + // size = 16, padded size = 16 + struct type.ConstantBuffer.Data { + float x; // abs offset = 0, rel offset = 0, size = 4, padded size = 16 + } MyConstantBuffer; + + + Binding 0.2 + spirv id : 11 + set : 0 + binding : 2 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture1D (type.1d.image) + + Binding 0.3 + spirv id : 14 + set : 0 + binding : 3 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2D (type.2d.image) + + Binding 0.4 + spirv id : 17 + set : 0 + binding : 4 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture3D (type.3d.image) + + Binding 0.5 + spirv id : 20 + set : 0 + binding : 5 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture1DArray (type.1d.image.array) + + Binding 0.6 + spirv id : 23 + set : 0 + binding : 6 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DArray (type.2d.image.array) + + Binding 0.7 + spirv id : 26 + set : 0 + binding : 7 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture1D (type.1d.image) + + Binding 0.8 + spirv id : 29 + set : 0 + binding : 8 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture2D (type.2d.image) + + Binding 0.9 + spirv id : 32 + set : 0 + binding : 9 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture3D (type.3d.image) + + Binding 0.10 + spirv id : 35 + set : 0 + binding : 10 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture1DArray (type.1d.image.array) + + Binding 0.11 + spirv id : 38 + set : 0 + binding : 11 + type : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (UAV) + count : 1 + accessed : false + name : MyRWTexture2DArray (type.2d.image.array) + + Binding 0.12 + spirv id : 41 + set : 0 + binding : 12 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DMS (type.2d.image) + + Binding 0.13 + spirv id : 44 + set : 0 + binding : 13 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTexture2DMSArray (type.2d.image.array) + + Binding 0.14 + spirv id : 47 + set : 0 + binding : 14 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTextureCube (type.cube.image) + + Binding 0.15 + spirv id : 50 + set : 0 + binding : 15 + type : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (SRV) + count : 1 + accessed : false + name : MyTextureCubeArray (type.cube.image.array) + + Binding 0.16 + spirv id : 53 + set : 0 + binding : 16 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyTBuffer (type.MyTBuffer) + // size = 0, padded size = 0 + struct type.MyTBuffer { + float q; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } MyTBuffer; + + + Binding 0.17 + spirv id : 57 + set : 0 + binding : 17 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyTextureBuffer (type.TextureBuffer.Data2) + // size = 0, padded size = 0 + struct type.TextureBuffer.Data2 { + float4 x; // abs offset = 0, rel offset = 0, size = 16, padded size = 16 + } MyTextureBuffer; + + + Binding 0.18 + spirv id : 60 + set : 0 + binding : 18 + type : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER (SRV) + count : 1 + accessed : false + name : MyBuffer (type.buffer.image) + + Binding 0.19 + spirv id : 63 + set : 0 + binding : 19 + type : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER (UAV) + count : 1 + accessed : false + name : MyRWBuffer (type.buffer.image) + + Binding 0.20 + spirv id : 67 + set : 0 + binding : 20 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyStructuredBuffer (type.StructuredBuffer.float) + // size = 0, padded size = 0 + struct type.StructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyStructuredBuffer; + + + Binding 0.21 + spirv id : 70 + set : 0 + binding : 21 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=22, name=counter.var.MyRWStructuredBuffer); + accessed : false + name : MyRWStructuredBuffer (type.RWStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.RWStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyRWStructuredBuffer; + + + Binding 0.22 + spirv id : 74 + set : 0 + binding : 22 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyRWStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyRWStructuredBuffer; + + + Binding 0.23 + spirv id : 77 + set : 0 + binding : 23 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=24, name=counter.var.MyAppendStructuredBuffer); + accessed : false + name : MyAppendStructuredBuffer (type.AppendStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.AppendStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyAppendStructuredBuffer; + + + Binding 0.24 + spirv id : 78 + set : 0 + binding : 24 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyAppendStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyAppendStructuredBuffer; + + + Binding 0.25 + spirv id : 81 + set : 0 + binding : 25 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + counter : (set=0, binding=26, name=counter.var.MyConsumeStructuredBuffer); + accessed : false + name : MyConsumeStructuredBuffer (type.ConsumeStructuredBuffer.float) + // size = 0, padded size = 0 + struct type.ConsumeStructuredBuffer.float { + float ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyConsumeStructuredBuffer; + + + Binding 0.26 + spirv id : 82 + set : 0 + binding : 26 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : counter.var.MyConsumeStructuredBuffer (type.ACSBuffer.counter) + // size = 0, padded size = 0 + struct type.ACSBuffer.counter { + int ; // abs offset = 0, rel offset = 0, size = 4, padded size = 4 + } counter.var.MyConsumeStructuredBuffer; + + + Binding 0.27 + spirv id : 87 + set : 0 + binding : 27 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (SRV) + count : 1 + accessed : false + name : MyByteAddressBuffer (type.ByteAddressBuffer) + // size = 0, padded size = 0 + struct type.ByteAddressBuffer { + uint ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyByteAddressBuffer; + + + Binding 0.28 + spirv id : 90 + set : 0 + binding : 28 + type : VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (UAV) + count : 1 + accessed : false + name : MyRWByteAddressBuffer (type.RWByteAddressBuffer) + // size = 0, padded size = 0 + struct type.RWByteAddressBuffer { + uint ; // abs offset = 0, rel offset = 0, size = 0, padded size = 0 + } MyRWByteAddressBuffer; + + diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.hlsl new file mode 100644 index 0000000..51ca83b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.hlsl @@ -0,0 +1,45 @@ + +struct OmniNormalStength { + float Front; + float Back; + float Top; + float Bottom; + float Left; + float Right; +}; + +struct ClothProperties { + float3 NormalAdjust; + OmniNormalStength Strengths; + uint Type; +}; + +struct AuxData { + ClothProperties ClothProperties[8]; + float3 ClothColors[8]; + float Scales[8]; + int EnableBitMask; +}; + +struct MaterialData { + float3 Color; + float Specular; + float Diffuse; + AuxData AuxDatArray[10]; +}; + +cbuffer MyCBuffer { + MaterialData Material[2][2][3]; + float4x4 ModelMatrix; + float4x4 ProjectionMatrix; + float Time; + float3 Scale; + float2 UvOffsets[12]; + //MaterialData Material[12]; + bool EnableTarget; +}; + +float4 main(float4 pos : POSITION) : SV_Position +{ + return float4(Time, 0, 0, 0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv new file mode 100644 index 0000000..71f13ca Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv.yaml new file mode 100644 index 0000000..9fe9bd7 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/cbuffer.spv.yaml @@ -0,0 +1,977 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 3 + op: 23 + type_name: + struct_member_name: "Color" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 2 + op: 22 + type_name: + struct_member_name: "Specular" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 2 + op: 22 + type_name: + struct_member_name: "Diffuse" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 3 + op: 23 + type_name: + struct_member_name: "NormalAdjust" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 2 + op: 22 + type_name: + struct_member_name: "Front" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 2 + op: 22 + type_name: + struct_member_name: "Back" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 2 + op: 22 + type_name: + struct_member_name: "Top" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 2 + op: 22 + type_name: + struct_member_name: "Bottom" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 2 + op: 22 + type_name: + struct_member_name: "Left" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 2 + op: 22 + type_name: + struct_member_name: "Right" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 4 + op: 30 + type_name: "OmniNormalStength" + struct_member_name: "Strengths" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 6 + members: + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - &td11 + id: 5 + op: 21 + type_name: + struct_member_name: "Type" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 8 + op: 28 + type_name: "ClothProperties" + struct_member_name: "ClothProperties" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 64 } + member_count: 3 + members: + - *td3 + - *td10 + - *td11 + - &td13 + id: 9 + op: 28 + type_name: + struct_member_name: "ClothColors" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 16 } + member_count: 0 + members: + - &td14 + id: 10 + op: 28 + type_name: + struct_member_name: "Scales" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 16 } + member_count: 0 + members: + - &td15 + id: 11 + op: 21 + type_name: + struct_member_name: "EnableBitMask" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 14 + op: 28 + type_name: "AuxData" + struct_member_name: "AuxDatArray" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [10,], stride: 784 } + member_count: 4 + members: + - *td12 + - *td13 + - *td14 + - *td15 + - &td17 + id: 20 + op: 28 + type_name: "MaterialData" + struct_member_name: "Material" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 3, dims: [2,2,3,], stride: 7872 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td16 + - &td18 + id: 22 + op: 24 + type_name: + struct_member_name: "ModelMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 22 + op: 24 + type_name: + struct_member_name: "ProjectionMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 2 + op: 22 + type_name: + struct_member_name: "Time" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 3 + op: 23 + type_name: + struct_member_name: "Scale" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 25 + op: 28 + type_name: + struct_member_name: "UvOffsets" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [12,], stride: 16 } + member_count: 0 + members: + - &td23 + id: 5 + op: 21 + type_name: + struct_member_name: "EnableTarget" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 26 + op: 30 + type_name: "type.MyCBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 7 + members: + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - &td25 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "Color" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Specular" + offset: 12 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "Diffuse" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "NormalAdjust" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "Front" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "Back" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "Top" + offset: 8 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "Bottom" + offset: 12 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "Left" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "Right" + offset: 20 + absolute_offset: 0 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "Strengths" + offset: 16 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 6 + members: + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + type_description: *td10 + - &bv11 + name: "Type" + offset: 48 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "ClothProperties" + offset: 0 + absolute_offset: 0 + size: 512 + padded_size: 512 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 64 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv3 + - *bv10 + - *bv11 + type_description: *td12 + - &bv13 + name: "ClothColors" + offset: 512 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "Scales" + offset: 640 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "EnableBitMask" + offset: 768 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "AuxDatArray" + offset: 32 + absolute_offset: 0 + size: 7840 + padded_size: 7840 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [10,], stride: 784 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv12 + - *bv13 + - *bv14 + - *bv15 + type_description: *td16 + - &bv17 + name: "Material" + offset: 0 + absolute_offset: 0 + size: 94464 + padded_size: 94464 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 3, dims: [2,2,3,], stride: 7872 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv16 + type_description: *td17 + - &bv18 + name: "ModelMatrix" + offset: 94464 + absolute_offset: 94464 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "ProjectionMatrix" + offset: 94528 + absolute_offset: 94528 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "Time" + offset: 94592 + absolute_offset: 94592 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "Scale" + offset: 94596 + absolute_offset: 94596 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "UvOffsets" + offset: 94608 + absolute_offset: 94608 + size: 192 + padded_size: 192 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [12,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "EnableTarget" + offset: 94800 + absolute_offset: 94800 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "MyCBuffer" + offset: 0 + absolute_offset: 0 + size: 94816 + padded_size: 94816 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 7 + members: + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + type_description: *td24 +all_descriptor_bindings: + - &db0 + spirv_id: 28 + name: "MyCBuffer" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv24 # "MyCBuffer" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td24 + word_offset: { binding: 623, set: 619 } +all_interface_variables: + - &iv0 + spirv_id: 37 + name: "in.var.POSITION" + location: 0 + storage_class: 1 # Input + semantic: "POSITION" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td25 + word_offset: { location: 615 } + - &iv1 + spirv_id: 41 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: "SV_Position" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td25 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 32 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "MyCBuffer" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "MyCBuffer" + input_variable_count: 1, + input_variables: + - *iv0 # "in.var.POSITION" + output_variable_count: 1, + output_variables: + - *iv1 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.hlsl new file mode 100644 index 0000000..b8e216f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.hlsl @@ -0,0 +1,47 @@ + +struct OmniNormalStength { + float Front; + float Back; + float Top; + float Bottom; + float Left; + float Right; +}; + +struct ClothProperties { + float3 NormalAdjust; + OmniNormalStength Strengths; + uint Type; +}; + +struct AuxData { + ClothProperties ClothProperties[8]; + float3 ClothColors[8]; + float Scales[8]; + int EnableBitMask; +}; + +struct MaterialData { + float3 Color; + float Specular; + float Diffuse; + AuxData AuxDatArray[10]; +}; + +struct Constants { + MaterialData Material[2][2][3]; + float4x4 ModelMatrix; + float4x4 ProjectionMatrix; + float Time; + float3 Scale; + float2 UvOffsets[12]; + //MaterialData Material[12]; + bool EnableTarget; +}; + +ConstantBuffer MyConstants : register(b0); + +float4 main(float4 pos : POSITION) : SV_Position +{ + return float4(MyConstants.Time, 0, 0, 0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv new file mode 100644 index 0000000..161d59a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv.yaml new file mode 100644 index 0000000..1b17d97 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer.spv.yaml @@ -0,0 +1,1142 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 20 + op: 23 + type_name: + struct_member_name: "Color" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 19 + op: 22 + type_name: + struct_member_name: "Specular" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 19 + op: 22 + type_name: + struct_member_name: "Diffuse" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 20 + op: 23 + type_name: + struct_member_name: "NormalAdjust" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 19 + op: 22 + type_name: + struct_member_name: "Front" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 19 + op: 22 + type_name: + struct_member_name: "Back" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 19 + op: 22 + type_name: + struct_member_name: "Top" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 19 + op: 22 + type_name: + struct_member_name: "Bottom" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 19 + op: 22 + type_name: + struct_member_name: "Left" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 19 + op: 22 + type_name: + struct_member_name: "Right" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 4 + op: 30 + type_name: "OmniNormalStength" + struct_member_name: "Strengths" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 6 + members: + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - &td11 + id: 21 + op: 21 + type_name: + struct_member_name: "Type" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 11 + op: 28 + type_name: "ClothProperties" + struct_member_name: "ClothProperties" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 64 } + member_count: 3 + members: + - *td3 + - *td10 + - *td11 + - &td13 + id: 12 + op: 28 + type_name: + struct_member_name: "ClothColors" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 16 } + member_count: 0 + members: + - &td14 + id: 13 + op: 28 + type_name: + struct_member_name: "Scales" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 16 } + member_count: 0 + members: + - &td15 + id: 23 + op: 21 + type_name: + struct_member_name: "EnableBitMask" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 14 + op: 28 + type_name: "AuxData" + struct_member_name: "AuxDatArray" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [10,], stride: 784 } + member_count: 4 + members: + - *td12 + - *td13 + - *td14 + - *td15 + - &td17 + id: 17 + op: 28 + type_name: "MaterialData" + struct_member_name: "Material" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 3, dims: [2,2,3,], stride: 7872 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td16 + - &td18 + id: 28 + op: 24 + type_name: + struct_member_name: "ModelMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 28 + op: 24 + type_name: + struct_member_name: "ProjectionMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 19 + op: 22 + type_name: + struct_member_name: "Time" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 20 + op: 23 + type_name: + struct_member_name: "Scale" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 18 + op: 28 + type_name: + struct_member_name: "UvOffsets" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [12,], stride: 16 } + member_count: 0 + members: + - &td23 + id: 21 + op: 21 + type_name: + struct_member_name: "EnableTarget" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 8 + op: 30 + type_name: "type.ConstantBuffer.Constants" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 7 + members: + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - &td25 + id: 27 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 27 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td27 + id: 19 + op: 22 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td28 + id: 35 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td29 + id: 35 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td30 + id: 10 + op: 30 + type_name: "type.gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td26 + - *td27 + - *td28 + - *td29 +all_block_variables: + - &bv0 + name: "Color" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Specular" + offset: 12 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "Diffuse" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "NormalAdjust" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "Front" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "Back" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "Top" + offset: 8 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "Bottom" + offset: 12 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "Left" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "Right" + offset: 20 + absolute_offset: 0 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "Strengths" + offset: 16 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 6 + members: + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + type_description: *td10 + - &bv11 + name: "Type" + offset: 48 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "ClothProperties" + offset: 0 + absolute_offset: 0 + size: 512 + padded_size: 512 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 64 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv3 + - *bv10 + - *bv11 + type_description: *td12 + - &bv13 + name: "ClothColors" + offset: 512 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "Scales" + offset: 640 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [8,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "EnableBitMask" + offset: 768 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "AuxDatArray" + offset: 32 + absolute_offset: 0 + size: 7840 + padded_size: 7840 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [10,], stride: 784 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv12 + - *bv13 + - *bv14 + - *bv15 + type_description: *td16 + - &bv17 + name: "Material" + offset: 0 + absolute_offset: 0 + size: 94464 + padded_size: 94464 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 3, dims: [2,2,3,], stride: 7872 } + flags: 0x00000001 # UNUSED + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv16 + type_description: *td17 + - &bv18 + name: "ModelMatrix" + offset: 94464 + absolute_offset: 94464 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "ProjectionMatrix" + offset: 94528 + absolute_offset: 94528 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "Time" + offset: 94592 + absolute_offset: 94592 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "Scale" + offset: 94596 + absolute_offset: 94596 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "UvOffsets" + offset: 94608 + absolute_offset: 94608 + size: 192 + padded_size: 192 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [12,], stride: 16 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "EnableTarget" + offset: 94800 + absolute_offset: 94800 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "MyConstants" + offset: 0 + absolute_offset: 0 + size: 94816 + padded_size: 94816 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 7 + members: + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + type_description: *td24 +all_descriptor_bindings: + - &db0 + spirv_id: 9 + name: "MyConstants" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv24 # "MyConstants" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td24 + word_offset: { binding: 425, set: 421 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: "in.var.POSITION" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td25 + word_offset: { location: 417 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td26 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td27 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td28 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td29 + word_offset: { location: 0 } + - &iv5 + spirv_id: 2 + name: "gl_PerVertexOut" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td30 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "MyConstants" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "MyConstants" + input_variable_count: 1, + input_variables: + - *iv0 # "in.var.POSITION" + output_variable_count: 1, + output_variables: + - *iv5 # "gl_PerVertexOut" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.hlsl new file mode 100644 index 0000000..d23ae3a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.hlsl @@ -0,0 +1,87 @@ +struct Nested5 { + float d00; + float d01; + float d02; + float d03; + float d04; + float d05; + float d06; + float d07; + float d08; + float d09; +}; + + +struct Nested4 { + float c00; + float c01; + float c02; + float c03; + float c04; + Nested5 nested5_00; + float c05; + float c06; + float c07; + float c08; + float c09; + Nested5 nested5_01; +}; + + +struct Nested3 { + float b00; + float b01; + float b02; + float b03; + float b04; + float b05; + float b06; + float b07; + float b08; + float b09; + Nested4 nested4_00; +}; + +struct Nested2 { + Nested3 nested3_00; + float a00; + float a01; + float a02; + float a03; + float a04; + float a05; + float a06; + float a07; + float a08; + float a09; + Nested4 nested4_00; +}; + +struct Nested1 { + Nested2 nested2_00; + float word00; + float word01; + float word02; + float word03; + float word04; + float word05; + float word06; + float word07; + float word08; + float word09; + Nested2 nested2_01; +}; + +struct Constants { + float var00; + float2 var01; + Nested1 nested1; + float Time; +}; + +ConstantBuffer MyConstants : register(b0); + +float4 main(float4 pos : POSITION) : SV_Position +{ + return float4(MyConstants.Time, 0, 0, 0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv new file mode 100644 index 0000000..69be7e5 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv.yaml new file mode 100644 index 0000000..1b9fcbd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/constantbuffer_nested_structs.spv.yaml @@ -0,0 +1,6952 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 12 + op: 22 + type_name: + struct_member_name: "var00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 13 + op: 23 + type_name: + struct_member_name: "var01" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 12 + op: 22 + type_name: + struct_member_name: "b00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 12 + op: 22 + type_name: + struct_member_name: "b01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 12 + op: 22 + type_name: + struct_member_name: "b02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 12 + op: 22 + type_name: + struct_member_name: "b03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 12 + op: 22 + type_name: + struct_member_name: "b04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 12 + op: 22 + type_name: + struct_member_name: "b05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 12 + op: 22 + type_name: + struct_member_name: "b06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 12 + op: 22 + type_name: + struct_member_name: "b07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 12 + op: 22 + type_name: + struct_member_name: "b08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 12 + op: 22 + type_name: + struct_member_name: "b09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 12 + op: 22 + type_name: + struct_member_name: "c00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 12 + op: 22 + type_name: + struct_member_name: "c01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 12 + op: 22 + type_name: + struct_member_name: "c02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 12 + op: 22 + type_name: + struct_member_name: "c03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 12 + op: 22 + type_name: + struct_member_name: "c04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td27 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - *td24 + - *td25 + - *td26 + - &td28 + id: 12 + op: 22 + type_name: + struct_member_name: "c05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td29 + id: 12 + op: 22 + type_name: + struct_member_name: "c06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td30 + id: 12 + op: 22 + type_name: + struct_member_name: "c07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td31 + id: 12 + op: 22 + type_name: + struct_member_name: "c08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td32 + id: 12 + op: 22 + type_name: + struct_member_name: "c09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td33 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td34 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td35 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td36 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td37 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td38 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td39 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td40 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td41 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td42 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td43 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_01" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td33 + - *td34 + - *td35 + - *td36 + - *td37 + - *td38 + - *td39 + - *td40 + - *td41 + - *td42 + - &td44 + id: 5 + op: 30 + type_name: "Nested4" + struct_member_name: "nested4_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td12 + - *td13 + - *td14 + - *td15 + - *td16 + - *td27 + - *td28 + - *td29 + - *td30 + - *td31 + - *td32 + - *td43 + - &td45 + id: 6 + op: 30 + type_name: "Nested3" + struct_member_name: "nested3_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 11 + members: + - *td2 + - *td3 + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - *td10 + - *td11 + - *td44 + - &td46 + id: 12 + op: 22 + type_name: + struct_member_name: "a00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td47 + id: 12 + op: 22 + type_name: + struct_member_name: "a01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td48 + id: 12 + op: 22 + type_name: + struct_member_name: "a02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td49 + id: 12 + op: 22 + type_name: + struct_member_name: "a03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td50 + id: 12 + op: 22 + type_name: + struct_member_name: "a04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td51 + id: 12 + op: 22 + type_name: + struct_member_name: "a05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td52 + id: 12 + op: 22 + type_name: + struct_member_name: "a06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td53 + id: 12 + op: 22 + type_name: + struct_member_name: "a07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td54 + id: 12 + op: 22 + type_name: + struct_member_name: "a08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td55 + id: 12 + op: 22 + type_name: + struct_member_name: "a09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td56 + id: 12 + op: 22 + type_name: + struct_member_name: "c00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td57 + id: 12 + op: 22 + type_name: + struct_member_name: "c01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td58 + id: 12 + op: 22 + type_name: + struct_member_name: "c02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td59 + id: 12 + op: 22 + type_name: + struct_member_name: "c03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td60 + id: 12 + op: 22 + type_name: + struct_member_name: "c04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td61 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td62 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td63 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td64 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td65 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td66 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td67 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td68 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td69 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td70 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td71 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td61 + - *td62 + - *td63 + - *td64 + - *td65 + - *td66 + - *td67 + - *td68 + - *td69 + - *td70 + - &td72 + id: 12 + op: 22 + type_name: + struct_member_name: "c05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td73 + id: 12 + op: 22 + type_name: + struct_member_name: "c06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td74 + id: 12 + op: 22 + type_name: + struct_member_name: "c07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td75 + id: 12 + op: 22 + type_name: + struct_member_name: "c08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td76 + id: 12 + op: 22 + type_name: + struct_member_name: "c09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td77 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td78 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td79 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td80 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td81 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td82 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td83 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td84 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td85 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td86 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td87 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_01" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td77 + - *td78 + - *td79 + - *td80 + - *td81 + - *td82 + - *td83 + - *td84 + - *td85 + - *td86 + - &td88 + id: 5 + op: 30 + type_name: "Nested4" + struct_member_name: "nested4_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td56 + - *td57 + - *td58 + - *td59 + - *td60 + - *td71 + - *td72 + - *td73 + - *td74 + - *td75 + - *td76 + - *td87 + - &td89 + id: 7 + op: 30 + type_name: "Nested2" + struct_member_name: "nested2_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td45 + - *td46 + - *td47 + - *td48 + - *td49 + - *td50 + - *td51 + - *td52 + - *td53 + - *td54 + - *td55 + - *td88 + - &td90 + id: 12 + op: 22 + type_name: + struct_member_name: "word00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td91 + id: 12 + op: 22 + type_name: + struct_member_name: "word01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td92 + id: 12 + op: 22 + type_name: + struct_member_name: "word02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td93 + id: 12 + op: 22 + type_name: + struct_member_name: "word03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td94 + id: 12 + op: 22 + type_name: + struct_member_name: "word04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td95 + id: 12 + op: 22 + type_name: + struct_member_name: "word05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td96 + id: 12 + op: 22 + type_name: + struct_member_name: "word06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td97 + id: 12 + op: 22 + type_name: + struct_member_name: "word07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td98 + id: 12 + op: 22 + type_name: + struct_member_name: "word08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td99 + id: 12 + op: 22 + type_name: + struct_member_name: "word09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td100 + id: 12 + op: 22 + type_name: + struct_member_name: "b00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td101 + id: 12 + op: 22 + type_name: + struct_member_name: "b01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td102 + id: 12 + op: 22 + type_name: + struct_member_name: "b02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td103 + id: 12 + op: 22 + type_name: + struct_member_name: "b03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td104 + id: 12 + op: 22 + type_name: + struct_member_name: "b04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td105 + id: 12 + op: 22 + type_name: + struct_member_name: "b05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td106 + id: 12 + op: 22 + type_name: + struct_member_name: "b06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td107 + id: 12 + op: 22 + type_name: + struct_member_name: "b07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td108 + id: 12 + op: 22 + type_name: + struct_member_name: "b08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td109 + id: 12 + op: 22 + type_name: + struct_member_name: "b09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td110 + id: 12 + op: 22 + type_name: + struct_member_name: "c00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td111 + id: 12 + op: 22 + type_name: + struct_member_name: "c01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td112 + id: 12 + op: 22 + type_name: + struct_member_name: "c02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td113 + id: 12 + op: 22 + type_name: + struct_member_name: "c03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td114 + id: 12 + op: 22 + type_name: + struct_member_name: "c04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td115 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td116 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td117 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td118 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td119 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td120 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td121 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td122 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td123 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td124 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td125 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td115 + - *td116 + - *td117 + - *td118 + - *td119 + - *td120 + - *td121 + - *td122 + - *td123 + - *td124 + - &td126 + id: 12 + op: 22 + type_name: + struct_member_name: "c05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td127 + id: 12 + op: 22 + type_name: + struct_member_name: "c06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td128 + id: 12 + op: 22 + type_name: + struct_member_name: "c07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td129 + id: 12 + op: 22 + type_name: + struct_member_name: "c08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td130 + id: 12 + op: 22 + type_name: + struct_member_name: "c09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td131 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td132 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td133 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td134 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td135 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td136 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td137 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td138 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td139 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td140 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td141 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_01" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td131 + - *td132 + - *td133 + - *td134 + - *td135 + - *td136 + - *td137 + - *td138 + - *td139 + - *td140 + - &td142 + id: 5 + op: 30 + type_name: "Nested4" + struct_member_name: "nested4_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td110 + - *td111 + - *td112 + - *td113 + - *td114 + - *td125 + - *td126 + - *td127 + - *td128 + - *td129 + - *td130 + - *td141 + - &td143 + id: 6 + op: 30 + type_name: "Nested3" + struct_member_name: "nested3_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 11 + members: + - *td100 + - *td101 + - *td102 + - *td103 + - *td104 + - *td105 + - *td106 + - *td107 + - *td108 + - *td109 + - *td142 + - &td144 + id: 12 + op: 22 + type_name: + struct_member_name: "a00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td145 + id: 12 + op: 22 + type_name: + struct_member_name: "a01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td146 + id: 12 + op: 22 + type_name: + struct_member_name: "a02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td147 + id: 12 + op: 22 + type_name: + struct_member_name: "a03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td148 + id: 12 + op: 22 + type_name: + struct_member_name: "a04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td149 + id: 12 + op: 22 + type_name: + struct_member_name: "a05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td150 + id: 12 + op: 22 + type_name: + struct_member_name: "a06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td151 + id: 12 + op: 22 + type_name: + struct_member_name: "a07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td152 + id: 12 + op: 22 + type_name: + struct_member_name: "a08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td153 + id: 12 + op: 22 + type_name: + struct_member_name: "a09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td154 + id: 12 + op: 22 + type_name: + struct_member_name: "c00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td155 + id: 12 + op: 22 + type_name: + struct_member_name: "c01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td156 + id: 12 + op: 22 + type_name: + struct_member_name: "c02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td157 + id: 12 + op: 22 + type_name: + struct_member_name: "c03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td158 + id: 12 + op: 22 + type_name: + struct_member_name: "c04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td159 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td160 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td161 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td162 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td163 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td164 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td165 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td166 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td167 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td168 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td169 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td159 + - *td160 + - *td161 + - *td162 + - *td163 + - *td164 + - *td165 + - *td166 + - *td167 + - *td168 + - &td170 + id: 12 + op: 22 + type_name: + struct_member_name: "c05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td171 + id: 12 + op: 22 + type_name: + struct_member_name: "c06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td172 + id: 12 + op: 22 + type_name: + struct_member_name: "c07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td173 + id: 12 + op: 22 + type_name: + struct_member_name: "c08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td174 + id: 12 + op: 22 + type_name: + struct_member_name: "c09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td175 + id: 12 + op: 22 + type_name: + struct_member_name: "d00" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td176 + id: 12 + op: 22 + type_name: + struct_member_name: "d01" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td177 + id: 12 + op: 22 + type_name: + struct_member_name: "d02" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td178 + id: 12 + op: 22 + type_name: + struct_member_name: "d03" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td179 + id: 12 + op: 22 + type_name: + struct_member_name: "d04" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td180 + id: 12 + op: 22 + type_name: + struct_member_name: "d05" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td181 + id: 12 + op: 22 + type_name: + struct_member_name: "d06" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td182 + id: 12 + op: 22 + type_name: + struct_member_name: "d07" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td183 + id: 12 + op: 22 + type_name: + struct_member_name: "d08" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td184 + id: 12 + op: 22 + type_name: + struct_member_name: "d09" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td185 + id: 4 + op: 30 + type_name: "Nested5" + struct_member_name: "nested5_01" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 10 + members: + - *td175 + - *td176 + - *td177 + - *td178 + - *td179 + - *td180 + - *td181 + - *td182 + - *td183 + - *td184 + - &td186 + id: 5 + op: 30 + type_name: "Nested4" + struct_member_name: "nested4_00" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td154 + - *td155 + - *td156 + - *td157 + - *td158 + - *td169 + - *td170 + - *td171 + - *td172 + - *td173 + - *td174 + - *td185 + - &td187 + id: 7 + op: 30 + type_name: "Nested2" + struct_member_name: "nested2_01" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td143 + - *td144 + - *td145 + - *td146 + - *td147 + - *td148 + - *td149 + - *td150 + - *td151 + - *td152 + - *td153 + - *td186 + - &td188 + id: 8 + op: 30 + type_name: "Nested1" + struct_member_name: "nested1" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 12 + members: + - *td89 + - *td90 + - *td91 + - *td92 + - *td93 + - *td94 + - *td95 + - *td96 + - *td97 + - *td98 + - *td99 + - *td187 + - &td189 + id: 12 + op: 22 + type_name: + struct_member_name: "Time" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td190 + id: 9 + op: 30 + type_name: "type.ConstantBuffer.Constants" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td0 + - *td1 + - *td188 + - *td189 + - &td191 + id: 17 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td192 + id: 17 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td193 + id: 12 + op: 22 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td194 + id: 20 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td195 + id: 20 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td196 + id: 11 + op: 30 + type_name: "type.gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td192 + - *td193 + - *td194 + - *td195 +all_block_variables: + - &bv0 + name: "var00" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "var01" + offset: 4 + absolute_offset: 4 + size: 8 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "b00" + offset: 0 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "b01" + offset: 4 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "b02" + offset: 8 + absolute_offset: 24 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "b03" + offset: 12 + absolute_offset: 28 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "b04" + offset: 16 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "b05" + offset: 20 + absolute_offset: 36 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "b06" + offset: 24 + absolute_offset: 40 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "b07" + offset: 28 + absolute_offset: 44 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "b08" + offset: 32 + absolute_offset: 48 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "b09" + offset: 36 + absolute_offset: 52 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "c00" + offset: 0 + absolute_offset: 64 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "c01" + offset: 4 + absolute_offset: 68 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "c02" + offset: 8 + absolute_offset: 72 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "c03" + offset: 12 + absolute_offset: 76 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "c04" + offset: 16 + absolute_offset: 80 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "d00" + offset: 0 + absolute_offset: 96 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td17 + - &bv18 + name: "d01" + offset: 4 + absolute_offset: 100 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "d02" + offset: 8 + absolute_offset: 104 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "d03" + offset: 12 + absolute_offset: 108 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "d04" + offset: 16 + absolute_offset: 112 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "d05" + offset: 20 + absolute_offset: 116 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "d06" + offset: 24 + absolute_offset: 120 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "d07" + offset: 28 + absolute_offset: 124 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "d08" + offset: 32 + absolute_offset: 128 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "d09" + offset: 36 + absolute_offset: 132 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td26 + - &bv27 + name: "nested5_00" + offset: 32 + absolute_offset: 96 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + - *bv24 + - *bv25 + - *bv26 + type_description: *td27 + - &bv28 + name: "c05" + offset: 80 + absolute_offset: 144 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv29 + name: "c06" + offset: 84 + absolute_offset: 148 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td29 + - &bv30 + name: "c07" + offset: 88 + absolute_offset: 152 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td30 + - &bv31 + name: "c08" + offset: 92 + absolute_offset: 156 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td31 + - &bv32 + name: "c09" + offset: 96 + absolute_offset: 160 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td32 + - &bv33 + name: "d00" + offset: 0 + absolute_offset: 176 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td33 + - &bv34 + name: "d01" + offset: 4 + absolute_offset: 180 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td34 + - &bv35 + name: "d02" + offset: 8 + absolute_offset: 184 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td35 + - &bv36 + name: "d03" + offset: 12 + absolute_offset: 188 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td36 + - &bv37 + name: "d04" + offset: 16 + absolute_offset: 192 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td37 + - &bv38 + name: "d05" + offset: 20 + absolute_offset: 196 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td38 + - &bv39 + name: "d06" + offset: 24 + absolute_offset: 200 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td39 + - &bv40 + name: "d07" + offset: 28 + absolute_offset: 204 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td40 + - &bv41 + name: "d08" + offset: 32 + absolute_offset: 208 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td41 + - &bv42 + name: "d09" + offset: 36 + absolute_offset: 212 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td42 + - &bv43 + name: "nested5_01" + offset: 112 + absolute_offset: 176 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv33 + - *bv34 + - *bv35 + - *bv36 + - *bv37 + - *bv38 + - *bv39 + - *bv40 + - *bv41 + - *bv42 + type_description: *td43 + - &bv44 + name: "nested4_00" + offset: 48 + absolute_offset: 64 + size: 160 + padded_size: 160 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv12 + - *bv13 + - *bv14 + - *bv15 + - *bv16 + - *bv27 + - *bv28 + - *bv29 + - *bv30 + - *bv31 + - *bv32 + - *bv43 + type_description: *td44 + - &bv45 + name: "nested3_00" + offset: 0 + absolute_offset: 16 + size: 208 + padded_size: 208 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 11 + members: + - *bv2 + - *bv3 + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + - *bv10 + - *bv11 + - *bv44 + type_description: *td45 + - &bv46 + name: "a00" + offset: 208 + absolute_offset: 224 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td46 + - &bv47 + name: "a01" + offset: 212 + absolute_offset: 228 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td47 + - &bv48 + name: "a02" + offset: 216 + absolute_offset: 232 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td48 + - &bv49 + name: "a03" + offset: 220 + absolute_offset: 236 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td49 + - &bv50 + name: "a04" + offset: 224 + absolute_offset: 240 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td50 + - &bv51 + name: "a05" + offset: 228 + absolute_offset: 244 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td51 + - &bv52 + name: "a06" + offset: 232 + absolute_offset: 248 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td52 + - &bv53 + name: "a07" + offset: 236 + absolute_offset: 252 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td53 + - &bv54 + name: "a08" + offset: 240 + absolute_offset: 256 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td54 + - &bv55 + name: "a09" + offset: 244 + absolute_offset: 260 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td55 + - &bv56 + name: "c00" + offset: 0 + absolute_offset: 272 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td56 + - &bv57 + name: "c01" + offset: 4 + absolute_offset: 276 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td57 + - &bv58 + name: "c02" + offset: 8 + absolute_offset: 280 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td58 + - &bv59 + name: "c03" + offset: 12 + absolute_offset: 284 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td59 + - &bv60 + name: "c04" + offset: 16 + absolute_offset: 288 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td60 + - &bv61 + name: "d00" + offset: 0 + absolute_offset: 304 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td61 + - &bv62 + name: "d01" + offset: 4 + absolute_offset: 308 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td62 + - &bv63 + name: "d02" + offset: 8 + absolute_offset: 312 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td63 + - &bv64 + name: "d03" + offset: 12 + absolute_offset: 316 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td64 + - &bv65 + name: "d04" + offset: 16 + absolute_offset: 320 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td65 + - &bv66 + name: "d05" + offset: 20 + absolute_offset: 324 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td66 + - &bv67 + name: "d06" + offset: 24 + absolute_offset: 328 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td67 + - &bv68 + name: "d07" + offset: 28 + absolute_offset: 332 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td68 + - &bv69 + name: "d08" + offset: 32 + absolute_offset: 336 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td69 + - &bv70 + name: "d09" + offset: 36 + absolute_offset: 340 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td70 + - &bv71 + name: "nested5_00" + offset: 32 + absolute_offset: 304 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv61 + - *bv62 + - *bv63 + - *bv64 + - *bv65 + - *bv66 + - *bv67 + - *bv68 + - *bv69 + - *bv70 + type_description: *td71 + - &bv72 + name: "c05" + offset: 80 + absolute_offset: 352 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td72 + - &bv73 + name: "c06" + offset: 84 + absolute_offset: 356 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td73 + - &bv74 + name: "c07" + offset: 88 + absolute_offset: 360 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td74 + - &bv75 + name: "c08" + offset: 92 + absolute_offset: 364 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td75 + - &bv76 + name: "c09" + offset: 96 + absolute_offset: 368 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td76 + - &bv77 + name: "d00" + offset: 0 + absolute_offset: 384 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td77 + - &bv78 + name: "d01" + offset: 4 + absolute_offset: 388 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td78 + - &bv79 + name: "d02" + offset: 8 + absolute_offset: 392 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td79 + - &bv80 + name: "d03" + offset: 12 + absolute_offset: 396 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td80 + - &bv81 + name: "d04" + offset: 16 + absolute_offset: 400 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td81 + - &bv82 + name: "d05" + offset: 20 + absolute_offset: 404 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td82 + - &bv83 + name: "d06" + offset: 24 + absolute_offset: 408 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td83 + - &bv84 + name: "d07" + offset: 28 + absolute_offset: 412 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td84 + - &bv85 + name: "d08" + offset: 32 + absolute_offset: 416 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td85 + - &bv86 + name: "d09" + offset: 36 + absolute_offset: 420 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td86 + - &bv87 + name: "nested5_01" + offset: 112 + absolute_offset: 384 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv77 + - *bv78 + - *bv79 + - *bv80 + - *bv81 + - *bv82 + - *bv83 + - *bv84 + - *bv85 + - *bv86 + type_description: *td87 + - &bv88 + name: "nested4_00" + offset: 256 + absolute_offset: 272 + size: 160 + padded_size: 160 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv56 + - *bv57 + - *bv58 + - *bv59 + - *bv60 + - *bv71 + - *bv72 + - *bv73 + - *bv74 + - *bv75 + - *bv76 + - *bv87 + type_description: *td88 + - &bv89 + name: "nested2_00" + offset: 0 + absolute_offset: 16 + size: 416 + padded_size: 416 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv45 + - *bv46 + - *bv47 + - *bv48 + - *bv49 + - *bv50 + - *bv51 + - *bv52 + - *bv53 + - *bv54 + - *bv55 + - *bv88 + type_description: *td89 + - &bv90 + name: "word00" + offset: 416 + absolute_offset: 432 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td90 + - &bv91 + name: "word01" + offset: 420 + absolute_offset: 436 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td91 + - &bv92 + name: "word02" + offset: 424 + absolute_offset: 440 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td92 + - &bv93 + name: "word03" + offset: 428 + absolute_offset: 444 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td93 + - &bv94 + name: "word04" + offset: 432 + absolute_offset: 448 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td94 + - &bv95 + name: "word05" + offset: 436 + absolute_offset: 452 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td95 + - &bv96 + name: "word06" + offset: 440 + absolute_offset: 456 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td96 + - &bv97 + name: "word07" + offset: 444 + absolute_offset: 460 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td97 + - &bv98 + name: "word08" + offset: 448 + absolute_offset: 464 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td98 + - &bv99 + name: "word09" + offset: 452 + absolute_offset: 468 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td99 + - &bv100 + name: "b00" + offset: 0 + absolute_offset: 480 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td100 + - &bv101 + name: "b01" + offset: 4 + absolute_offset: 484 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td101 + - &bv102 + name: "b02" + offset: 8 + absolute_offset: 488 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td102 + - &bv103 + name: "b03" + offset: 12 + absolute_offset: 492 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td103 + - &bv104 + name: "b04" + offset: 16 + absolute_offset: 496 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td104 + - &bv105 + name: "b05" + offset: 20 + absolute_offset: 500 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td105 + - &bv106 + name: "b06" + offset: 24 + absolute_offset: 504 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td106 + - &bv107 + name: "b07" + offset: 28 + absolute_offset: 508 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td107 + - &bv108 + name: "b08" + offset: 32 + absolute_offset: 512 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td108 + - &bv109 + name: "b09" + offset: 36 + absolute_offset: 516 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td109 + - &bv110 + name: "c00" + offset: 0 + absolute_offset: 528 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td110 + - &bv111 + name: "c01" + offset: 4 + absolute_offset: 532 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td111 + - &bv112 + name: "c02" + offset: 8 + absolute_offset: 536 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td112 + - &bv113 + name: "c03" + offset: 12 + absolute_offset: 540 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td113 + - &bv114 + name: "c04" + offset: 16 + absolute_offset: 544 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td114 + - &bv115 + name: "d00" + offset: 0 + absolute_offset: 560 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td115 + - &bv116 + name: "d01" + offset: 4 + absolute_offset: 564 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td116 + - &bv117 + name: "d02" + offset: 8 + absolute_offset: 568 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td117 + - &bv118 + name: "d03" + offset: 12 + absolute_offset: 572 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td118 + - &bv119 + name: "d04" + offset: 16 + absolute_offset: 576 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td119 + - &bv120 + name: "d05" + offset: 20 + absolute_offset: 580 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td120 + - &bv121 + name: "d06" + offset: 24 + absolute_offset: 584 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td121 + - &bv122 + name: "d07" + offset: 28 + absolute_offset: 588 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td122 + - &bv123 + name: "d08" + offset: 32 + absolute_offset: 592 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td123 + - &bv124 + name: "d09" + offset: 36 + absolute_offset: 596 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td124 + - &bv125 + name: "nested5_00" + offset: 32 + absolute_offset: 560 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv115 + - *bv116 + - *bv117 + - *bv118 + - *bv119 + - *bv120 + - *bv121 + - *bv122 + - *bv123 + - *bv124 + type_description: *td125 + - &bv126 + name: "c05" + offset: 80 + absolute_offset: 608 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td126 + - &bv127 + name: "c06" + offset: 84 + absolute_offset: 612 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td127 + - &bv128 + name: "c07" + offset: 88 + absolute_offset: 616 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td128 + - &bv129 + name: "c08" + offset: 92 + absolute_offset: 620 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td129 + - &bv130 + name: "c09" + offset: 96 + absolute_offset: 624 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td130 + - &bv131 + name: "d00" + offset: 0 + absolute_offset: 640 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td131 + - &bv132 + name: "d01" + offset: 4 + absolute_offset: 644 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td132 + - &bv133 + name: "d02" + offset: 8 + absolute_offset: 648 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td133 + - &bv134 + name: "d03" + offset: 12 + absolute_offset: 652 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td134 + - &bv135 + name: "d04" + offset: 16 + absolute_offset: 656 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td135 + - &bv136 + name: "d05" + offset: 20 + absolute_offset: 660 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td136 + - &bv137 + name: "d06" + offset: 24 + absolute_offset: 664 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td137 + - &bv138 + name: "d07" + offset: 28 + absolute_offset: 668 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td138 + - &bv139 + name: "d08" + offset: 32 + absolute_offset: 672 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td139 + - &bv140 + name: "d09" + offset: 36 + absolute_offset: 676 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td140 + - &bv141 + name: "nested5_01" + offset: 112 + absolute_offset: 640 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv131 + - *bv132 + - *bv133 + - *bv134 + - *bv135 + - *bv136 + - *bv137 + - *bv138 + - *bv139 + - *bv140 + type_description: *td141 + - &bv142 + name: "nested4_00" + offset: 48 + absolute_offset: 528 + size: 160 + padded_size: 160 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv110 + - *bv111 + - *bv112 + - *bv113 + - *bv114 + - *bv125 + - *bv126 + - *bv127 + - *bv128 + - *bv129 + - *bv130 + - *bv141 + type_description: *td142 + - &bv143 + name: "nested3_00" + offset: 0 + absolute_offset: 480 + size: 208 + padded_size: 208 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 11 + members: + - *bv100 + - *bv101 + - *bv102 + - *bv103 + - *bv104 + - *bv105 + - *bv106 + - *bv107 + - *bv108 + - *bv109 + - *bv142 + type_description: *td143 + - &bv144 + name: "a00" + offset: 208 + absolute_offset: 688 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td144 + - &bv145 + name: "a01" + offset: 212 + absolute_offset: 692 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td145 + - &bv146 + name: "a02" + offset: 216 + absolute_offset: 696 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td146 + - &bv147 + name: "a03" + offset: 220 + absolute_offset: 700 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td147 + - &bv148 + name: "a04" + offset: 224 + absolute_offset: 704 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td148 + - &bv149 + name: "a05" + offset: 228 + absolute_offset: 708 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td149 + - &bv150 + name: "a06" + offset: 232 + absolute_offset: 712 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td150 + - &bv151 + name: "a07" + offset: 236 + absolute_offset: 716 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td151 + - &bv152 + name: "a08" + offset: 240 + absolute_offset: 720 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td152 + - &bv153 + name: "a09" + offset: 244 + absolute_offset: 724 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td153 + - &bv154 + name: "c00" + offset: 0 + absolute_offset: 736 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td154 + - &bv155 + name: "c01" + offset: 4 + absolute_offset: 740 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td155 + - &bv156 + name: "c02" + offset: 8 + absolute_offset: 744 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td156 + - &bv157 + name: "c03" + offset: 12 + absolute_offset: 748 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td157 + - &bv158 + name: "c04" + offset: 16 + absolute_offset: 752 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td158 + - &bv159 + name: "d00" + offset: 0 + absolute_offset: 768 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td159 + - &bv160 + name: "d01" + offset: 4 + absolute_offset: 772 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td160 + - &bv161 + name: "d02" + offset: 8 + absolute_offset: 776 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td161 + - &bv162 + name: "d03" + offset: 12 + absolute_offset: 780 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td162 + - &bv163 + name: "d04" + offset: 16 + absolute_offset: 784 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td163 + - &bv164 + name: "d05" + offset: 20 + absolute_offset: 788 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td164 + - &bv165 + name: "d06" + offset: 24 + absolute_offset: 792 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td165 + - &bv166 + name: "d07" + offset: 28 + absolute_offset: 796 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td166 + - &bv167 + name: "d08" + offset: 32 + absolute_offset: 800 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td167 + - &bv168 + name: "d09" + offset: 36 + absolute_offset: 804 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td168 + - &bv169 + name: "nested5_00" + offset: 32 + absolute_offset: 768 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv159 + - *bv160 + - *bv161 + - *bv162 + - *bv163 + - *bv164 + - *bv165 + - *bv166 + - *bv167 + - *bv168 + type_description: *td169 + - &bv170 + name: "c05" + offset: 80 + absolute_offset: 816 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td170 + - &bv171 + name: "c06" + offset: 84 + absolute_offset: 820 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td171 + - &bv172 + name: "c07" + offset: 88 + absolute_offset: 824 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td172 + - &bv173 + name: "c08" + offset: 92 + absolute_offset: 828 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td173 + - &bv174 + name: "c09" + offset: 96 + absolute_offset: 832 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td174 + - &bv175 + name: "d00" + offset: 0 + absolute_offset: 848 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td175 + - &bv176 + name: "d01" + offset: 4 + absolute_offset: 852 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td176 + - &bv177 + name: "d02" + offset: 8 + absolute_offset: 856 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td177 + - &bv178 + name: "d03" + offset: 12 + absolute_offset: 860 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td178 + - &bv179 + name: "d04" + offset: 16 + absolute_offset: 864 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td179 + - &bv180 + name: "d05" + offset: 20 + absolute_offset: 868 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td180 + - &bv181 + name: "d06" + offset: 24 + absolute_offset: 872 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td181 + - &bv182 + name: "d07" + offset: 28 + absolute_offset: 876 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td182 + - &bv183 + name: "d08" + offset: 32 + absolute_offset: 880 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td183 + - &bv184 + name: "d09" + offset: 36 + absolute_offset: 884 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td184 + - &bv185 + name: "nested5_01" + offset: 112 + absolute_offset: 848 + size: 48 + padded_size: 48 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 10 + members: + - *bv175 + - *bv176 + - *bv177 + - *bv178 + - *bv179 + - *bv180 + - *bv181 + - *bv182 + - *bv183 + - *bv184 + type_description: *td185 + - &bv186 + name: "nested4_00" + offset: 256 + absolute_offset: 736 + size: 160 + padded_size: 160 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv154 + - *bv155 + - *bv156 + - *bv157 + - *bv158 + - *bv169 + - *bv170 + - *bv171 + - *bv172 + - *bv173 + - *bv174 + - *bv185 + type_description: *td186 + - &bv187 + name: "nested2_01" + offset: 464 + absolute_offset: 480 + size: 416 + padded_size: 416 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv143 + - *bv144 + - *bv145 + - *bv146 + - *bv147 + - *bv148 + - *bv149 + - *bv150 + - *bv151 + - *bv152 + - *bv153 + - *bv186 + type_description: *td187 + - &bv188 + name: "nested1" + offset: 16 + absolute_offset: 16 + size: 880 + padded_size: 880 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 12 + members: + - *bv89 + - *bv90 + - *bv91 + - *bv92 + - *bv93 + - *bv94 + - *bv95 + - *bv96 + - *bv97 + - *bv98 + - *bv99 + - *bv187 + type_description: *td188 + - &bv189 + name: "Time" + offset: 896 + absolute_offset: 896 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td189 + - &bv190 + name: "MyConstants" + offset: 0 + absolute_offset: 0 + size: 912 + padded_size: 912 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv188 + - *bv189 + type_description: *td190 +all_descriptor_bindings: + - &db0 + spirv_id: 10 + name: "MyConstants" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv190 # "MyConstants" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td190 + word_offset: { binding: 692, set: 688 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: "in.var.POSITION" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td191 + word_offset: { location: 684 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td192 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td193 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td194 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td195 + word_offset: { location: 0 } + - &iv5 + spirv_id: 2 + name: "gl_PerVertexOut" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td196 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "MyConstants" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "MyConstants" + input_variable_count: 1, + input_variables: + - *iv0 # "in.var.POSITION" + output_variable_count: 1, + output_variables: + - *iv5 # "gl_PerVertexOut" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.hlsl new file mode 100644 index 0000000..ca94c1a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.hlsl @@ -0,0 +1,22 @@ +/* +Build with DXC using -fspv-reflect to enable counter buffers + + dxc -spirv -fspv-reflect -T ps_5_0 -Fo counter_buffers.spv counter_buffers.hlsl + +*/ + +struct Data { + float4 f4; + int i; +}; + +ConsumeStructuredBuffer MyBufferIn : register(u3, space2); +AppendStructuredBuffer MyBufferOut : register(u4, space2); + +float4 main(float4 PosCS : SV_Position) : SV_TARGET0 +{ + Data val = MyBufferIn.Consume(); + MyBufferOut.Append(val); + + return val.f4; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv new file mode 100644 index 0000000..5892851 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv.yaml new file mode 100644 index 0000000..b27ec44 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/counter_buffers.spv.yaml @@ -0,0 +1,538 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 10 + op: 30 + type_name: "type.ACSBuffer.counter" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 3 + op: 23 + type_name: + struct_member_name: "f4" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 4 + op: 21 + type_name: + struct_member_name: "i" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 6 + op: 29 + type_name: "Data" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 32 } + member_count: 2 + members: + - *td2 + - *td3 + - &td5 + id: 7 + op: 30 + type_name: "type.ConsumeStructuredBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 3 + op: 23 + type_name: + struct_member_name: "f4" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 4 + op: 21 + type_name: + struct_member_name: "i" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 6 + op: 29 + type_name: "Data" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 32 } + member_count: 2 + members: + - *td6 + - *td7 + - &td9 + id: 13 + op: 30 + type_name: "type.AppendStructuredBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td8 + - &td10 + id: 3 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "counter.var.MyBufferIn" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv3 + name: "counter.var.MyBufferOut" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td1 + - &bv4 + name: "f4" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv5 + name: "i" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv6 + name: + offset: 0 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv4 + - *bv5 + type_description: *td4 + - &bv7 + name: "MyBufferIn" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv6 + type_description: *td5 + - &bv8 + name: "f4" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv9 + name: "i" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv10 + name: + offset: 0 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv8 + - *bv9 + type_description: *td8 + - &bv11 + name: "MyBufferOut" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv10 + type_description: *td9 +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "counter.var.MyBufferIn" + binding: 0 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "counter.var.MyBufferIn" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 333, set: 329 } + - &db1 + spirv_id: 16 + name: "counter.var.MyBufferOut" + binding: 1 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "counter.var.MyBufferOut" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 341, set: 337 } + - &db2 + spirv_id: 9 + name: "MyBufferIn" + binding: 3 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # "MyBufferIn" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 12 + uav_counter_binding: *db0 # "counter.var.MyBufferIn" + type_description: *td5 + word_offset: { binding: 317, set: 313 } + - &db3 + spirv_id: 15 + name: "MyBufferOut" + binding: 4 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "MyBufferOut" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 16 + uav_counter_binding: *db1 # "counter.var.MyBufferOut" + type_description: *td9 + word_offset: { binding: 325, set: 321 } +all_interface_variables: + - &iv0 + spirv_id: 25 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_Position" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td10 + word_offset: { location: 0 } + - &iv1 + spirv_id: 29 + name: "out.var.SV_TARGET0" + location: 0 + storage_class: 3 # Output + semantic: "SV_TARGET0" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td10 + word_offset: { location: 309 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 20 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 4 + descriptor_bindings: + - *db0 # "counter.var.MyBufferIn" + - *db1 # "counter.var.MyBufferOut" + - *db2 # "MyBufferIn" + - *db3 # "MyBufferOut" + descriptor_set_count: 1 + descriptor_sets: + - set: 2 + binding_count: 4 + bindings: + - *db0 # "counter.var.MyBufferIn" + - *db1 # "counter.var.MyBufferOut" + - *db2 # "MyBufferIn" + - *db3 # "MyBufferOut" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 1, + output_variables: + - *iv1 # "out.var.SV_TARGET0" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/localsize.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.hlsl new file mode 100644 index 0000000..3cb9325 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.hlsl @@ -0,0 +1,5 @@ + +[numthreads(16, 24, 4)] +void csmain() +{ +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv new file mode 100644 index 0000000..bb7c6bd Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv.yaml new file mode 100644 index 0000000..e012df0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/localsize.spv.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "csmain" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.hlsl new file mode 100644 index 0000000..aac2ef3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.hlsl @@ -0,0 +1,64 @@ +/* +Build with DXC using -O0 to preserve unused types: + + dxc -spirv -O0 -T ps_5_0 -Fo matrix_major_order_hlsl.spv matrix_major_order_hlsl.hlsl + +*/ + + +// +// NOTE: 1xN and Nx1 matrices are aliased to floatN so they're not included. +// + +// ----------------------------------------------------------------------------- +// Matrices without row / column major decoration +// ----------------------------------------------------------------------------- + +float2x2 mat_2x2; +float2x3 mat_2x3; +float2x4 mat_2x4; + +float3x2 mat_3x2; +float3x3 mat_3x3; +float3x4 mat_3x4; + +float4x2 mat_4x2; +float4x3 mat_4x3; +float4x4 mat_4x4; + +// ----------------------------------------------------------------------------- +// Matrices with row major decoration +// ----------------------------------------------------------------------------- + +row_major float2x2 row_major_my_mat_2x2; +row_major float2x3 row_major_my_mat_2x3; +row_major float2x4 row_major_my_mat_2x4; + +row_major float3x2 row_major_my_mat_3x2; +row_major float3x3 row_major_my_mat_3x3; +row_major float3x4 row_major_my_mat_3x4; + +row_major float4x2 row_major_my_mat_4x2; +row_major float4x3 row_major_my_mat_4x3; +row_major float4x4 row_major_my_mat_4x4; + +// ----------------------------------------------------------------------------- +// Matrices with column major decoration +// ----------------------------------------------------------------------------- + +column_major float2x2 column_major_my_mat_2x2; +column_major float2x3 column_major_my_mat_2x3; +column_major float2x4 column_major_my_mat_2x4; + +column_major float3x2 column_major_my_mat_3x2; +column_major float3x3 column_major_my_mat_3x3; +column_major float3x4 column_major_my_mat_3x4; + +column_major float4x2 column_major_my_mat_4x2; +column_major float4x3 column_major_my_mat_4x3; +column_major float4x4 column_major_my_mat_4x4; + +float4 main(float4 pos : SV_POSITION) : SV_TARGET +{ + return pos; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv new file mode 100644 index 0000000..43e6104 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv.yaml new file mode 100644 index 0000000..7062729 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/matrix_major_order_hlsl.spv.yaml @@ -0,0 +1,1082 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 24 + type_name: + struct_member_name: "mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 10 + op: 24 + type_name: + struct_member_name: "mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 12 + op: 24 + type_name: + struct_member_name: "mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 14 + op: 24 + type_name: + struct_member_name: "mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 15 + op: 24 + type_name: + struct_member_name: "mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 16 + op: 24 + type_name: + struct_member_name: "mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 17 + op: 24 + type_name: + struct_member_name: "mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 18 + op: 24 + type_name: + struct_member_name: "mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 19 + op: 24 + type_name: + struct_member_name: "mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 7 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 10 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 12 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 14 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 15 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 16 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 17 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 18 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 19 + op: 24 + type_name: + struct_member_name: "row_major_my_mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 7 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 10 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 12 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_2x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 14 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 15 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 16 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_3x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 17 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x2" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 18 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x3" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 19 + op: 24 + type_name: + struct_member_name: "column_major_my_mat_4x4" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td27 + id: 6 + op: 30 + type_name: "type.$Globals" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 27 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 + - *td5 + - *td6 + - *td7 + - *td8 + - *td9 + - *td10 + - *td11 + - *td12 + - *td13 + - *td14 + - *td15 + - *td16 + - *td17 + - *td18 + - *td19 + - *td20 + - *td21 + - *td22 + - *td23 + - *td24 + - *td25 + - *td26 + - &td28 + id: 13 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "mat_2x2" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "mat_2x3" + offset: 32 + absolute_offset: 32 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "mat_2x4" + offset: 80 + absolute_offset: 80 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "mat_3x2" + offset: 144 + absolute_offset: 144 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "mat_3x3" + offset: 176 + absolute_offset: 176 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "mat_3x4" + offset: 224 + absolute_offset: 224 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "mat_4x2" + offset: 288 + absolute_offset: 288 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "mat_4x3" + offset: 320 + absolute_offset: 320 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "mat_4x4" + offset: 368 + absolute_offset: 368 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "row_major_my_mat_2x2" + offset: 432 + absolute_offset: 432 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "row_major_my_mat_2x3" + offset: 464 + absolute_offset: 464 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "row_major_my_mat_2x4" + offset: 496 + absolute_offset: 496 + size: 32 + padded_size: 32 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "row_major_my_mat_3x2" + offset: 528 + absolute_offset: 528 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "row_major_my_mat_3x3" + offset: 576 + absolute_offset: 576 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "row_major_my_mat_3x4" + offset: 624 + absolute_offset: 624 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td14 + - &bv15 + name: "row_major_my_mat_4x2" + offset: 672 + absolute_offset: 672 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "row_major_my_mat_4x3" + offset: 736 + absolute_offset: 736 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "row_major_my_mat_4x4" + offset: 800 + absolute_offset: 800 + size: 64 + padded_size: 64 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td17 + - &bv18 + name: "column_major_my_mat_2x2" + offset: 864 + absolute_offset: 864 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 2, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "column_major_my_mat_2x3" + offset: 896 + absolute_offset: 896 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 2, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "column_major_my_mat_2x4" + offset: 944 + absolute_offset: 944 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td20 + - &bv21 + name: "column_major_my_mat_3x2" + offset: 1008 + absolute_offset: 1008 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 3, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "column_major_my_mat_3x3" + offset: 1040 + absolute_offset: 1040 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "column_major_my_mat_3x4" + offset: 1088 + absolute_offset: 1088 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 3, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td23 + - &bv24 + name: "column_major_my_mat_4x2" + offset: 1152 + absolute_offset: 1152 + size: 32 + padded_size: 32 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 4, row_count: 2, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "column_major_my_mat_4x3" + offset: 1184 + absolute_offset: 1184 + size: 48 + padded_size: 48 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "column_major_my_mat_4x4" + offset: 1232 + absolute_offset: 1232 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td26 + - &bv27 + name: "$Globals" + offset: 0 + absolute_offset: 0 + size: 1296 + padded_size: 1296 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 27 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + - *bv5 + - *bv6 + - *bv7 + - *bv8 + - *bv9 + - *bv10 + - *bv11 + - *bv12 + - *bv13 + - *bv14 + - *bv15 + - *bv16 + - *bv17 + - *bv18 + - *bv19 + - *bv20 + - *bv21 + - *bv22 + - *bv23 + - *bv24 + - *bv25 + - *bv26 + type_description: *td27 +all_descriptor_bindings: + - &db0 + spirv_id: 4 + name: "$Globals" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv27 # "$Globals" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td27 + word_offset: { binding: 286, set: 282 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td28 + word_offset: { location: 0 } + - &iv1 + spirv_id: 3 + name: "out.var.SV_TARGET" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td28 + word_offset: { location: 278 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "$Globals" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "$Globals" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 1, + output_variables: + - *iv1 # "out.var.SV_TARGET" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.hlsl new file mode 100644 index 0000000..092d33f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.hlsl @@ -0,0 +1,13 @@ + +struct Constants_t { + float3 Scale; + float Time; + float2 UvOffsets; +}; + +[[vk::push_constant]] Constants_t g_PushConstants; + +float4 main(float4 pos : POSITION) : SV_Position +{ + return float4(g_PushConstants.Time, 0, 0, 0); +} diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv new file mode 100644 index 0000000..2747116 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv.yaml new file mode 100644 index 0000000..bc74608 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/pushconstant.spv.yaml @@ -0,0 +1,202 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 23 + type_name: + struct_member_name: "Scale" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 22 + type_name: + struct_member_name: "Time" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 10 + op: 23 + type_name: + struct_member_name: "UvOffsets" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 4 + op: 30 + type_name: "type.PushConstant.Constants_t" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 + - &td4 + id: 12 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "Scale" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Time" + offset: 12 + absolute_offset: 12 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "UvOffsets" + offset: 16 + absolute_offset: 16 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "g_PushConstants" + offset: 0 + absolute_offset: 0 + size: 24 + padded_size: 24 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # + push_constant_count: 1, + push_constants: + - *bv3 # "g_PushConstants" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/semantics.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.hlsl new file mode 100644 index 0000000..6cb1e25 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.hlsl @@ -0,0 +1,51 @@ +/* +Build with DXC using -fspv-reflect to enable semantics + + dxc -spirv -fspv-reflect -T ps_5_0 -Fo semantics.spv semantics.hlsl + +*/ + +struct UBO { + float4x4 XformMatrix; + float3 Scale; + float t; + float2 uv; +}; + +ConstantBuffer MyConstants : register(b2, space2); + +struct PSInput { + float4 Position : SV_POSITION; + float3 Normal : NORMAL; + float3 Color : COLOR_00001; + float Alpha : OPACITY_512; + float4 Scaling : SCALE_987654321; + float2 TexCoord0 : TEXCOORD0; + float2 TexCoord1 : TEXCOORD1; + float2 TexCoord2 : TEXCOORD2; +}; + +struct PSOutput { + float4 oColor0 : SV_TARGET0; + float4 oColor1 : SV_TARGET1; + float4 oColor2 : SV_TARGET2; + float4 oColor3 : SV_TARGET3; + float4 oColor4 : SV_TARGET4; + float4 oColor5 : SV_TARGET5; + float4 oColor6 : SV_TARGET6; + float4 oColor7 : SV_TARGET7; +}; + +PSOutput main(PSInput input, uint prim_id : SV_PRIMITIVEID) +{ + PSOutput ret; + ret.oColor0 = mul(MyConstants.XformMatrix, input.Position); + ret.oColor1 = float4(input.Normal, 1) + float4(MyConstants.Scale, 0); + ret.oColor2 = float4(input.Color, 1); + ret.oColor3 = float4(0, 0, 0, input.Alpha); + ret.oColor4 = input.Scaling; + ret.oColor5 = float4(input.TexCoord0, 0, 0); + ret.oColor6 = float4(input.TexCoord1, 0, 0); + ret.oColor7 = float4(input.TexCoord2, 0, 0); + return ret; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv new file mode 100644 index 0000000..4d84ae5 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv.yaml new file mode 100644 index 0000000..0ae75e0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/semantics.spv.yaml @@ -0,0 +1,630 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 24 + type_name: + struct_member_name: "XformMatrix" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 5 + op: 23 + type_name: + struct_member_name: "Scale" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 2 + op: 22 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 6 + op: 23 + type_name: + struct_member_name: "uv" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 7 + op: 30 + type_name: "type.ConstantBuffer.UBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - &td5 + id: 3 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 5 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 2 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 6 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 39 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "XformMatrix" + offset: 0 + absolute_offset: 0 + size: 64 + padded_size: 64 + decorations: 0x00000004 # ROW_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 4, row_count: 4, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Scale" + offset: 64 + absolute_offset: 64 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "t" + offset: 76 + absolute_offset: 76 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "uv" + offset: 80 + absolute_offset: 80 + size: 8 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "MyConstants" + offset: 0 + absolute_offset: 0 + size: 96 + padded_size: 96 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + type_description: *td4 +all_descriptor_bindings: + - &db0 + spirv_id: 9 + name: "MyConstants" + binding: 2 + input_attachment_index: 0 + set: 2 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # "MyConstants" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 838, set: 834 } +all_interface_variables: + - &iv0 + spirv_id: 19 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_POSITION" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 15 # FragCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv1 + spirv_id: 22 + name: "in.var.NORMAL" + location: 0 + storage_class: 1 # Input + semantic: "NORMAL" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td6 + word_offset: { location: 774 } + - &iv2 + spirv_id: 24 + name: "in.var.COLOR_1" + location: 1 + storage_class: 1 # Input + semantic: "COLOR_00001" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td6 + word_offset: { location: 778 } + - &iv3 + spirv_id: 27 + name: "in.var.OPACITY_512" + location: 2 + storage_class: 1 # Input + semantic: "OPACITY_512" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td7 + word_offset: { location: 782 } + - &iv4 + spirv_id: 29 + name: "in.var.SCALE_987654321" + location: 3 + storage_class: 1 # Input + semantic: "SCALE_987654321" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 786 } + - &iv5 + spirv_id: 32 + name: "in.var.TEXCOORD0" + location: 4 + storage_class: 1 # Input + semantic: "TEXCOORD0" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td8 + word_offset: { location: 790 } + - &iv6 + spirv_id: 34 + name: "in.var.TEXCOORD1" + location: 5 + storage_class: 1 # Input + semantic: "TEXCOORD1" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td8 + word_offset: { location: 794 } + - &iv7 + spirv_id: 36 + name: "in.var.TEXCOORD2" + location: 6 + storage_class: 1 # Input + semantic: "TEXCOORD2" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td8 + word_offset: { location: 798 } + - &iv8 + spirv_id: 43 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_PRIMITIVEID" + decoration_flags: 0x00000050 # FLAT BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td9 + word_offset: { location: 0 } + - &iv9 + spirv_id: 49 + name: "out.var.SV_TARGET0" + location: 0 + storage_class: 3 # Output + semantic: "SV_TARGET0" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 802 } + - &iv10 + spirv_id: 51 + name: "out.var.SV_TARGET1" + location: 1 + storage_class: 3 # Output + semantic: "SV_TARGET1" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 806 } + - &iv11 + spirv_id: 53 + name: "out.var.SV_TARGET2" + location: 2 + storage_class: 3 # Output + semantic: "SV_TARGET2" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 810 } + - &iv12 + spirv_id: 55 + name: "out.var.SV_TARGET3" + location: 3 + storage_class: 3 # Output + semantic: "SV_TARGET3" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 814 } + - &iv13 + spirv_id: 57 + name: "out.var.SV_TARGET4" + location: 4 + storage_class: 3 # Output + semantic: "SV_TARGET4" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 818 } + - &iv14 + spirv_id: 59 + name: "out.var.SV_TARGET5" + location: 5 + storage_class: 3 # Output + semantic: "SV_TARGET5" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 822 } + - &iv15 + spirv_id: 61 + name: "out.var.SV_TARGET6" + location: 6 + storage_class: 3 # Output + semantic: "SV_TARGET6" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 826 } + - &iv16 + spirv_id: 63 + name: "out.var.SV_TARGET7" + location: 7 + storage_class: 3 # Output + semantic: "SV_TARGET7" + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 830 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 13 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "MyConstants" + descriptor_set_count: 1 + descriptor_sets: + - set: 2 + binding_count: 1 + bindings: + - *db0 # "MyConstants" + input_variable_count: 9, + input_variables: + - *iv0 # + - *iv1 # "in.var.NORMAL" + - *iv2 # "in.var.COLOR_1" + - *iv3 # "in.var.OPACITY_512" + - *iv4 # "in.var.SCALE_987654321" + - *iv5 # "in.var.TEXCOORD0" + - *iv6 # "in.var.TEXCOORD1" + - *iv7 # "in.var.TEXCOORD2" + - *iv8 # + output_variable_count: 8, + output_variables: + - *iv9 # "out.var.SV_TARGET0" + - *iv10 # "out.var.SV_TARGET1" + - *iv11 # "out.var.SV_TARGET2" + - *iv12 # "out.var.SV_TARGET3" + - *iv13 # "out.var.SV_TARGET4" + - *iv14 # "out.var.SV_TARGET5" + - *iv15 # "out.var.SV_TARGET6" + - *iv16 # "out.var.SV_TARGET7" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.hlsl new file mode 100644 index 0000000..d5ecf12 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.hlsl @@ -0,0 +1,33 @@ + +struct SepNormal { + float x; + float y; + float z; +}; + +struct Rgb { + float r[5]; + float g[5]; + float b[5]; +}; + +struct Uv { + float u; + float v; +}; + +struct Data { + float3 Position; + SepNormal Normal; + Rgb Colors[3]; + Uv TexCoords; + float Scales[3]; + uint Id; +}; + +StructuredBuffer MyData : register(t0); + +float4 main() : SV_Target +{ + return float4(MyData[0].Position, 1); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv new file mode 100644 index 0000000..8dffea7 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv.yaml new file mode 100644 index 0000000..69895f2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/structuredbuffer.spv.yaml @@ -0,0 +1,643 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 23 + type_name: + struct_member_name: "Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 13 + op: 22 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 13 + op: 22 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 13 + op: 22 + type_name: + struct_member_name: "z" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 3 + op: 30 + type_name: "SepNormal" + struct_member_name: "Normal" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td1 + - *td2 + - *td3 + - &td5 + id: 9 + op: 28 + type_name: + struct_member_name: "r" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 4 } + member_count: 0 + members: + - &td6 + id: 9 + op: 28 + type_name: + struct_member_name: "g" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 9 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 4 } + member_count: 0 + members: + - &td8 + id: 10 + op: 28 + type_name: "Rgb" + struct_member_name: "Colors" + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 60 } + member_count: 3 + members: + - *td5 + - *td6 + - *td7 + - &td9 + id: 13 + op: 22 + type_name: + struct_member_name: "u" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 13 + op: 22 + type_name: + struct_member_name: "v" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 5 + op: 30 + type_name: "Uv" + struct_member_name: "TexCoords" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td9 + - *td10 + - &td12 + id: 11 + op: 28 + type_name: + struct_member_name: "Scales" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 4 } + member_count: 0 + members: + - &td13 + id: 15 + op: 21 + type_name: + struct_member_name: "Id" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 12 + op: 29 + type_name: "Data" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 228 } + member_count: 6 + members: + - *td0 + - *td4 + - *td8 + - *td11 + - *td12 + - *td13 + - &td15 + id: 7 + op: 30 + type_name: "type.StructuredBuffer.Data" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td14 + - &td16 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "Position" + offset: 0 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "y" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "z" + offset: 8 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "Normal" + offset: 12 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv1 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "r" + offset: 0 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [5,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "g" + offset: 20 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [5,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "b" + offset: 40 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [5,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "Colors" + offset: 24 + absolute_offset: 0 + size: 180 + padded_size: 180 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 60 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv5 + - *bv6 + - *bv7 + type_description: *td8 + - &bv9 + name: "u" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "v" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "TexCoords" + offset: 204 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv9 + - *bv10 + type_description: *td11 + - &bv12 + name: "Scales" + offset: 212 + absolute_offset: 0 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "Id" + offset: 224 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: + offset: 0 + absolute_offset: 0 + size: 228 + padded_size: 228 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 6 + members: + - *bv0 + - *bv4 + - *bv8 + - *bv11 + - *bv12 + - *bv13 + type_description: *td14 + - &bv15 + name: "MyData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv14 + type_description: *td15 +all_descriptor_bindings: + - &db0 + spirv_id: 8 + name: "MyData" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv15 # "MyData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td15 + word_offset: { binding: 233, set: 229 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "out.var.SV_Target" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td16 + word_offset: { location: 225 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "MyData" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "MyData" + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "out.var.SV_Target" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/user_type.hlsl b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.hlsl new file mode 100644 index 0000000..1b46c84 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.hlsl @@ -0,0 +1,63 @@ +StructuredBuffer a; +RWStructuredBuffer b; +AppendStructuredBuffer c; +ConsumeStructuredBuffer d; +Texture1D e; +Texture2D f; +Texture3D g; +TextureCube h; +Texture1DArray i; +Texture2DArray j; +Texture2DMS k; +Texture2DMSArray l; +TextureCubeArray m; +RWTexture1D n; +RWTexture2D o; +RWTexture3D p; +RWTexture1DArray q; +RWTexture2DArray r; +Buffer s; +RWBuffer t; +Texture2DMSArray u; +const Texture2DMSArray v; +Texture1D t1; +Texture2D t2; + +Texture1D eArr[5]; +Texture2D fArr[5]; +Texture3D gArr[5]; +TextureCube hArr[5]; +Texture1DArray iArr[5]; +Texture2DArray jArr[5]; +Texture2DMS kArr[5]; +Texture2DMSArray lArr[5]; +TextureCubeArray mArr[5]; +RWTexture1D nArr[5]; +RWTexture2D oArr[5]; +RWTexture3D pArr[5]; +RWTexture1DArray qArr[5]; +RWTexture2DArray rArr[5]; +Buffer sArr[5]; +RWBuffer tArr[5]; + +cbuffer MyCBuffer { float x; }; + +tbuffer MyTBuffer { float y; }; + +ByteAddressBuffer bab; + +RWByteAddressBuffer rwbab; + +RaytracingAccelerationStructure rs; + +struct S { + float f1; + float3 f2; +}; + +ConstantBuffer cb; + +TextureBuffer tb; + +void main(){ +} diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv new file mode 100644 index 0000000..aeb395d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv.yaml b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv.yaml new file mode 100644 index 0000000..9017494 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/hlsl/user_type.spv.yaml @@ -0,0 +1,3014 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 54 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 53 + op: 30 + type_name: "type.StructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 54 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td3 + id: 57 + op: 30 + type_name: "type.RWStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 54 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td5 + id: 59 + op: 30 + type_name: "type.AppendStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 62 + op: 21 + type_name: + struct_member_name: "counter" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 61 + op: 30 + type_name: "type.ACSBuffer.counter" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 54 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td9 + id: 64 + op: 30 + type_name: "type.ConsumeStructuredBuffer.float" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td8 + - &td10 + id: 66 + op: 25 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 68 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 70 + op: 25 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 72 + op: 25 + type_name: "type.cube.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 74 + op: 25 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td15 + id: 76 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 78 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 80 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 82 + op: 25 + type_name: "type.cube.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td19 + id: 84 + op: 25 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 86 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td21 + id: 88 + op: 25 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=3D image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td22 + id: 90 + op: 25 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 92 + op: 25 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td24 + id: 94 + op: 25 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 3 } # dim=Buffer image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td25 + id: 96 + op: 25 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=Buffer image_format=R32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 98 + op: 28 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td27 + id: 102 + op: 28 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td28 + id: 104 + op: 28 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td29 + id: 106 + op: 28 + type_name: "type.cube.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td30 + id: 108 + op: 28 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td31 + id: 110 + op: 28 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td32 + id: 112 + op: 28 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td33 + id: 114 + op: 28 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td34 + id: 116 + op: 28 + type_name: "type.cube.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td35 + id: 118 + op: 28 + type_name: "type.1d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td36 + id: 120 + op: 28 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td37 + id: 122 + op: 28 + type_name: "type.3d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=3D image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td38 + id: 124 + op: 28 + type_name: "type.1d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td39 + id: 126 + op: 28 + type_name: "type.2d.image.array" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td40 + id: 128 + op: 28 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 3 } # dim=Buffer image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td41 + id: 130 + op: 28 + type_name: "type.buffer.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20010008 # ARRAY EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=Buffer image_format=R32f + array: { dims_count: 1, dims: [5,], stride: 0 } + member_count: 0 + members: + - &td42 + id: 55 + op: 22 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td43 + id: 132 + op: 30 + type_name: "type.MyCBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td42 + - &td44 + id: 55 + op: 22 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td45 + id: 134 + op: 30 + type_name: "type.MyTBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td44 + - &td46 + id: 137 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td47 + id: 136 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td46 + - &td48 + id: 137 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td49 + id: 139 + op: 30 + type_name: "type.RWByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td48 + - &td50 + id: 141 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td51 + id: 55 + op: 22 + type_name: + struct_member_name: "f1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td52 + id: 144 + op: 23 + type_name: + struct_member_name: "f2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td53 + id: 143 + op: 30 + type_name: "type.ConstantBuffer.S" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td51 + - *td52 + - &td54 + id: 55 + op: 22 + type_name: + struct_member_name: "f1" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td55 + id: 144 + op: 23 + type_name: + struct_member_name: "f2" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td56 + id: 146 + op: 30 + type_name: "type.TextureBuffer.S" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td54 + - *td55 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "a" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "b" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "c" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv4 + type_description: *td5 + - &bv6 + name: "counter" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "counter.var.c" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv6 + type_description: *td7 + - &bv8 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "d" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv8 + type_description: *td9 + - &bv10 + name: "counter" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv11 + name: "counter.var.d" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv10 + type_description: *td7 + - &bv12 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv13 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv14 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv15 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv16 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv17 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv18 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv19 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv20 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv21 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv22 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv23 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv24 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv25 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv26 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv27 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv28 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv29 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv30 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv31 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv32 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv33 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv34 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv35 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv36 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv37 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv38 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv39 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv40 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv41 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv42 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv43 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv44 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv45 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv46 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv47 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv48 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td42 + - &bv49 + name: "MyCBuffer" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv48 + type_description: *td43 + - &bv50 + name: "y" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td44 + - &bv51 + name: "MyTBuffer" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv50 + type_description: *td45 + - &bv52 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td46 + - &bv53 + name: "bab" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv52 + type_description: *td47 + - &bv54 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td48 + - &bv55 + name: "rwbab" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv54 + type_description: *td49 + - &bv56 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv57 + name: "f1" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td51 + - &bv58 + name: "f2" + offset: 4 + absolute_offset: 4 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td52 + - &bv59 + name: "cb" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv57 + - *bv58 + type_description: *td53 + - &bv60 + name: "f1" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td54 + - &bv61 + name: "f2" + offset: 4 + absolute_offset: 4 + size: 12 + padded_size: 12 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td55 + - &bv62 + name: "tb" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv60 + - *bv61 + type_description: *td56 +all_descriptor_bindings: + - &db0 + spirv_id: 7 + name: "a" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "a" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 840, set: 836 } + user_type: StructuredBuffer + - &db1 + spirv_id: 8 + name: "b" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "b" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 848, set: 844 } + user_type: RWStructuredBuffer + - &db2 + spirv_id: 4 + name: "counter.var.c" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # "counter.var.c" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 864, set: 860 } + - &db3 + spirv_id: 3 + name: "c" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "c" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4 + uav_counter_binding: *db2 # "counter.var.c" + type_description: *td5 + word_offset: { binding: 856, set: 852 } + user_type: AppendStructuredBuffer + - *db2 + - &db4 + spirv_id: 6 + name: "counter.var.d" + binding: 5 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "counter.var.d" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 880, set: 876 } + - &db5 + spirv_id: 5 + name: "d" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv9 # "d" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 6 + uav_counter_binding: *db4 # "counter.var.d" + type_description: *td9 + word_offset: { binding: 872, set: 868 } + user_type: ConsumeStructuredBuffer + - *db4 + - &db6 + spirv_id: 9 + name: "e" + binding: 6 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv12 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td10 + word_offset: { binding: 888, set: 884 } + user_type: Texture1D + - &db7 + spirv_id: 10 + name: "f" + binding: 7 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv13 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 896, set: 892 } + user_type: Texture2D + - &db8 + spirv_id: 11 + name: "g" + binding: 8 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + block: *bv14 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td12 + word_offset: { binding: 904, set: 900 } + user_type: Texture3D + - &db9 + spirv_id: 12 + name: "h" + binding: 9 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv15 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td13 + word_offset: { binding: 912, set: 908 } + user_type: TextureCube + - &db10 + spirv_id: 13 + name: "i" + binding: 10 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv16 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td14 + word_offset: { binding: 920, set: 916 } + user_type: Texture1DArray + - &db11 + spirv_id: 14 + name: "j" + binding: 11 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv17 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td15 + word_offset: { binding: 928, set: 924 } + user_type: Texture2DArray + - &db12 + spirv_id: 15 + name: "k" + binding: 12 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv18 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td16 + word_offset: { binding: 936, set: 932 } + user_type: Texture2DMS + - &db13 + spirv_id: 16 + name: "l" + binding: 13 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv19 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 944, set: 940 } + user_type: Texture2DMSArray + - &db14 + spirv_id: 17 + name: "m" + binding: 14 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv20 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td18 + word_offset: { binding: 952, set: 948 } + user_type: TextureCubeArray + - &db15 + spirv_id: 18 + name: "n" + binding: 15 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + block: *bv21 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td19 + word_offset: { binding: 960, set: 956 } + user_type: RWTexture1D + - &db16 + spirv_id: 19 + name: "o" + binding: 16 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + block: *bv22 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td20 + word_offset: { binding: 968, set: 964 } + user_type: RWTexture2D + - &db17 + spirv_id: 20 + name: "p" + binding: 17 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=3D image_format=R32f + block: *bv23 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td21 + word_offset: { binding: 976, set: 972 } + user_type: RWTexture3D + - &db18 + spirv_id: 21 + name: "q" + binding: 18 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + block: *bv24 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td22 + word_offset: { binding: 984, set: 980 } + user_type: RWTexture1DArray + - &db19 + spirv_id: 22 + name: "r" + binding: 19 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + block: *bv25 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td23 + word_offset: { binding: 992, set: 988 } + user_type: RWTexture2DArray + - &db20 + spirv_id: 23 + name: "s" + binding: 20 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 4 # VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + resource_type: 4 # SRV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 3 } # dim=Buffer image_format=R32f + block: *bv26 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td24 + word_offset: { binding: 1000, set: 996 } + user_type: Buffer + - &db21 + spirv_id: 24 + name: "t" + binding: 21 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 5 # VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + resource_type: 8 # UAV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=Buffer image_format=R32f + block: *bv27 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td25 + word_offset: { binding: 1008, set: 1004 } + user_type: RWBuffer + - &db22 + spirv_id: 25 + name: "u" + binding: 22 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv28 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 1016, set: 1012 } + user_type: Texture2DMSArray + - &db23 + spirv_id: 26 + name: "v" + binding: 23 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv29 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 1024, set: 1020 } + user_type: Texture2DMSArray + - &db24 + spirv_id: 27 + name: "t1" + binding: 24 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv30 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td10 + word_offset: { binding: 1032, set: 1028 } + user_type: Texture1D + - &db25 + spirv_id: 28 + name: "t2" + binding: 25 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv31 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 1040, set: 1036 } + user_type: Texture2D + - &db26 + spirv_id: 29 + name: "eArr" + binding: 26 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv32 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td26 + word_offset: { binding: 1048, set: 1044 } + user_type: Texture1D + - &db27 + spirv_id: 30 + name: "fArr" + binding: 27 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv33 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td27 + word_offset: { binding: 1056, set: 1052 } + user_type: Texture2D + - &db28 + spirv_id: 31 + name: "gArr" + binding: 28 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=3D image_format=Unknown + block: *bv34 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td28 + word_offset: { binding: 1064, set: 1060 } + user_type: Texture3D + - &db29 + spirv_id: 32 + name: "hArr" + binding: 29 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv35 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1072, set: 1068 } + user_type: TextureCube + - &db30 + spirv_id: 33 + name: "iArr" + binding: 30 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=1D image_format=Unknown + block: *bv36 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td30 + word_offset: { binding: 1080, set: 1076 } + user_type: Texture1DArray + - &db31 + spirv_id: 34 + name: "jArr" + binding: 31 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv37 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td31 + word_offset: { binding: 1088, set: 1084 } + user_type: Texture2DArray + - &db32 + spirv_id: 35 + name: "kArr" + binding: 32 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv38 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td32 + word_offset: { binding: 1096, set: 1092 } + user_type: Texture2DMS + - &db33 + spirv_id: 36 + name: "lArr" + binding: 33 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 1, ms: 1, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv39 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td33 + word_offset: { binding: 1104, set: 1100 } + user_type: Texture2DMSArray + - &db34 + spirv_id: 37 + name: "mArr" + binding: 34 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 3, depth: 2, arrayed: 1, ms: 0, sampled: 1, image_format: 0 } # dim=Cube image_format=Unknown + block: *bv40 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td34 + word_offset: { binding: 1112, set: 1108 } + user_type: TextureCubeArray + - &db35 + spirv_id: 38 + name: "nArr" + binding: 35 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + block: *bv41 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td35 + word_offset: { binding: 1120, set: 1116 } + user_type: RWTexture1D + - &db36 + spirv_id: 39 + name: "oArr" + binding: 36 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + block: *bv42 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td36 + word_offset: { binding: 1128, set: 1124 } + user_type: RWTexture2D + - &db37 + spirv_id: 40 + name: "pArr" + binding: 37 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 2, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=3D image_format=R32f + block: *bv43 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td37 + word_offset: { binding: 1136, set: 1132 } + user_type: RWTexture3D + - &db38 + spirv_id: 41 + name: "qArr" + binding: 38 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 0, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=1D image_format=R32f + block: *bv44 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td38 + word_offset: { binding: 1144, set: 1140 } + user_type: RWTexture1DArray + - &db39 + spirv_id: 42 + name: "rArr" + binding: 39 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 1, ms: 0, sampled: 2, image_format: 3 } # dim=2D image_format=R32f + block: *bv45 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td39 + word_offset: { binding: 1152, set: 1148 } + user_type: RWTexture2DArray + - &db40 + spirv_id: 43 + name: "sArr" + binding: 40 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 4 # VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + resource_type: 4 # SRV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 3 } # dim=Buffer image_format=R32f + block: *bv46 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td40 + word_offset: { binding: 1160, set: 1156 } + user_type: Buffer + - &db41 + spirv_id: 44 + name: "tArr" + binding: 41 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 5 # VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + resource_type: 8 # UAV + image: { dim: 5, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 3 } # dim=Buffer image_format=R32f + block: *bv47 # + array: { dims_count: 1, dims: [5,] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td41 + word_offset: { binding: 1168, set: 1164 } + user_type: RWBuffer + - &db42 + spirv_id: 45 + name: "MyCBuffer" + binding: 42 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv49 # "MyCBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td43 + word_offset: { binding: 1176, set: 1172 } + user_type: cbuffer + - &db43 + spirv_id: 46 + name: "MyTBuffer" + binding: 43 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv51 # "MyTBuffer" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td45 + word_offset: { binding: 1184, set: 1180 } + user_type: tbuffer + - &db44 + spirv_id: 47 + name: "bab" + binding: 44 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv53 # "bab" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td47 + word_offset: { binding: 1192, set: 1188 } + user_type: ByteAddressBuffer + - &db45 + spirv_id: 48 + name: "rwbab" + binding: 45 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv55 # "rwbab" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td49 + word_offset: { binding: 1200, set: 1196 } + user_type: RWByteAddressBuffer + - &db46 + spirv_id: 49 + name: "rs" + binding: 46 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv56 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td50 + word_offset: { binding: 1208, set: 1204 } + user_type: RaytracingAccelerationStructure + - &db47 + spirv_id: 50 + name: "cb" + binding: 47 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv59 # "cb" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td53 + word_offset: { binding: 1216, set: 1212 } + user_type: ConstantBuffer + - &db48 + spirv_id: 51 + name: "tb" + binding: 48 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv62 # "tb" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td56 + word_offset: { binding: 1224, set: 1220 } + user_type: TextureBuffer +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 49 + descriptor_bindings: + - *db0 # "a" + - *db1 # "b" + - *db3 # "c" + - *db2 # "counter.var.c" + - *db5 # "d" + - *db4 # "counter.var.d" + - *db6 # "e" + - *db7 # "f" + - *db8 # "g" + - *db9 # "h" + - *db10 # "i" + - *db11 # "j" + - *db12 # "k" + - *db13 # "l" + - *db14 # "m" + - *db15 # "n" + - *db16 # "o" + - *db17 # "p" + - *db18 # "q" + - *db19 # "r" + - *db20 # "s" + - *db21 # "t" + - *db22 # "u" + - *db23 # "v" + - *db24 # "t1" + - *db25 # "t2" + - *db26 # "eArr" + - *db27 # "fArr" + - *db28 # "gArr" + - *db29 # "hArr" + - *db30 # "iArr" + - *db31 # "jArr" + - *db32 # "kArr" + - *db33 # "lArr" + - *db34 # "mArr" + - *db35 # "nArr" + - *db36 # "oArr" + - *db37 # "pArr" + - *db38 # "qArr" + - *db39 # "rArr" + - *db40 # "sArr" + - *db41 # "tArr" + - *db42 # "MyCBuffer" + - *db43 # "MyTBuffer" + - *db44 # "bab" + - *db45 # "rwbab" + - *db46 # "rs" + - *db47 # "cb" + - *db48 # "tb" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 49 + bindings: + - *db0 # "a" + - *db1 # "b" + - *db3 # "c" + - *db2 # "counter.var.c" + - *db5 # "d" + - *db4 # "counter.var.d" + - *db6 # "e" + - *db7 # "f" + - *db8 # "g" + - *db9 # "h" + - *db10 # "i" + - *db11 # "j" + - *db12 # "k" + - *db13 # "l" + - *db14 # "m" + - *db15 # "n" + - *db16 # "o" + - *db17 # "p" + - *db18 # "q" + - *db19 # "r" + - *db20 # "s" + - *db21 # "t" + - *db22 # "u" + - *db23 # "v" + - *db24 # "t1" + - *db25 # "t2" + - *db26 # "eArr" + - *db27 # "fArr" + - *db28 # "gArr" + - *db29 # "hArr" + - *db30 # "iArr" + - *db31 # "jArr" + - *db32 # "kArr" + - *db33 # "lArr" + - *db34 # "mArr" + - *db35 # "nArr" + - *db36 # "oArr" + - *db37 # "pArr" + - *db38 # "qArr" + - *db39 # "rArr" + - *db40 # "sArr" + - *db41 # "tArr" + - *db42 # "MyCBuffer" + - *db43 # "MyTBuffer" + - *db44 # "bab" + - *db45 # "rwbab" + - *db46 # "rs" + - *db47 # "cb" + - *db48 # "tb" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.glsl b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.glsl new file mode 100644 index 0000000..850974e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.glsl @@ -0,0 +1,21 @@ +#version 450 core + +in gl_PerVertex { + vec4 gl_Position; + float gl_CullDistance[3]; +} gl_in[]; + +out gl_PerVertex { + float gl_CullDistance[3]; +}; + +layout(triangles) in; +layout(invocations = 4) in; +layout(line_strip) out; +layout(max_vertices = 127) out; + +void main() +{ + vec4 pos = gl_in[2].gl_Position; + gl_CullDistance[2] = gl_in[1].gl_CullDistance[2] * pos.x; +} diff --git a/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv new file mode 100644 index 0000000..540b16a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv.yaml b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv.yaml new file mode 100644 index 0000000..c90c78a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/interface/geom_input_builtin_array.spv.yaml @@ -0,0 +1,210 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 12 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + - &td2 + id: 14 + op: 28 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 12 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 23 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 0 # UniformConstant + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 0 # VK_FORMAT_UNDEFINED + type_description: + word_offset: { location: 0 } + - &iv2 + spirv_id: 16 + name: "gl_in" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 2 + members: + - *iv0 # + - *iv1 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 25 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 4 # [CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *iv3 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 3 # Geometry + shader_stage: 0x00000008 # GS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv2 # "gl_in" + output_variable_count: 1, + output_variables: + - *iv4 # "" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv new file mode 100644 index 0000000..4e25fe4 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv.yaml b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv.yaml new file mode 100644 index 0000000..20b5bdd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_block.spv.yaml @@ -0,0 +1,247 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 5 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 9 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 8 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 4 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 42 # VertexIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 43 # InstanceIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 42, 43 # [VertexIndex, InstanceIndex] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *iv0 # + - *iv1 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv5 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1 # [Position, PointSize] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *iv3 # + - *iv4 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td5 + word_offset: { location: 0 } +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv2 # + output_variable_count: 1, + output_variables: + - *iv5 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.glsl b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.glsl new file mode 100644 index 0000000..4dc2018 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.glsl @@ -0,0 +1,12 @@ +#version 450 + +out gl_PerVertex { + vec4 gl_Position; + float gl_PointSize; +}; + +void main() { + float x[4]; + gl_Position = vec4(x[gl_VertexIndex % 4]); + gl_PointSize = x[gl_InstanceIndex % 4]; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv new file mode 100644 index 0000000..d0bd9a6 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv.yaml b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv.yaml new file mode 100644 index 0000000..451728f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/interface/vertex_input_builtin_non_block.spv.yaml @@ -0,0 +1,192 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 8 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td1 + - *td2 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 19 + name: "gl_VertexIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 42 # VertexIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 30 + name: "gl_InstanceIndex" + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 43 # InstanceIndex + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 99 # VK_FORMAT_R32_SINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv4 + spirv_id: 10 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1 # [Position, PointSize] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *iv2 # + - *iv3 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td3 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 2, + input_variables: + - *iv0 # "gl_VertexIndex" + - *iv1 # "gl_InstanceIndex" + output_variable_count: 1, + output_variables: + - *iv4 # "" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.glsl b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.glsl new file mode 100644 index 0000000..8daa2fd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.glsl @@ -0,0 +1,51 @@ +/* +glslangValidator -V -S frag -g0 --ku -o function_parameter_access.spv function_parameter_access.glsl +*/ + +#version 450 + +layout(binding = 0) uniform sampler Sampler; +layout(binding = 1) uniform texture2D Texture; +layout(binding = 2) uniform sampler2D Sampler2D; + +layout(binding = 3) uniform sampler NeverAccessedSampler; +layout(binding = 4) uniform texture2D NeverAccessedTexture; +layout(binding = 5) uniform sampler2D NeverAccessedSampler2D; + +layout(location = 0) out vec4 color; + +vec4 access_sampler_and_texture(texture2D t, sampler s, vec2 coord) +{ + vec4 ret = texture(sampler2D(t, s), coord); + return vec4(5.0) * ret; +} + +vec4 access_combined_sampler(sampler2D s) +{ + vec2 coord = vec2(0.5, 0.5); + vec4 ret = texture(s, coord); + return vec4(1.0, 2.0, 3.0, 1.0) * ret; +} + +vec4 call_access_functions(texture2D t, sampler s) +{ + return access_combined_sampler(Sampler2D) + access_sampler_and_texture(t, s, vec2(0.25, 0.75)); +} + +vec4 never_called(texture2D t, sampler s, float u, float v) +{ + vec4 ret = texture(sampler2D(t, s), vec2(u, v)); + return vec4(-3.0) * ret; +} + +vec4 never_called_2(vec2 coord) +{ + vec4 ret = texture(sampler2D(NeverAccessedTexture, NeverAccessedSampler), coord); + ret *= texture(NeverAccessedSampler2D, coord); + return ret; +} + +void main() +{ + color = vec4(-1.0) * call_access_functions(Texture, Sampler); +} diff --git a/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv new file mode 100644 index 0000000..7638142 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv.yaml new file mode 100644 index 0000000..297f647 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/102/function_parameter_access.spv.yaml @@ -0,0 +1,327 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 26 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00020000 # EXTERNAL_SAMPLER + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 25 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 20 + op: 27 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00050008 # EXTERNAL_SAMPLED_IMAGE EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 13 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv5 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 117 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 0 # VK_DESCRIPTOR_TYPE_SAMPLER + resource_type: 1 # SAMPLER + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 76, set: 72 } + - &db1 + spirv_id: 116 + name: + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 68, set: 64 } + - &db2 + spirv_id: 71 + name: + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1 # VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + resource_type: 5 # ??? + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv2 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 32, set: 28 } + - &db3 + spirv_id: 98 + name: + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 0 # VK_DESCRIPTOR_TYPE_SAMPLER + resource_type: 1 # SAMPLER + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 48, set: 44 } + - &db4 + spirv_id: 96 + name: + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv4 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 40, set: 36 } + - &db5 + spirv_id: 103 + name: + binding: 5 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1 # VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + resource_type: 5 # ??? + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv5 # + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 56, set: 52 } +all_interface_variables: + - &iv0 + spirv_id: 113 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 60 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 6 + descriptor_bindings: + - *db0 # + - *db1 # + - *db2 # + - *db3 # + - *db4 # + - *db5 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 6 + bindings: + - *db0 # + - *db1 # + - *db2 # + - *db3 # + - *db4 # + - *db5 # + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv new file mode 100644 index 0000000..22c8f65 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv.yaml new file mode 100644 index 0000000..8cf9384 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct.spv.yaml @@ -0,0 +1,137 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: "alice" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "bob" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 3 + op: 30 + type_name: "Communicators" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 9 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 11 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000001 # BLOCK + built_in: 0, 0 # [Position, Position] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *iv0 # + - *iv1 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td2 + word_offset: { location: 0 } +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv2 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv new file mode 100644 index 0000000..34006eb Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv.yaml new file mode 100644 index 0000000..e9a8fc5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/178/vertex_input_struct2.spv.yaml @@ -0,0 +1,174 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 11 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000308 # ARRAY MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + - &td3 + id: 3 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 2 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 4 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 6 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 2, row_count: 4, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000001 # BLOCK + built_in: 0, 0, 0 # [Position, Position, Position] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *iv0 # + - *iv1 # + - *iv2 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td3 + word_offset: { location: 0 } +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 1, + input_variables: + - *iv3 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/227/README.md b/lib/All/SPIRV-Reflect/tests/issues/227/README.md new file mode 100644 index 0000000..bc3c104 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/227/README.md @@ -0,0 +1 @@ +Note that null_node.spv and null_type.spv are not valid SPIR-V inputs, can not be decompiled into GLSL, and are solely provided to prevent regressions for a specific null pointer dereference bug (https://github.com/KhronosGroup/SPIRV-Reflect/issues/227). diff --git a/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv b/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv new file mode 100644 index 0000000..e7cb673 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv.yaml new file mode 100644 index 0000000..81ad0e4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/227/null_node.spv.yaml @@ -0,0 +1,257 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 22 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 23 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 8 + op: 24 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 11 + op: 28 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 12 + op: 29 + type_name: + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td5 + id: 13 + op: 30 + type_name: "ssbo" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 5 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 16 + absolute_offset: 16 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 32 + absolute_offset: 32 + size: 48 + padded_size: 48 + decorations: 0x00000008 # COLUMN_MAJOR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 3, row_count: 3, stride: 16 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "d" + offset: 80 + absolute_offset: 80 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "e" + offset: 96 + absolute_offset: 96 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 5 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 15 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 114, set: 110 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/68/64_bit_float.glsl b/lib/All/SPIRV-Reflect/tests/issues/68/64_bit_float.glsl new file mode 100644 index 0000000..25c4bc8 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/68/64_bit_float.glsl @@ -0,0 +1,14 @@ +#version 460 core +#extension GL_ARB_separate_shader_objects : enable + +layout(location=0) in dvec2 position; +layout(location=1) in double in_thing; + +layout(location=0) out VertexData { +double out_thing; +} VertexOut; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); + VertexOut.out_thing = in_thing; +} diff --git a/lib/All/SPIRV-Reflect/tests/issues/68/sample_spv.h b/lib/All/SPIRV-Reflect/tests/issues/68/sample_spv.h new file mode 100644 index 0000000..a64e59f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/68/sample_spv.h @@ -0,0 +1,112 @@ +#ifndef SAMPLE_SPV_H +#define SAMPLE_SPV_H + +/* Source from sample.hlsl + +#version 460 core +#extension GL_ARB_separate_shader_objects : enable + +layout(location=0) in dvec2 position; +layout(location=1) in double in_thing; + +layout(location=0) out VertexData { +double out_thing; +} VertexOut; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); + VertexOut.out_thing = in_thing; +} + + +*/ + +// Imported from file 'sample.spv' +const uint32_t k_sample_spv[] = { +0x07230203,0x00010000,0x000d000a,0x00000026, +0x00000000,0x00020011,0x00000001,0x00020011, +0x0000000a,0x0006000b,0x00000001,0x4c534c47, +0x6474732e,0x3035342e,0x00000000,0x0003000e, +0x00000000,0x00000001,0x0009000f,0x00000000, +0x00000004,0x6e69616d,0x00000000,0x0000000d, +0x00000013,0x00000020,0x00000022,0x00030003, +0x00000002,0x000001cc,0x00090004,0x415f4c47, +0x735f4252,0x72617065,0x5f657461,0x64616873, +0x6f5f7265,0x63656a62,0x00007374,0x000a0004, +0x475f4c47,0x4c474f4f,0x70635f45,0x74735f70, +0x5f656c79,0x656e696c,0x7269645f,0x69746365, +0x00006576,0x00080004,0x475f4c47,0x4c474f4f, +0x6e695f45,0x64756c63,0x69645f65,0x74636572, +0x00657669,0x00040005,0x00000004,0x6e69616d, +0x00000000,0x00060005,0x0000000b,0x505f6c67, +0x65567265,0x78657472,0x00000000,0x00060006, +0x0000000b,0x00000000,0x505f6c67,0x7469736f, +0x006e6f69,0x00070006,0x0000000b,0x00000001, +0x505f6c67,0x746e696f,0x657a6953,0x00000000, +0x00070006,0x0000000b,0x00000002,0x435f6c67, +0x4470696c,0x61747369,0x0065636e,0x00070006, +0x0000000b,0x00000003,0x435f6c67,0x446c6c75, +0x61747369,0x0065636e,0x00030005,0x0000000d, +0x00000000,0x00050005,0x00000013,0x69736f70, +0x6e6f6974,0x00000000,0x00050005,0x0000001e, +0x74726556,0x61447865,0x00006174,0x00060006, +0x0000001e,0x00000000,0x5f74756f,0x6e696874, +0x00000067,0x00050005,0x00000020,0x74726556, +0x754f7865,0x00000074,0x00050005,0x00000022, +0x745f6e69,0x676e6968,0x00000000,0x00050048, +0x0000000b,0x00000000,0x0000000b,0x00000000, +0x00050048,0x0000000b,0x00000001,0x0000000b, +0x00000001,0x00050048,0x0000000b,0x00000002, +0x0000000b,0x00000003,0x00050048,0x0000000b, +0x00000003,0x0000000b,0x00000004,0x00030047, +0x0000000b,0x00000002,0x00040047,0x00000013, +0x0000001e,0x00000000,0x00030047,0x0000001e, +0x00000002,0x00040047,0x00000020,0x0000001e, +0x00000000,0x00040047,0x00000022,0x0000001e, +0x00000001,0x00020013,0x00000002,0x00030021, +0x00000003,0x00000002,0x00030016,0x00000006, +0x00000020,0x00040017,0x00000007,0x00000006, +0x00000004,0x00040015,0x00000008,0x00000020, +0x00000000,0x0004002b,0x00000008,0x00000009, +0x00000001,0x0004001c,0x0000000a,0x00000006, +0x00000009,0x0006001e,0x0000000b,0x00000007, +0x00000006,0x0000000a,0x0000000a,0x00040020, +0x0000000c,0x00000003,0x0000000b,0x0004003b, +0x0000000c,0x0000000d,0x00000003,0x00040015, +0x0000000e,0x00000020,0x00000001,0x0004002b, +0x0000000e,0x0000000f,0x00000000,0x00030016, +0x00000010,0x00000040,0x00040017,0x00000011, +0x00000010,0x00000002,0x00040020,0x00000012, +0x00000001,0x00000011,0x0004003b,0x00000012, +0x00000013,0x00000001,0x00040017,0x00000015, +0x00000006,0x00000002,0x0004002b,0x00000006, +0x00000017,0x00000000,0x0004002b,0x00000006, +0x00000018,0x3f800000,0x00040020,0x0000001c, +0x00000003,0x00000007,0x0003001e,0x0000001e, +0x00000010,0x00040020,0x0000001f,0x00000003, +0x0000001e,0x0004003b,0x0000001f,0x00000020, +0x00000003,0x00040020,0x00000021,0x00000001, +0x00000010,0x0004003b,0x00000021,0x00000022, +0x00000001,0x00040020,0x00000024,0x00000003, +0x00000010,0x00050036,0x00000002,0x00000004, +0x00000000,0x00000003,0x000200f8,0x00000005, +0x0004003d,0x00000011,0x00000014,0x00000013, +0x00040073,0x00000015,0x00000016,0x00000014, +0x00050051,0x00000006,0x00000019,0x00000016, +0x00000000,0x00050051,0x00000006,0x0000001a, +0x00000016,0x00000001,0x00070050,0x00000007, +0x0000001b,0x00000019,0x0000001a,0x00000017, +0x00000018,0x00050041,0x0000001c,0x0000001d, +0x0000000d,0x0000000f,0x0003003e,0x0000001d, +0x0000001b,0x0004003d,0x00000010,0x00000023, +0x00000022,0x00050041,0x00000024,0x00000025, +0x00000020,0x0000000f,0x0003003e,0x00000025, +0x00000023,0x000100fd,0x00010038 +}; + +/* SPIRV Disassembly + + +*/ + +#endif // SAMPLE_SPV_H diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.hlsl b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.hlsl new file mode 100644 index 0000000..03b0819 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.hlsl @@ -0,0 +1,38 @@ +struct S_cbPerObjectBones +{ + float4 v4Bones[4095]; +}; + +shared cbuffer _cbPerObjectBones : register(b4) +{ + S_cbPerObjectBones cbPerObjectBones; +}; + +struct v2f +{ + float4 HPosition: SV_POSITION; + float4 Position: POSITION; +}; + +struct a2v_StandardWeighted +{ + float4 Position: POSITION0; + int4 Indices: BLENDINDICES; +}; + +float3x4 FailFunc(int4 i, float4 v4Bones[4095]) +{ + float4 mRow1 = v4Bones[i.x+0]; + return float3x4(mRow1, mRow1, mRow1); +} + +v2f Test_VS(a2v_StandardWeighted input) +{ + v2f OUT=(v2f)0; + float4 inputPosition = float4(input.Position.xyz, 1); + int4 i = input.Indices; + float3x4 mMatrix = FailFunc(i, cbPerObjectBones.v4Bones); + float4 v4Position = float4(mul(mMatrix, inputPosition), 1); + OUT.Position = v4Position; + return OUT; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv new file mode 100644 index 0000000..bbb3e1a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv.yaml new file mode 100644 index 0000000..409e856 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo.spv.yaml @@ -0,0 +1,262 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 28 + type_name: + struct_member_name: "v4Bones" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4095,], stride: 16 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "S_cbPerObjectBones" + struct_member_name: "cbPerObjectBones" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 6 + op: 30 + type_name: "type._cbPerObjectBones" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 11 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 19 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "v4Bones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4095,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "_cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 8 + name: "_cbPerObjectBones" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "_cbPerObjectBones" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 105, set: 101 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "in.var.POSITION0" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 89 } + - &iv1 + spirv_id: 3 + name: "in.var.BLENDINDICES" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 108 # VK_FORMAT_R32G32B32A32_SINT + type_description: *td4 + word_offset: { location: 93 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: "out.var.POSITION" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 97 } +module: + generator: 14 # Google spiregg + entry_point_name: "Test_VS" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "_cbPerObjectBones" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "_cbPerObjectBones" + input_variable_count: 2, + input_variables: + - *iv0 # "in.var.POSITION0" + - *iv1 # "in.var.BLENDINDICES" + output_variable_count: 2, + output_variables: + - *iv2 # + - *iv3 # "out.var.POSITION" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv new file mode 100644 index 0000000..98cb4aa Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv.yaml new file mode 100644 index 0000000..be36b20 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/array_from_ubo_with_O0.spv.yaml @@ -0,0 +1,262 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 18 + op: 28 + type_name: + struct_member_name: "v4Bones" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4095,], stride: 16 } + member_count: 0 + members: + - &td1 + id: 17 + op: 30 + type_name: "S_cbPerObjectBones" + struct_member_name: "cbPerObjectBones" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 16 + op: 30 + type_name: "type._cbPerObjectBones" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 8 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 23 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "v4Bones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4095,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "_cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 6 + name: "_cbPerObjectBones" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "_cbPerObjectBones" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 213, set: 209 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "in.var.POSITION0" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 197 } + - &iv1 + spirv_id: 3 + name: "in.var.BLENDINDICES" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 108 # VK_FORMAT_R32G32B32A32_SINT + type_description: *td4 + word_offset: { location: 201 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: "out.var.POSITION" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 205 } +module: + generator: 14 # Google spiregg + entry_point_name: "Test_VS" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "_cbPerObjectBones" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "_cbPerObjectBones" + input_variable_count: 2, + input_variables: + - *iv0 # "in.var.POSITION0" + - *iv1 # "in.var.BLENDINDICES" + output_variable_count: 2, + output_variables: + - *iv2 # + - *iv3 # "out.var.POSITION" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.hlsl b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.hlsl new file mode 100644 index 0000000..2232279 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.hlsl @@ -0,0 +1,42 @@ +/* + +Compile command: +dxc.exe -T vs_6_0 -spirv -E Test_VS -Fo rocketz.spv rocketz.hlsl + +*/ + +struct S_cbPerObjectBones { + float4 v4Bones[4095]; +}; + +shared cbuffer _cbPerObjectBones : register(b4) +{ + S_cbPerObjectBones cbPerObjectBones; +}; + +struct v2f { + float4 HPosition : SV_POSITION; + float4 Position : POSITION; +}; + +struct a2v_StandardWeighted { + float4 Position : POSITION0; + int4 Indices : BLENDINDICES; +}; + +float3x4 FailFunc(int4 i, float4 v4Bones[4095]) +{ + float4 mRow1 = v4Bones[i.x + 0]; + return float3x4(mRow1, mRow1, mRow1); +} + +v2f Test_VS(a2v_StandardWeighted input) +{ + v2f OUT = (v2f)0; + float4 inputPosition = float4(input.Position.xyz, 1); + int4 i = input.Indices; + float3x4 mMatrix = FailFunc(i, cbPerObjectBones.v4Bones); + float4 v4Position = float4(mul(mMatrix, inputPosition), 1); + OUT.Position = v4Position; + return OUT; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv new file mode 100644 index 0000000..bbb3e1a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv.yaml b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv.yaml new file mode 100644 index 0000000..409e856 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/issues/77/hlsl/rocketz.spv.yaml @@ -0,0 +1,262 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 28 + type_name: + struct_member_name: "v4Bones" + storage_class: 0 # UniformConstant + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4095,], stride: 16 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "S_cbPerObjectBones" + struct_member_name: "cbPerObjectBones" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 6 + op: 30 + type_name: "type._cbPerObjectBones" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 11 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 19 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "v4Bones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4095,], stride: 16 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "_cbPerObjectBones" + offset: 0 + absolute_offset: 0 + size: 65520 + padded_size: 65520 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 8 + name: "_cbPerObjectBones" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "_cbPerObjectBones" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 105, set: 101 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "in.var.POSITION0" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 89 } + - &iv1 + spirv_id: 3 + name: "in.var.BLENDINDICES" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 108 # VK_FORMAT_R32G32B32A32_SINT + type_description: *td4 + word_offset: { location: 93 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: "out.var.POSITION" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td3 + word_offset: { location: 97 } +module: + generator: 14 # Google spiregg + entry_point_name: "Test_VS" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "_cbPerObjectBones" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "_cbPerObjectBones" + input_variable_count: 2, + input_variables: + - *iv0 # "in.var.POSITION0" + - *iv1 # "in.var.BLENDINDICES" + output_variable_count: 2, + output_variables: + - *iv2 # + - *iv3 # "out.var.POSITION" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl new file mode 100644 index 0000000..1ba9b60 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl @@ -0,0 +1,36 @@ +// Run: %dxc -spirv -fspv-target-env=vulkan1.3 -E main -T ms_6_7 -fspv-extension=SPV_EXT_mesh_shader + +struct PayLoad +{ + uint data[8]; +}; + +struct Vertex +{ + float4 pos : SV_Position; +}; + +struct Primitive +{ + uint data : COLOR0; +}; + +[outputtopology("triangle")] +[numthreads(32, 1, 1)] +void main(in uint3 dispatchThreadId : SV_DispatchThreadID, + in uint3 groupThreadId : SV_GroupThreadID, + in uint threadIndex : SV_GroupIndex, + in uint3 groupId : SV_GroupID, + out vertices Vertex verts[64], + out indices uint3 tris[124], + out primitives Primitive prims[124]) +{ + SetMeshOutputCounts(3, 1); + + verts[0].pos = float4(1.f, 0.f, 0.f, 1.f); + verts[1].pos = float4(1.f, 1.f, 0.f, 1.f); + verts[2].pos = float4(1.f, 0.f, 1.f, 1.f); + + prims[0].data = 1; + tris[0] = uint3(0, 1, 2); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv new file mode 100644 index 0000000..e9ca9b1 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv.yaml b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv.yaml new file mode 100644 index 0000000..54944a6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv.yaml @@ -0,0 +1,245 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 33 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 17 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 38 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [64,], stride: 0 } + member_count: 0 + members: + - &td3 + id: 41 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000104 # ARRAY VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [124,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 43 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [124,], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 27 # LocalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 29 # LocalInvocationIndex + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 26 # WorkgroupId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv4 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [64,], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv5 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5296 # ??? (5296) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [124,], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv6 + spirv_id: 8 + name: "out.var.COLOR0" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [124,], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 150 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 670 + spirv_execution_model: 5365 # MeshEXT + shader_stage: 0x00000080 # MESH + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 4, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + output_variable_count: 3, + output_variables: + - *iv4 # + - *iv5 # + - *iv6 # "out.var.COLOR0" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl new file mode 100644 index 0000000..5e170bc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl @@ -0,0 +1,20 @@ +// Run: %dxc -spirv -fspv-target-env=vulkan1.3 -E main -T as_6_7 -fspv-extension=SPV_EXT_mesh_shader + +struct PayLoad +{ + uint data[8]; +}; + +groupshared PayLoad s_payload; + +[numthreads(8, 1, 1)] +void main( + in uint3 dispatchThreadId : SV_DispatchThreadID, + in uint3 groupThreadId : SV_GroupThreadID, + in uint threadIndex : SV_GroupIndex, + in uint3 groupId : SV_GroupID) +{ + s_payload.data[groupId.x] = 1; + + DispatchMesh(1, 1, 1, s_payload); +} diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv new file mode 100644 index 0000000..cbbb8c0 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv.yaml b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv.yaml new file mode 100644 index 0000000..7172410 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv.yaml @@ -0,0 +1,137 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 20 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 13 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 27 # LocalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 29 # LocalInvocationIndex + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 26 # WorkgroupId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 670 + spirv_execution_model: 5364 # TaskEXT + shader_stage: 0x00000040 # TASK + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 4, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.glsl b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.glsl new file mode 100644 index 0000000..8cea9b6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.glsl @@ -0,0 +1,44 @@ +#version 450 + +layout (set = 0, binding = 1) uniform Ubo { + vec4 data; +} ubo; + +layout (location = 1) in vec3 pos; +layout (location = 0) in vec2 iUV; +layout (location = 0) out vec2 oUV; + +layout (push_constant) uniform PushConstantVert { + float val; +} push_constant_vert; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec4 getData() { + return ubo.data; +} + +void entry_vert() { + oUV = iUV; + gl_Position = vec4(pos, 1.0) * push_constant_vert.val * getData(); +} + +layout (set = 0, binding = 0) uniform sampler2D tex; +layout (location = 1) out vec4 colour; + +/* +layout (push_constant) uniform PushConstantFrag { + float val; +} push_constant_frag; +*/ + +void entry_frag() { + colour = texture(tex, iUV) * push_constant_vert.val * getData(); +} + +void main() { + entry_vert(); + entry_frag(); +} diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv new file mode 100644 index 0000000..077abb8 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis new file mode 100644 index 0000000..b347c28 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis @@ -0,0 +1,121 @@ +; SPIR-V +; Version: 1.0 +; Generator: Google Shaderc over Glslang; 6 +; Bound: 70 +; Schema: 0 + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Vertex %entry_vert_ "entry_vert" %_ %iUV %oUV %pos + OpEntryPoint Fragment %entry_frag_ "entry_frag" %iUV %colour + OpSource GLSL 450 + OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" + OpSourceExtension "GL_GOOGLE_include_directive" + OpName %getData_ "getData(" + OpName %entry_vert_ "entry_vert(" + OpName %entry_frag_ "entry_frag(" + OpName %Ubo "Ubo" + OpMemberName %Ubo 0 "data" + OpName %ubo "ubo" + OpName %oUV "oUV" + OpName %iUV "iUV" + OpName %gl_PerVertex "gl_PerVertex" + OpMemberName %gl_PerVertex 0 "gl_Position" + OpName %_ "" + OpName %pos "pos" + OpName %PushConstantVert "PushConstantVert" + OpMemberName %PushConstantVert 0 "val" + OpName %push_constant_vert "push_constant_vert" + OpName %PushConstantFrag "PushConstantFrag" + OpMemberName %PushConstantFrag 0 "val" + OpName %push_constant_frag "push_constant_frag" + OpName %colour "colour" + OpName %tex "tex" + OpMemberDecorate %Ubo 0 Offset 0 + OpDecorate %Ubo Block + OpDecorate %ubo DescriptorSet 0 + OpDecorate %ubo Binding 1 + OpDecorate %oUV Location 0 + OpDecorate %iUV Location 0 + OpMemberDecorate %gl_PerVertex 0 BuiltIn Position + OpDecorate %gl_PerVertex Block + OpDecorate %pos Location 1 + OpMemberDecorate %PushConstantVert 0 Offset 0 + OpDecorate %PushConstantVert Block + OpDecorate %colour Location 0 + OpDecorate %tex DescriptorSet 0 + OpDecorate %tex Binding 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 + %8 = OpTypeFunction %v4float + %Ubo = OpTypeStruct %v4float +%_ptr_Uniform_Ubo = OpTypePointer Uniform %Ubo + %ubo = OpVariable %_ptr_Uniform_Ubo Uniform + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float + %v2float = OpTypeVector %float 2 +%_ptr_Output_v2float = OpTypePointer Output %v2float + %oUV = OpVariable %_ptr_Output_v2float Output +%_ptr_Input_v2float = OpTypePointer Input %v2float + %iUV = OpVariable %_ptr_Input_v2float Input +%gl_PerVertex = OpTypeStruct %v4float +%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex + %_ = OpVariable %_ptr_Output_gl_PerVertex Output + %v3float = OpTypeVector %float 3 +%_ptr_Input_v3float = OpTypePointer Input %v3float + %pos = OpVariable %_ptr_Input_v3float Input + %float_1 = OpConstant %float 1 +%PushConstantVert = OpTypeStruct %float +%_ptr_PushConstant_PushConstantVert = OpTypePointer PushConstant %PushConstantVert +%push_constant_vert = OpVariable %_ptr_PushConstant_PushConstantVert PushConstant +%PushConstantFrag = OpTypeStruct %float +%_ptr_PushConstant_PushConstantFrag = OpTypePointer PushConstant %PushConstantFrag +%push_constant_frag = OpVariable %_ptr_PushConstant_PushConstantFrag PushConstant +%_ptr_PushConstant_float = OpTypePointer PushConstant %float +%_ptr_Output_v4float = OpTypePointer Output %v4float + %colour = OpVariable %_ptr_Output_v4float Output + %55 = OpTypeImage %float 2D 0 0 0 1 Unknown + %56 = OpTypeSampledImage %55 +%_ptr_UniformConstant_56 = OpTypePointer UniformConstant %56 + %tex = OpVariable %_ptr_UniformConstant_56 UniformConstant + %float_0 = OpConstant %float 0 + %getData_ = OpFunction %v4float None %8 + %10 = OpLabel + %21 = OpAccessChain %_ptr_Uniform_v4float %ubo %int_0 + %22 = OpLoad %v4float %21 + OpReturnValue %22 + OpFunctionEnd +%entry_vert_ = OpFunction %void None %3 + %12 = OpLabel + %30 = OpLoad %v2float %iUV + OpStore %oUV %30 + %37 = OpLoad %v3float %pos + %39 = OpCompositeExtract %float %37 0 + %40 = OpCompositeExtract %float %37 1 + %41 = OpCompositeExtract %float %37 2 + %42 = OpCompositeConstruct %v4float %39 %40 %41 %float_1 + %47 = OpAccessChain %_ptr_PushConstant_float %push_constant_vert %int_0 + %48 = OpLoad %float %47 + %49 = OpVectorTimesScalar %v4float %42 %48 + %50 = OpFunctionCall %v4float %getData_ + %51 = OpFMul %v4float %49 %50 + %53 = OpAccessChain %_ptr_Output_v4float %_ %int_0 + OpStore %53 %51 + OpReturn + OpFunctionEnd +%entry_frag_ = OpFunction %void None %3 + %14 = OpLabel + %59 = OpLoad %56 %tex + %60 = OpLoad %v2float %iUV + %62 = OpImageSampleExplicitLod %v4float %59 %60 Lod %float_0 + %63 = OpAccessChain %_ptr_PushConstant_float %push_constant_frag %int_0 + %64 = OpLoad %float %63 + %65 = OpVectorTimesScalar %v4float %62 %64 + %66 = OpFunctionCall %v4float %getData_ + %67 = OpFMul %v4float %65 %66 + OpStore %colour %67 + OpReturn + OpFunctionEnd diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis.diff b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis.diff new file mode 100644 index 0000000..27f8586 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.dis.diff @@ -0,0 +1,30 @@ +9c9,10 +< OpEntryPoint Vertex %main "main" %oUV %iUV %_ %pos %colour +--- +> OpEntryPoint Vertex %entry_vert_ "entry_vert" %_ %iUV %oUV %pos +> OpEntryPoint Fragment %entry_frag_ "entry_frag" %iUV %colour +13d13 +< OpName %main "main" +28a29,31 +> OpName %PushConstantFrag "PushConstantFrag" +> OpMemberName %PushConstantFrag 0 "val" +> OpName %push_constant_frag "push_constant_frag" +42c45 +< OpDecorate %colour Location 1 +--- +> OpDecorate %colour Location 0 +70a74,76 +> %PushConstantFrag = OpTypeStruct %float +> %_ptr_PushConstant_PushConstantFrag = OpTypePointer PushConstant %PushConstantFrag +> %push_constant_frag = OpVariable %_ptr_PushConstant_PushConstantFrag PushConstant +79,84d84 +< %main = OpFunction %void None %3 +< %5 = OpLabel +< %68 = OpFunctionCall %void %entry_vert_ +< %69 = OpFunctionCall %void %entry_frag_ +< OpReturn +< OpFunctionEnd +114c114 +< %63 = OpAccessChain %_ptr_PushConstant_float %push_constant_vert %int_0 +--- +> %63 = OpAccessChain %_ptr_PushConstant_float %push_constant_frag %int_0 diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.yaml b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.yaml new file mode 100644 index 0000000..4dd2fa1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/multi_entrypoint.spv.yaml @@ -0,0 +1,471 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 39 + op: 27 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00050008 # EXTERNAL_SAMPLED_IMAGE EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 21 + op: 23 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 10 + op: 30 + type_name: "Ubo" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 20 + op: 22 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 13 + op: 30 + type_name: "PushConstantVert" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 20 + op: 22 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 15 + op: 30 + type_name: "PushConstantFrag" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td5 + - &td7 + id: 27 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 31 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 21 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 12 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td9 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: "data" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "ubo" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "push_constant_vert" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 + - &bv5 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "push_constant_frag" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv5 + type_description: *td6 +all_descriptor_bindings: + - &db0 + spirv_id: 17 + name: "tex" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1 # VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + resource_type: 5 # ??? + image: { dim: 1, depth: 0, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 203, set: 199 } + - &db1 + spirv_id: 11 + name: "ubo" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "ubo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 163, set: 159 } +all_interface_variables: + - &iv0 + spirv_id: 4 + name: "iUV" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td7 + word_offset: { location: 171 } + - &iv1 + spirv_id: 6 + name: "pos" + location: 1 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td8 + word_offset: { location: 183 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td9 + word_offset: { location: 0 } + - &iv3 + spirv_id: 3 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0 # [Position] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *iv2 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td10 + word_offset: { location: 0 } + - &iv4 + spirv_id: 5 + name: "oUV" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 103 # VK_FORMAT_R32G32_SFLOAT + type_description: *td7 + word_offset: { location: 167 } +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "entry_vert" + entry_point_id: 2 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "tex" + - *db1 # "ubo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "tex" + - *db1 # "ubo" + input_variable_count: 2, + input_variables: + - *iv0 # "iUV" + - *iv1 # "pos" + output_variable_count: 2, + output_variables: + - *iv3 # "" + - *iv4 # "oUV" + push_constant_count: 2, + push_constants: + - *bv4 # "push_constant_vert" + - *bv6 # "push_constant_frag" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/multi_entrypoint/rebuild.sh b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/rebuild.sh new file mode 100755 index 0000000..25debd8 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/multi_entrypoint/rebuild.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Creates multi_entrypoint.spv from multi_entrypoint.glsl and +# multi_entrypoint.spv.dis.diff +glslc -fshader-stage=vert multi_entrypoint.glsl -o multi_entrypoint.spv +spirv-dis multi_entrypoint.spv > multi_entrypoint.spv.dis +patch multi_entrypoint.spv.dis multi_entrypoint.spv.dis.diff +spirv-as multi_entrypoint.spv.dis -o multi_entrypoint.spv diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv b/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv new file mode 100644 index 0000000..4310a67 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv.yaml new file mode 100644 index 0000000..3b4aa8d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/non_zero_block_offset.spv.yaml @@ -0,0 +1,350 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 16 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 22 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 22 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 17 + op: 30 + type_name: "uPushConstant" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 + - &td4 + id: 7 + op: 23 + type_name: + struct_member_name: "gl_Position" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 6 + op: 22 + type_name: + struct_member_name: "gl_PointSize" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_ClipDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td7 + id: 10 + op: 28 + type_name: + struct_member_name: "gl_CullDistance" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + - &td8 + id: 11 + op: 30 + type_name: "gl_PerVertex" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td4 + - *td5 + - *td6 + - *td7 +all_block_variables: + - &bv0 + name: "a" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "pc" + offset: 4 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv1 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 1 # PointSize + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv2 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 3 # ClipDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td6 + word_offset: { location: 0 } + - &iv3 + spirv_id: 0 + name: + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4 # CullDistance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [1,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td7 + word_offset: { location: 0 } + - &iv4 + spirv_id: 13 + name: "" + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000011 # BUILT_IN BLOCK + built_in: 0, 1, 3, 4 # [Position, PointSize, ClipDistance, CullDistance] + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + format: 0 # VK_FORMAT_UNDEFINED + type_description: *td8 + word_offset: { location: 0 } +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv4 # "" + push_constant_count: 1, + push_constants: + - *bv3 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.slang b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.slang new file mode 100644 index 0000000..627ef22 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.slang @@ -0,0 +1,15 @@ +RWStructuredBuffer result; + +struct Data{ + int a; + int* b; + int c; +}; +[[vk::push_constant]] Data pc; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + result[0] = pc.b[2] + pc.c; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv new file mode 100755 index 0000000..39d94e8 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv.yaml new file mode 100644 index 0000000..d2820b1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct.spv.yaml @@ -0,0 +1,256 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 9 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 5 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 14 + op: 32 + type_name: + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 5 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 13 + op: 30 + type_name: "Data_std430" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td2 + - *td3 + - *td4 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "result" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "b" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "c" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv2 + - *bv3 + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "result" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "result" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 103, set: 107 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "result" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "result" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv5 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.slang b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.slang new file mode 100644 index 0000000..c674c9c --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.slang @@ -0,0 +1,20 @@ +RWStructuredBuffer result; + +struct Data2{ + int x; + int* y; +}; + +struct Data{ + int a; + Data2* b; + int c; +}; +[[vk::push_constant]] Data pc; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + result[0] = pc.b[2].y[2] + pc.c; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv new file mode 100755 index 0000000..ba1348a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv.yaml new file mode 100644 index 0000000..27126e2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/pointer_in_struct_2.spv.yaml @@ -0,0 +1,360 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 9 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 5 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 5 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 24 + op: 32 + type_name: + struct_member_name: "y" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 15 + op: 32 + type_name: "Data2_natural" + struct_member_name: "b" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 + - &td6 + id: 5 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 13 + op: 30 + type_name: "Data_std430" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td2 + - *td5 + - *td6 + - &td8 + id: 5 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 24 + op: 32 + type_name: + struct_member_name: "y" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "result" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td8 + - &bv4 + name: "y" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv5 + name: "b" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv3 + - *bv4 + type_description: *td5 + - &bv6 + name: "c" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 20 + padded_size: 20 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv2 + - *bv5 + - *bv6 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "result" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "result" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 117, set: 121 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "result" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "result" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv7 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.glsl b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.glsl new file mode 100644 index 0000000..2717638 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.glsl @@ -0,0 +1,23 @@ +#version 460 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer Node { uint x; }; + +struct Bar { + uint t; + uint s; +}; + +layout(push_constant, std430) uniform foo { + uint a; + uint b[4]; + Bar bar; + Node node; +}; + +layout(set=0, binding=0) buffer SSBO { + uint out_value; +}; + +// Everything should be marked as UNUSED +void main() {} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv new file mode 100644 index 0000000..4429cf5 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv.yaml new file mode 100644 index 0000000..f8647d3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_0.spv.yaml @@ -0,0 +1,413 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "out_value" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 15 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 8 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 6 + op: 21 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 6 + op: 21 + type_name: + struct_member_name: "s" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 9 + op: 30 + type_name: "Bar" + struct_member_name: "bar" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td4 + - *td5 + - &td7 + id: 6 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 10 + op: 32 + type_name: "Node" + struct_member_name: "node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 11 + op: 30 + type_name: "foo" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td2 + - *td3 + - *td6 + - *td8 + - &td10 + id: 6 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "out_value" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "b" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "t" + offset: 0 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "s" + offset: 4 + absolute_offset: 24 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "bar" + offset: 20 + absolute_offset: 20 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv4 + - *bv5 + type_description: *td6 + - &bv7 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv8 + name: "node" + offset: 32 + absolute_offset: 32 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv7 + type_description: *td8 + - &bv9 + name: "" + offset: 0 + absolute_offset: 0 + size: 40 + padded_size: 40 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv2 + - *bv3 + - *bv6 + - *bv8 + type_description: *td9 +all_descriptor_bindings: + - &db0 + spirv_id: 17 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "" + array: { dims_count: 0, dims: [] } + accessed: 0 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 174, set: 178 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv9 # "" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.glsl b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.glsl new file mode 100644 index 0000000..2d3134d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.glsl @@ -0,0 +1,27 @@ +#version 460 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer Node { uint x; }; + +struct Bar { + uint t; + uint s; +}; + +layout(push_constant, std430) uniform foo { + uint a; + uint b[4]; + Bar bar; + Node node; +}; + +layout(set=0, binding=0) buffer SSBO { + uint out_value; +}; + +void main() { + out_value = a; + out_value = b[1]; + out_value = bar.s; + out_value = node.x; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv new file mode 100644 index 0000000..0d1922f Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv.yaml new file mode 100644 index 0000000..c2fdd17 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_1.spv.yaml @@ -0,0 +1,413 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "out_value" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 13 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 6 + op: 21 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 6 + op: 21 + type_name: + struct_member_name: "s" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 14 + op: 30 + type_name: "Bar" + struct_member_name: "bar" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td4 + - *td5 + - &td7 + id: 6 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 15 + op: 32 + type_name: "Node" + struct_member_name: "node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 16 + op: 30 + type_name: "foo" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td2 + - *td3 + - *td6 + - *td8 + - &td10 + id: 6 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "out_value" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "b" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "t" + offset: 0 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "s" + offset: 4 + absolute_offset: 24 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "bar" + offset: 20 + absolute_offset: 20 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv4 + - *bv5 + type_description: *td6 + - &bv7 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td10 + - &bv8 + name: "node" + offset: 32 + absolute_offset: 32 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv7 + type_description: *td8 + - &bv9 + name: "" + offset: 0 + absolute_offset: 0 + size: 40 + padded_size: 40 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv2 + - *bv3 + - *bv6 + - *bv8 + type_description: *td9 +all_descriptor_bindings: + - &db0 + spirv_id: 9 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 129, set: 133 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv9 # "" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.slang b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.slang new file mode 100644 index 0000000..4e45054 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.slang @@ -0,0 +1,24 @@ +RWStructuredBuffer result; + +struct Bar{ + uint t; + uint s; +}; + +struct Data{ + uint a; + uint b[4]; + Bar bar; + uint* node; +}; +[[vk::push_constant]] Data pc; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + result[0] += pc.a; + result[0] += pc.b[1]; + result[0] += pc.bar.s; + result[0] += pc.node[3]; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv new file mode 100755 index 0000000..523593a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv.yaml new file mode 100644 index 0000000..baebaef --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_2.spv.yaml @@ -0,0 +1,396 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 10 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 7 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 16 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 15 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 7 + op: 21 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 7 + op: 21 + type_name: + struct_member_name: "s" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 18 + op: 30 + type_name: "Bar_std430" + struct_member_name: "bar" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td5 + - *td6 + - &td8 + id: 19 + op: 32 + type_name: + struct_member_name: "node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 14 + op: 30 + type_name: "Data_std430" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 4 + members: + - *td2 + - *td4 + - *td7 + - *td8 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "result" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "data" + offset: 0 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "b" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 + - &bv5 + name: "t" + offset: 0 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "s" + offset: 4 + absolute_offset: 24 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "bar" + offset: 20 + absolute_offset: 20 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv5 + - *bv6 + type_description: *td7 + - &bv8 + name: "node" + offset: 32 + absolute_offset: 32 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 40 + padded_size: 40 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv2 + - *bv4 + - *bv7 + - *bv8 + type_description: *td9 +all_descriptor_bindings: + - &db0 + spirv_id: 13 + name: "result" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "result" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 133, set: 137 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "result" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "result" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv9 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.slang b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.slang new file mode 100644 index 0000000..2e97a55 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.slang @@ -0,0 +1,30 @@ +RWStructuredBuffer result; + +struct Foo{ + uint s; + uint t; +}; + +struct Bar{ + uint x_unused; + uint y; +}; + +struct Data{ + uint a_unused; + uint b[4]; + uint c; + uint d_unused[4]; + Foo* foo_unused; + Bar* bar; +}; +[[vk::push_constant]] Data pc; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + result[0] += pc.c; + result[0] += pc.b[1]; + result[0] += pc.bar->y; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv new file mode 100644 index 0000000..2ba4715 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv.yaml b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv.yaml new file mode 100644 index 0000000..04c1060 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/push_constants/push_constant_basic_3.spv.yaml @@ -0,0 +1,639 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 10 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 7 + op: 21 + type_name: + struct_member_name: "a_unused" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 16 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 15 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 7 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 16 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 15 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "d_unused" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 + - &td8 + id: 7 + op: 21 + type_name: + struct_member_name: "s" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 7 + op: 21 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 19 + op: 32 + type_name: "Foo_natural" + struct_member_name: "foo_unused" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td8 + - *td9 + - &td11 + id: 7 + op: 21 + type_name: + struct_member_name: "x_unused" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 7 + op: 21 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 21 + op: 32 + type_name: "Bar_natural" + struct_member_name: "bar" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td11 + - *td12 + - &td14 + id: 14 + op: 30 + type_name: "Data_std430" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 6 + members: + - *td2 + - *td4 + - *td5 + - *td7 + - *td10 + - *td13 + - &td15 + id: 7 + op: 21 + type_name: + struct_member_name: "s" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 7 + op: 21 + type_name: + struct_member_name: "t" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 7 + op: 21 + type_name: + struct_member_name: "x_unused" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td18 + id: 7 + op: 21 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "result" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "a_unused" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "data" + offset: 0 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "b" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv3 + type_description: *td4 + - &bv5 + name: "c" + offset: 20 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "data" + offset: 0 + absolute_offset: 24 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "d_unused" + offset: 24 + absolute_offset: 24 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv6 + type_description: *td7 + - &bv8 + name: "s" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv9 + name: "t" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv10 + name: "foo_unused" + offset: 40 + absolute_offset: 40 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv8 + - *bv9 + type_description: *td10 + - &bv11 + name: "x_unused" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td17 + - &bv12 + name: "y" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td18 + - &bv13 + name: "bar" + offset: 48 + absolute_offset: 48 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv11 + - *bv12 + type_description: *td13 + - &bv14 + name: "pc" + offset: 0 + absolute_offset: 0 + size: 56 + padded_size: 56 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 6 + members: + - *bv2 + - *bv4 + - *bv5 + - *bv7 + - *bv10 + - *bv13 + type_description: *td14 +all_descriptor_bindings: + - &db0 + spirv_id: 13 + name: "result" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "result" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 161, set: 165 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "result" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "result" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 1, + push_constants: + - *bv14 # "pc" + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/compile_shaders.sh b/lib/All/SPIRV-Reflect/tests/raytrace/compile_shaders.sh new file mode 100644 index 0000000..79f1afb --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/compile_shaders.sh @@ -0,0 +1,40 @@ +#!/bin/sh +if [ "$#" -ne 1 ]; then + echo -e "error: missing path to DXC" + echo -e "\nUsage:\n compile_shaders.sh \n" +fi + +DXC_EXE=$1 + +echo "Using DXC at $DXC_EXE" + +function exec_dxc { + echo $1 + eval $1 +} + +#exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T cs_6_5 -E CS -Fo rayquery_assign.cs.spv rayquery_assign.cs.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T cs_6_5 -E main -Fo rayquery_equal.cs.spv rayquery_equal.cs.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T ds_6_5 -E main -Fo rayquery_init_ds.spv rayquery_init_ds.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T gs_6_5 -E main -Fo rayquery_init_gs.spv rayquery_init_gs.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T hs_6_5 -E main -Fo rayquery_init_hs.spv rayquery_init_hs.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T ps_6_5 -E main -Fo rayquery_init_ps.spv rayquery_init_ps.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rahit.spv rayquery_init_rahit.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rcall.spv rayquery_init_rcall.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rchit.spv rayquery_init_rchit.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rgen.spv rayquery_init_rgen.hlsl" +#exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rint.spv rayquery_init_rint.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_rmiss.spv rayquery_init_rmiss.hlsl" +#exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_init_vs.spv rayquery_init_vs.hlsl" +#exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo rayquery_tryAllOps.cs.spv rayquery_tryAllOps.cs.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T cs_6_4 -E main -Fo raytracing.acceleration-structure.spv raytracing.acceleration-structure.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.khr.closesthit.spv raytracing.khr.closesthit.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T cs_6_4 -E main -Fo raytracing.nv.acceleration-structure.spv raytracing.nv.acceleration-structure.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing -Fo raytracing.nv.anyhit.spv raytracing.nv.anyhit.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.callable.spv raytracing.nv.callable.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.closesthit.spv raytracing.nv.closesthit.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.enum.spv raytracing.nv.enum.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.intersection.spv raytracing.nv.intersection.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing -Fo raytracing.nv.library.spv raytracing.nv.library.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.miss.spv raytracing.nv.miss.hlsl" +exec_dxc "$DXC_EXE -spirv -fspv-target-env=vulkan1.2 -T lib_6_3 -Fo raytracing.nv.raygen.spv raytracing.nv.raygen.hlsl" diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_assign.cs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_assign.cs.hlsl new file mode 100644 index 0000000..52bce21 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_assign.cs.hlsl @@ -0,0 +1,9 @@ +// Run: %dxc -T cs_6_5 -E CS -fspv-target-env=vulkan1.2 +// CHECK: error: store value of type 'RayQuery' is unsupported + +[numThreads(1,1,1)] +void CS() +{ + RayQuery q; + RayQuery b = q; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.hlsl new file mode 100644 index 0000000..fc27aa6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.hlsl @@ -0,0 +1,35 @@ +// Run: %dxc -T cs_6_5 -E main -fspv-target-env=vulkan1.2 +RaytracingAccelerationStructure g_topLevel : register(t0, space0); +RWTexture2D g_output : register(u1, space0); + +[numthreads(64, 1, 1)] +void main(uint2 launchIndex: SV_DispatchThreadID) +{ + float3 T = (float3)0; + float sampleCount = 0; + RayDesc ray; + + ray.Origin = float3(0, 0, 0); + ray.Direction = float3(0, 1, 0); + ray.TMin = 0.0; + ray.TMax = 1000.0; + + RayQuery q; + + q.TraceRayInline(g_topLevel, 0, 0xff, ray); +// CHECK: [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryKHR Function + q.Proceed(); +// CHECK: OpRayQueryProceedKHR %bool [[rayquery]] + if(q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) +// CHECK: [[status:%\d+]] = OpRayQueryGetIntersectionTypeKHR %uint [[rayquery]] %uint_1 +// CHECK: OpIEqual %bool [[status]] %uint_1 + { + T += float3(1, 0, 1); + } + else + { + T += float3(0, 1, 0); + } + + g_output[launchIndex] += float4(T, 1); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv new file mode 100644 index 0000000..545b1e7 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv.yaml new file mode 100644 index 0000000..b99b7a9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_equal.cs.spv.yaml @@ -0,0 +1,170 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 5 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "g_topLevel" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 87, set: 83 } + - &db1 + spirv_id: 3 + name: "g_output" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 3 # VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + resource_type: 8 # UAV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 2, image_format: 1 } # dim=2D image_format=Rgba32f + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 95, set: 91 } +all_interface_variables: + - &iv0 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td2 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 650 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "g_topLevel" + - *db1 # "g_output" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "g_topLevel" + - *db1 # "g_output" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.hlsl new file mode 100644 index 0000000..17ab72a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.hlsl @@ -0,0 +1,63 @@ +// RUN: %dxc -T ds_6_5 -E main -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_query" + +struct VSSceneIn { + float3 pos : POSITION; +}; + +struct PSSceneIn { + float4 pos : SV_Position; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Simple forwarding Tessellation shaders + +struct HSPerVertexData { + // This is just the original vertex verbatim. In many real life cases this would be a + // control point instead + PSSceneIn v; +}; + +struct HSPerPatchData { + // We at least have to specify tess factors per patch + // As we're tesselating triangles, there will be 4 tess factors + // In real life case this might contain face normal, for example + float edges[3] : SV_TessFactor; + float inside : SV_InsideTessFactor; +}; + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +// domain shader that actually outputs the triangle vertices +[domain("tri")] PSSceneIn main(const float3 bary + : SV_DomainLocation, + const OutputPatch patch, + const HSPerPatchData perPatchData) { + PSSceneIn v; + v.pos = patch[0].v.pos * bary.x + patch[1].v.pos * bary.y + patch[2].v.pos * bary.z + perPatchData.edges[1]; + + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); + + return v; +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv new file mode 100644 index 0000000..7a00e47 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv.yaml new file mode 100644 index 0000000..e2e429f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ds.spv.yaml @@ -0,0 +1,262 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 8 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 16 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 25 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + - &td3 + id: 28 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 30 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + - &td5 + id: 24 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 104, set: 100 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000410 # BUILT_IN PATCH + built_in: 13 # TessCoord + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv2 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000410 # BUILT_IN PATCH + built_in: 11 # TessLevelOuter + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv3 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000410 # BUILT_IN PATCH + built_in: 12 # TessLevelInner + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv4 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 650 + spirv_execution_model: 2 # TessellationEvaluation + shader_stage: 0x00000004 # DS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 4, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + output_variable_count: 1, + output_variables: + - *iv4 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.hlsl new file mode 100644 index 0000000..30b8d5a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.hlsl @@ -0,0 +1,43 @@ +// RUN: %dxc -T gs_6_5 -E main -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_query + +struct Out +{ + float4 pos : SV_Position; +}; + +struct Empty{}; + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +[maxvertexcount(3)] +void main(line Empty e[4], inout PointStream OutputStream0) +{ + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); + + Out output = (Out)0; + + OutputStream0.Append(output); + OutputStream0.RestartStrip(); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv new file mode 100644 index 0000000..6021063 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv.yaml new file mode 100644 index 0000000..724d8b8 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_gs.spv.yaml @@ -0,0 +1,118 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 10 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 86, set: 82 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 650 + spirv_execution_model: 3 # Geometry + shader_stage: 0x00000008 # GS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.hlsl new file mode 100644 index 0000000..3f481c4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.hlsl @@ -0,0 +1,75 @@ +// Run: %dxc -T hs_6_5 -E main -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayQueryKHR +// CHECK: OpCapability RayTraversalPrimitiveCullingKHR +// CHECK: OpExtension "SPV_KHR_ray_query" + +#define MAX_POINTS 3 + +// Input control point +struct VS_CONTROL_POINT_OUTPUT +{ + float3 vPosition : WORLDPOS; +}; + +// Output control point +struct CONTROL_POINT +{ + float3 vPosition : BEZIERPOS; +}; + +// Output patch constant data. +struct HS_CONSTANT_DATA_OUTPUT +{ + float Edges[4] : SV_TessFactor; + float Inside[2] : SV_InsideTessFactor; +}; + +// Patch Constant Function +HS_CONSTANT_DATA_OUTPUT mainConstant(InputPatch ip) { + HS_CONSTANT_DATA_OUTPUT Output; + + // Must initialize Edges and Inside; otherwise HLSL validation will fail. + Output.Edges[0] = 1.0; + Output.Edges[1] = 2.0; + Output.Edges[2] = 3.0; + Output.Edges[3] = 4.0; + Output.Inside[0] = 5.0; + Output.Inside[1] = 6.0; + + return Output; +} + + + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +[outputcontrolpoints(MAX_POINTS)] +[patchconstantfunc("mainConstant")] +CONTROL_POINT main(InputPatch ip, uint cpid : SV_OutputControlPointID) { +// CHECK: %rayQueryKHR = OpTypeRayQueryKHR +// CHECK: %_ptr_Function_rayQueryKHR = OpTypePointer Function %rayQueryKHR +// CHECK: [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryKHR Function + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_517 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_259 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); + CONTROL_POINT result; + return result; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv new file mode 100644 index 0000000..441d166 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv.yaml new file mode 100644 index 0000000..d55986f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_hs.spv.yaml @@ -0,0 +1,245 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 8 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 30 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000108 # ARRAY VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + - &td2 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 35 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + - &td4 + id: 37 + op: 28 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 122, set: 118 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: "in.var.WORLDPOS" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 110 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 8 # InvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } + - &iv2 + spirv_id: 5 + name: "out.var.BEZIERPOS" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 114 } + - &iv3 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000410 # BUILT_IN PATCH + built_in: 11 # TessLevelOuter + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv4 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000410 # BUILT_IN PATCH + built_in: 12 # TessLevelInner + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 650 + spirv_execution_model: 1 # TessellationControl + shader_stage: 0x00000002 # HS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 2, + input_variables: + - *iv0 # "in.var.WORLDPOS" + - *iv1 # + output_variable_count: 3, + output_variables: + - *iv2 # "out.var.BEZIERPOS" + - *iv3 # + - *iv4 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.hlsl new file mode 100644 index 0000000..dfb4ea6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.hlsl @@ -0,0 +1,33 @@ +// RUN: %dxc -E main -T ps_6_5 -fspv-target-env=vulkan1.2 + +// RUN: %dxc -T gs_6_5 -E main +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_query + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +uint4 main() : SV_Target +{ + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); + return float4(1.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv new file mode 100644 index 0000000..9aa3879 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv.yaml new file mode 100644 index 0000000..5333b17 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_ps.spv.yaml @@ -0,0 +1,118 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 10 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 82, set: 78 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: "out.var.SV_Target" + location: 0 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 107 # VK_FORMAT_R32G32B32A32_UINT + type_description: *td1 + word_offset: { location: 74 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 650 + spirv_execution_model: 4 # Fragment + shader_stage: 0x00000010 # PS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 1, + output_variables: + - *iv0 # "out.var.SV_Target" + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.hlsl new file mode 100644 index 0000000..6e98e4b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.hlsl @@ -0,0 +1,42 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct Payload +{ + float4 color; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; + +[shader("anyhit")] +void main(inout Payload MyPayload, in Attribute MyAttr) { + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv new file mode 100644 index 0000000..9527bd0 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv.yaml new file mode 100644 index 0000000..0af2db0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rahit.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 80, set: 76 } +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5315 # AnyHitKHR + shader_stage: 0x00000200 # ANY_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.hlsl new file mode 100644 index 0000000..641ccc0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.hlsl @@ -0,0 +1,37 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct Payload +{ + float4 color; +}; + +[shader("miss")] +void main(inout Payload MyPayload) { + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv new file mode 100644 index 0000000..0040612 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv.yaml new file mode 100644 index 0000000..47bc5df --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rcall.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 80, set: 76 } +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5317 # MissKHR + shader_stage: 0x00000800 # MISS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.hlsl new file mode 100644 index 0000000..5ef7e60 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.hlsl @@ -0,0 +1,42 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct Payload +{ + float4 color; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; + +[shader("closesthit")] +void main(inout Payload MyPayload, in Attribute MyAttr) { + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv new file mode 100644 index 0000000..c36f5cf Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv.yaml new file mode 100644 index 0000000..b4a054e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rchit.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 80, set: 76 } +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5316 # ClosestHitKHR + shader_stage: 0x00000400 # CLOSEST_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.hlsl new file mode 100644 index 0000000..e83ad75 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.hlsl @@ -0,0 +1,42 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +// CHECK-COUNT-1: [[rs:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct Payload +{ + float4 color; +}; + + +[shader("raygeneration")] +void main() { + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +// CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0 + TraceRay(AccelerationStructure, 0x0, 0xff, 0, 1, 0, ray, myPayload); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv new file mode 100644 index 0000000..295815e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv.yaml new file mode 100644 index 0000000..53df793 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rgen.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 84, set: 80 } +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5313 # RayGenerationKHR + shader_stage: 0x00000100 # RAYGEN + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rint.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rint.hlsl new file mode 100644 index 0000000..c385e79 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rint.hlsl @@ -0,0 +1,41 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct CallData +{ + float4 data; +}; + +[shader("callable")] +void main() { + + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); + + Attribute myHitAttribute = { float2(0.0f,0.0f) }; +// CHECK: OpReportIntersectionKHR %bool %float_0 %uint_0 + ReportHit(0.0f, 0U, myHitAttribute); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.hlsl new file mode 100644 index 0000000..641ccc0 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.hlsl @@ -0,0 +1,37 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_NON_OPAQUE,0xFF,ray); +} + +struct Payload +{ + float4 color; +}; + +[shader("miss")] +void main(inout Payload MyPayload) { + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_1 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + q.TraceRayInline(AccelerationStructure,RAY_FLAG_FORCE_OPAQUE, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_3 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv new file mode 100644 index 0000000..0040612 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv.yaml new file mode 100644 index 0000000..47bc5df --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_rmiss.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 4 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "AccelerationStructure" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 80, set: 76 } +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5317 # MissKHR + shader_stage: 0x00000800 # MISS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "AccelerationStructure" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "AccelerationStructure" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_vs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_vs.hlsl new file mode 100644 index 0000000..c021a2d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_init_vs.hlsl @@ -0,0 +1,45 @@ +// Run: %dxc -T vs_6_5 -E main -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayQueryKHR +// CHECK: OpCapability RayTraversalPrimitiveCullingKHR +// CHECK: OpExtension "SPV_KHR_ray_query" + + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RWByteAddressBuffer log : register(u0); + +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} + + +void DoSomething() +{ + log.Store(0,1); +} + +void doInitialize(RayQuery query, RayDesc ray) +{ + query.TraceRayInline(AccelerationStructure,RAY_FLAG_NONE,0xFF,ray); +} + + +void main() +{ +// CHECK: %rayQueryKHR = OpTypeRayQueryKHR +// CHECK: %_ptr_Function_rayQueryKHR = OpTypePointer Function %rayQueryKHR +// CHECK: [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryKHR Function + RayQuery q; + RayDesc ray = MakeRayDesc(); +// CHECK: [[accel:%\d+]] = OpLoad %accelerationStructureNV %AccelerationStructure +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_517 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + + q.TraceRayInline(AccelerationStructure,RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES, 0xFF, ray); +// CHECK: OpRayQueryInitializeKHR [[rayquery]] [[accel]] %uint_5 %uint_255 {{%\d+}} %float_0 {{%\d+}} %float_9999 + doInitialize(q, ray); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_tryAllOps.cs.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_tryAllOps.cs.hlsl new file mode 100644 index 0000000..43bcc77 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/rayquery_tryAllOps.cs.hlsl @@ -0,0 +1,206 @@ +// Run: dxc -T cs_6_5 -E CS -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayQueryKHR +// CHECK: OpExtension "SPV_KHR_ray_query" + +RaytracingAccelerationStructure AccelerationStructure : register(t0); +RWByteAddressBuffer log : register(u0); + +RayDesc MakeRayDesc() +{ + RayDesc desc; + desc.Origin = float3(0,0,0); + desc.Direction = float3(1,0,0); + desc.TMin = 0.0f; + desc.TMax = 9999.0; + return desc; +} + +void DoSomething() +{ + log.Store(0,1); +} + +[numThreads(1,1,1)] +void CS() +{ + RayQuery q; + RayDesc ray = MakeRayDesc(); + q.TraceRayInline(AccelerationStructure,RAY_FLAG_NONE,0xFF,ray); + float4x3 mat4x3; + float3x4 mat3x4; +// CHECK: [[rayquery:%\d+]] = OpVariable %_ptr_Function_rayQueryKHR Function +// CHECK: OpRayQueryProceedKHR %bool [[rayquery]] + while(q.Proceed()) + { +// CHECK: OpRayQueryGetIntersectionTypeKHR %uint [[rayquery]] %uint_0 + switch(q.CandidateType()) + { + case CANDIDATE_NON_OPAQUE_TRIANGLE: + q.Abort(); +// CHECK: OpRayQueryGetIntersectionObjectToWorldKHR %mat4v3float [[rayquery]] %uint_0 + mat3x4 = q.CandidateObjectToWorld3x4(); + mat4x3 = q.CandidateObjectToWorld4x3(); +// CHECK: OpRayQueryConfirmIntersectionKHR [[rayquery]] + q.CommitNonOpaqueTriangleHit(); +// CHECK: OpRayQueryGetIntersectionFrontFaceKHR %bool [[rayquery]] %uint_0 + if(q.CandidateTriangleFrontFace()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionBarycentricsKHR %v2float [[rayquery]] %uint_0 + if(q.CandidateTriangleBarycentrics().x == 0) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionGeometryIndexKHR %uint [[rayquery]] %uint_0 + if(q.CandidateGeometryIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceCustomIndexKHR %uint [[rayquery]] %uint_0 + if(q.CandidateInstanceID()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceIdKHR %uint [[rayquery]] %uint_0 + if(q.CandidateInstanceIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionObjectRayDirectionKHR %v3float [[rayquery]] %uint_0 + if(q.CandidateObjectRayDirection().x) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionObjectRayOriginKHR %v3float [[rayquery]] %uint_0 + if(q.CandidateObjectRayOrigin().y) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionPrimitiveIndexKHR %uint [[rayquery]] %uint_0 + if(q.CandidatePrimitiveIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionTKHR %float [[rayquery]] %uint_0 + if(q.CandidateTriangleRayT()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %uint [[rayquery]] %uint_0 + if(q.CandidateInstanceContributionToHitGroupIndex()) + { + DoSomething(); + } + break; + case CANDIDATE_PROCEDURAL_PRIMITIVE: + { +// CHECK: OpRayQueryGetIntersectionWorldToObjectKHR %mat4v3float [[rayquery]] %uint_0 + mat3x4 = q.CandidateWorldToObject3x4(); + mat4x3 = q.CandidateWorldToObject4x3(); +// CHECK: OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %bool + if(q.CandidateProceduralPrimitiveNonOpaque()) + { + DoSomething(); + } + float t = 0.5; +// CHECK: OpRayQueryGenerateIntersectionKHR [[rayquery]] %float_0_5 + q.CommitProceduralPrimitiveHit(t); + q.Abort(); + break; + } + } + } + if(mat3x4[0][0] == mat4x3[0][0]) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionTypeKHR %uint [[rayquery]] %uint_1 + switch(q.CommittedStatus()) + { + case COMMITTED_NOTHING: +// CHECK: OpRayQueryGetIntersectionObjectToWorldKHR %mat4v3float [[rayquery]] %uint_1 + mat3x4 = q.CommittedObjectToWorld3x4(); + mat4x3 = q.CommittedObjectToWorld4x3(); + break; + case COMMITTED_TRIANGLE_HIT: +// CHECK: OpRayQueryGetIntersectionWorldToObjectKHR %mat4v3float [[rayquery]] %uint_1 + mat3x4 = q.CommittedWorldToObject3x4(); + mat4x3 = q.CommittedWorldToObject4x3(); +// CHECK: OpRayQueryGetIntersectionFrontFaceKHR %bool [[rayquery]] %uint_1 + if(q.CommittedTriangleFrontFace()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionBarycentricsKHR %v2float [[rayquery]] %uint_1 + if(q.CommittedTriangleBarycentrics().y == 0) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %uint [[rayquery]] %uint_1 + if(q.CommittedInstanceContributionToHitGroupIndex()) + { + DoSomething(); + } + break; + case COMMITTED_PROCEDURAL_PRIMITIVE_HIT: +// CHECK: OpRayQueryGetIntersectionGeometryIndexKHR %uint [[rayquery]] %uint_1 + if(q.CommittedGeometryIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceCustomIndexKHR %uint [[rayquery]] %uint_1 + if(q.CommittedInstanceID()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionInstanceIdKHR %uint [[rayquery]] %uint_1 + if(q.CommittedInstanceIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionObjectRayDirectionKHR %v3float [[rayquery]] %uint_1 + if(q.CommittedObjectRayDirection().z) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionObjectRayOriginKHR %v3float [[rayquery]] %uint_1 + if(q.CommittedObjectRayOrigin().x) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionPrimitiveIndexKHR %uint [[rayquery]] %uint_1 + if(q.CommittedPrimitiveIndex()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetIntersectionTKHR %float [[rayquery]] %uint_1 + if(q.CommittedRayT()) + { + DoSomething(); + } + break; + } + if(mat3x4[0][0] == mat4x3[0][0]) + { + DoSomething(); + } +// CHECK: OpRayQueryGetRayFlagsKHR %uint [[rayquery]] + if(q.RayFlags()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetRayTMinKHR %float [[rayquery]] + if(q.RayTMin()) + { + DoSomething(); + } +// CHECK: OpRayQueryGetWorldRayDirectionKHR %v3float [[rayquery]] + float3 o = q.WorldRayDirection(); +// CHECK: OpRayQueryGetWorldRayOriginKHR %v3float [[rayquery]] + float3 d = q.WorldRayOrigin(); + if(o.x == d.z) + { + DoSomething(); + } +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.hlsl new file mode 100644 index 0000000..92c90c7 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.hlsl @@ -0,0 +1,10 @@ +// Run: %dxc -E main -T cs_6_4 -fspv-target-env=vulkan1.2 + +// CHECK: OpCapability RayTracingKHR + +// CHECK: %accelerationStructureNV = OpTypeAccelerationStructureKHR + +RaytracingAccelerationStructure test_bvh; + +[numthreads(1, 1, 1)] +void main() {} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv new file mode 100644 index 0000000..19c9d5d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv.yaml new file mode 100644 index 0000000..2af6c30 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.acceleration-structure.spv.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 640 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.hlsl new file mode 100644 index 0000000..e70b250 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.hlsl @@ -0,0 +1,91 @@ +// Run: %dxc -T lib_6_3 -fspv-target-env=vulkan1.2 +// CHECK: OpCapability RayTracingKHR +// CHECK: OpExtension "SPV_KHR_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV +// CHECK: OpDecorate %gl_InstanceID BuiltIn InstanceId +// CHECK: OpDecorate [[g:%\d+]] BuiltIn InstanceCustomIndexNV +// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId +// CHECK: OpDecorate [[h:%\d+]] BuiltIn ObjectRayOriginNV +// CHECK: OpDecorate [[i:%\d+]] BuiltIn ObjectRayDirectionNV +// CHECK: OpDecorate [[j:%\d+]] BuiltIn ObjectToWorldNV +// CHECK: OpDecorate [[k:%\d+]] BuiltIn WorldToObjectNV +// CHECK: OpDecorate [[l:%\d+]] BuiltIn HitKindNV +// CHECK: OpDecorate [[m:%\d+]] BuiltIn RayGeometryIndexKHR + +// CHECK: OpTypePointer IncomingRayPayloadNV %Payload +struct Payload +{ + float4 color; +}; + +struct CallData +{ + float4 data; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; + +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + +[shader("closesthit")] +void main(inout Payload MyPayload, in Attribute MyAttr) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: [[matotw:%\d+]] = OpLoad %mat4v3float [[j]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matotw]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: [[matwto:%\d+]] = OpLoad %mat4v3float [[k]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matwto]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); +// CHECK: OpLoad %uint [[l]] + uint _16 = HitKind(); +// CHECK: OpLoad %uint [[m]] + uint _17 = GeometryIndex(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + CallData myCallData = { float4(0.0f,0.0f,0.0f,0.0f) }; +// CHECK: OpStore %myPayload {{%\d+}} + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; +// CHECK: OpTraceRayKHR {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %myPayload + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); +// CHECK: OpExecuteCallableKHR %uint_0 %myCallData + CallShader(0, myCallData); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv new file mode 100644 index 0000000..20abb81 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv.yaml new file mode 100644 index 0000000..3b547d2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.khr.closesthit.spv.yaml @@ -0,0 +1,452 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 21 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 38 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 26 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 24 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 31 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 43 + op: 24 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "rs" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 167, set: 163 } +all_interface_variables: + - &iv0 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv4 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv5 + spirv_id: 9 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv6 + spirv_id: 10 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv7 + spirv_id: 11 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5327 # InInstanceCustomIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv8 + spirv_id: 12 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv9 + spirv_id: 13 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5323 # InObjectRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv10 + spirv_id: 14 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5324 # InObjectRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv11 + spirv_id: 15 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5330 # InObjectToWorldKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv12 + spirv_id: 16 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5331 # InWorldToObjectKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv13 + spirv_id: 17 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5333 # InHitKindKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv14 + spirv_id: 18 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5352 # InRayGeometryIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5316 # ClosestHitKHR + shader_stage: 0x00000400 # CLOSEST_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "rs" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "rs" + input_variable_count: 15, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + - *iv9 # + - *iv10 # + - *iv11 # + - *iv12 # + - *iv13 # + - *iv14 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.hlsl new file mode 100644 index 0000000..e16491e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.hlsl @@ -0,0 +1,11 @@ +// Run: %dxc -E main -T cs_6_4 -fspv-target-env=vulkan1.2 -fspv-extension=SPV_NV_ray_tracing + +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" + +// CHECK: %accelerationStructureNV = OpTypeAccelerationStructureKHR + +RaytracingAccelerationStructure test_bvh; + +[numthreads(1, 1, 1)] +void main() {} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv new file mode 100644 index 0000000..19c9d5d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv.yaml new file mode 100644 index 0000000..2af6c30 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.acceleration-structure.spv.yaml @@ -0,0 +1,27 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 640 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.hlsl new file mode 100644 index 0000000..a5def99 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.hlsl @@ -0,0 +1,82 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV +// CHECK: OpDecorate %gl_InstanceID BuiltIn InstanceId +// CHECK: OpDecorate [[g:%\d+]] BuiltIn InstanceCustomIndexNV +// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId +// CHECK: OpDecorate [[h:%\d+]] BuiltIn ObjectRayOriginNV +// CHECK: OpDecorate [[i:%\d+]] BuiltIn ObjectRayDirectionNV +// CHECK: OpDecorate [[j:%\d+]] BuiltIn ObjectToWorldNV +// CHECK: OpDecorate [[k:%\d+]] BuiltIn WorldToObjectNV +// CHECK: OpDecorate [[l:%\d+]] BuiltIn HitKindNV + +// CHECK: OpTypePointer IncomingRayPayloadNV %Payload +struct Payload +{ + float4 color; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; + +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + +[shader("anyhit")] +void main(inout Payload MyPayload, in Attribute MyAttr) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: [[matotw:%\d+]] = OpLoad %mat4v3float [[j]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matotw]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: [[matwto:%\d+]] = OpLoad %mat4v3float [[k]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matwto]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); +// CHECK: OpLoad %uint [[l]] + uint _16 = HitKind(); + + if (_16 == 1U) { +// CHECK: [[payloadread0:%\d+]] = OpLoad %Payload %MyPayload_0 +// CHECK-NEXT : OpStore %MyPayload [[payloadread0]] +// CHECK-NEXT : OpIgnoreIntersectionNV + IgnoreHit(); + } else { +// CHECK: [[payloadread1:%\d+]] = OpLoad %Payload %MyPayload_0 +// CHECK-NEXT : OpStore %MyPayload [[payloadread1]] +// CHECK-NEXT : OpTerminateRayNV + AcceptHitAndEndSearch(); + } +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv new file mode 100644 index 0000000..e976c64 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv.yaml new file mode 100644 index 0000000..63dad2a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.anyhit.spv.yaml @@ -0,0 +1,378 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 23 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 25 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 20 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 18 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 29 + op: 24 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv4 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv5 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv6 + spirv_id: 9 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv7 + spirv_id: 10 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5327 # InInstanceCustomIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv8 + spirv_id: 11 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv9 + spirv_id: 12 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5323 # InObjectRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv10 + spirv_id: 13 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5324 # InObjectRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv11 + spirv_id: 14 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5330 # InObjectToWorldKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv12 + spirv_id: 15 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5331 # InWorldToObjectKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv13 + spirv_id: 16 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5333 # InHitKindKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5315 # AnyHitKHR + shader_stage: 0x00000200 # ANY_HIT + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 14, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + - *iv9 # + - *iv10 # + - *iv11 # + - *iv12 # + - *iv13 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.hlsl new file mode 100644 index 0000000..ce147fc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.hlsl @@ -0,0 +1,20 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV + +// CHECK: OpTypePointer IncomingCallableDataNV %CallData +struct CallData +{ + float4 data; +}; + +[shader("callable")] +void main(inout CallData myCallData) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 a = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 b = DispatchRaysDimensions(); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv new file mode 100644 index 0000000..bcc087d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv.yaml new file mode 100644 index 0000000..cb7b135 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.callable.spv.yaml @@ -0,0 +1,82 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5318 # CallableKHR + shader_stage: 0x00002000 # CALLABLE + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 2, + input_variables: + - *iv0 # + - *iv1 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.hlsl new file mode 100644 index 0000000..4dab12f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.hlsl @@ -0,0 +1,79 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV +// CHECK: OpDecorate %gl_InstanceID BuiltIn InstanceId +// CHECK: OpDecorate [[g:%\d+]] BuiltIn InstanceCustomIndexNV +// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId +// CHECK: OpDecorate [[h:%\d+]] BuiltIn ObjectRayOriginNV +// CHECK: OpDecorate [[i:%\d+]] BuiltIn ObjectRayDirectionNV +// CHECK: OpDecorate [[j:%\d+]] BuiltIn ObjectToWorldNV +// CHECK: OpDecorate [[k:%\d+]] BuiltIn WorldToObjectNV +// CHECK: OpDecorate [[l:%\d+]] BuiltIn HitKindNV + +// CHECK: OpTypePointer IncomingRayPayloadNV %Payload +struct Payload +{ + float4 color; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; + +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + +[shader("closesthit")] +void main(inout Payload MyPayload, in Attribute MyAttr) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: [[matotw:%\d+]] = OpLoad %mat4v3float [[j]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matotw]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: [[matwto:%\d+]] = OpLoad %mat4v3float [[k]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matwto]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); +// CHECK: OpLoad %uint [[l]] + uint _16 = HitKind(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; +// CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0 + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv new file mode 100644 index 0000000..e987d9e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv.yaml new file mode 100644 index 0000000..92ed25b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.closesthit.spv.yaml @@ -0,0 +1,433 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 19 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 35 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 23 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 21 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 28 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 40 + op: 24 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "rs" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 142, set: 138 } +all_interface_variables: + - &iv0 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv4 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv5 + spirv_id: 9 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv6 + spirv_id: 10 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv7 + spirv_id: 11 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5327 # InInstanceCustomIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv8 + spirv_id: 12 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv9 + spirv_id: 13 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5323 # InObjectRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv10 + spirv_id: 14 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5324 # InObjectRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv11 + spirv_id: 15 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5330 # InObjectToWorldKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv12 + spirv_id: 16 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5331 # InWorldToObjectKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv13 + spirv_id: 17 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5333 # InHitKindKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5316 # ClosestHitKHR + shader_stage: 0x00000400 # CLOSEST_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "rs" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "rs" + input_variable_count: 14, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + - *iv9 # + - *iv10 # + - *iv11 # + - *iv12 # + - *iv13 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.hlsl new file mode 100644 index 0000000..6b7dee5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.hlsl @@ -0,0 +1,48 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV + +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + +struct Payload +{ + float4 color; +}; +struct CallData +{ + float4 data; +}; + +//CHECK: %First = OpVariable %_ptr_Private_int Private %int_0 +//CHECK-NEXT: %Second = OpVariable %_ptr_Private_int Private %int_1 +enum Number { + First, + Second, +}; + +//CHECK: [[first:%\d+]] = OpLoad %int %First +//CHECK-NEXT: OpStore %foo [[first]] +static ::Number foo = First; + +[shader("raygeneration")] +void main() { +//CHECK: [[second:%\d+]] = OpLoad %int %Second +//CHECK-NEXT: OpStore %bar [[second]] + static ::Number bar = Second; + + uint3 a = DispatchRaysIndex(); + uint3 b = DispatchRaysDimensions(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + CallData myCallData = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); + CallShader(0, myCallData); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv new file mode 100644 index 0000000..96d2cb4 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv.yaml new file mode 100644 index 0000000..2dbac18 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.enum.spv.yaml @@ -0,0 +1,137 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 22 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "rs" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 96, set: 92 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5313 # RayGenerationKHR + shader_stage: 0x00000100 # RAYGEN + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "rs" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "rs" + input_variable_count: 2, + input_variables: + - *iv0 # + - *iv1 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.hlsl new file mode 100644 index 0000000..7799d57 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.hlsl @@ -0,0 +1,62 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV +// CHECK: OpDecorate %gl_InstanceID BuiltIn InstanceId +// CHECK: OpDecorate [[g:%\d+]] BuiltIn InstanceCustomIndexNV +// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId +// CHECK: OpDecorate [[h:%\d+]] BuiltIn ObjectRayOriginNV +// CHECK: OpDecorate [[i:%\d+]] BuiltIn ObjectRayDirectionNV +// CHECK: OpDecorate [[j:%\d+]] BuiltIn ObjectToWorldNV +// CHECK: OpDecorate [[k:%\d+]] BuiltIn WorldToObjectNV + +struct Attribute +{ + float2 bary; +}; + +[shader("intersection")] +void main() { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: [[matotw:%\d+]] = OpLoad %mat4v3float [[j]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matotw]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: [[matwto:%\d+]] = OpLoad %mat4v3float [[k]] +// CHECK-NEXT: OpTranspose %mat3v4float [[matwto]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); + + Attribute myHitAttribute = { float2(0.0f,0.0f) }; +// CHECK: OpReportIntersectionKHR %bool %float_0 %uint_0 + ReportHit(0.0f, 0U, myHitAttribute); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv new file mode 100644 index 0000000..f95e27e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv.yaml new file mode 100644 index 0000000..0b2cab2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.intersection.spv.yaml @@ -0,0 +1,359 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 23 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 17 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 19 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 27 + op: 24 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv4 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv5 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv6 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv7 + spirv_id: 9 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5327 # InInstanceCustomIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv8 + spirv_id: 10 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } + - &iv9 + spirv_id: 11 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5323 # InObjectRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv10 + spirv_id: 12 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5324 # InObjectRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv11 + spirv_id: 13 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5330 # InObjectToWorldKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } + - &iv12 + spirv_id: 14 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5331 # InWorldToObjectKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5314 # IntersectionKHR + shader_stage: 0x00001000 # INTERSECTION + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 13, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + - *iv9 # + - *iv10 # + - *iv11 # + - *iv12 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.hlsl new file mode 100644 index 0000000..00cbb54 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.hlsl @@ -0,0 +1,260 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpEntryPoint RayGenerationNV %MyRayGenMain "MyRayGenMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint RayGenerationNV %MyRayGenMain2 "MyRayGenMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint MissNV %MyMissMain "MyMissMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint MissNV %MyMissMain2 "MyMissMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint IntersectionNV %MyISecMain "MyISecMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint IntersectionNV %MyISecMain2 "MyISecMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint AnyHitNV %MyAHitMain "MyAHitMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint AnyHitNV %MyAHitMain2 "MyAHitMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint ClosestHitNV %MyCHitMain "MyCHitMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint ClosestHitNV %MyCHitMain2 "MyCHitMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint CallableNV %MyCallMain "MyCallMain" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpEntryPoint CallableNV %MyCallMain2 "MyCallMain2" {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %gl_InstanceID {{%\d+}} %gl_PrimitiveID {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV +// CHECK: OpDecorate %gl_InstanceID BuiltIn InstanceId +// CHECK: OpDecorate [[g:%\d+]] BuiltIn InstanceCustomIndexNV +// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId +// CHECK: OpDecorate [[h:%\d+]] BuiltIn ObjectRayOriginNV +// CHECK: OpDecorate [[i:%\d+]] BuiltIn ObjectRayDirectionNV +// CHECK: OpDecorate [[j:%\d+]] BuiltIn ObjectToWorldNV +// CHECK: OpDecorate [[k:%\d+]] BuiltIn WorldToObjectNV +// CHECK: OpDecorate [[l:%\d+]] BuiltIn HitKindNV + + +// CHECK: OpTypePointer CallableDataNV %CallData +struct CallData +{ + float4 data; +}; +// CHECK: OpTypePointer IncomingRayPayloadNV %Payload +struct Payload +{ + float4 color; +}; +// CHECK: OpTypePointer HitAttributeNV %Attribute +struct Attribute +{ + float2 bary; +}; +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + + +[shader("raygeneration")] +void MyRayGenMain() { + +// CHECK: OpLoad %v3uint [[a]] + uint3 a = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 b = DispatchRaysDimensions(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + CallData myCallData = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; +// CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0 + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); +// CHECK: OpExecuteCallableNV %uint_0 %uint_0 + CallShader(0, myCallData); +} + +[shader("raygeneration")] +void MyRayGenMain2() { + CallData myCallData = { float4(0.0f,0.0f,0.0f,0.0f) }; + CallShader(0, myCallData); +} + +[shader("miss")] +void MyMissMain(inout Payload MyPayload) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +} + +[shader("miss")] +void MyMissMain2(inout Payload MyPayload) { + MyPayload.color = float4(0.0f,1.0f,0.0f,1.0f); +} + +[shader("intersection")] +void MyISecMain() { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: OpLoad %mat4v3float [[j]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: OpLoad %mat4v3float [[k]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); + + Attribute myHitAttribute = { float2(0.0f,0.0f) }; +// CHECK: OpReportIntersectionKHR %bool %float_0 %uint_0 + ReportHit(0.0f, 0U, myHitAttribute); +} + +[shader("intersection")] +void MyISecMain2() { + Attribute myHitAttribute = { float2(0.0f,1.0f) }; +// CHECK: OpReportIntersectionKHR %bool %float_0 %uint_0 + ReportHit(0.0f, 0U, myHitAttribute); +} + +[shader("anyhit")] +void MyAHitMain(inout Payload MyPayload, in Attribute MyAttr) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: OpLoad %mat4v3float [[j]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: OpLoad %mat4v3float [[k]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); +// CHECK: OpLoad %uint [[l]] + uint _16 = HitKind(); + + if (_16 == 1U) { +// CHECK: OpIgnoreIntersectionNV + IgnoreHit(); + } else { +// CHECK: OpTerminateRayNV + AcceptHitAndEndSearch(); + } +} + +[shader("anyhit")] +void MyAHitMain2(inout Payload MyPayload, in Attribute MyAttr) { +// CHECK: OpTerminateRayNV + AcceptHitAndEndSearch(); +} + +[shader("closesthit")] +void MyCHitMain(inout Payload MyPayload, in Attribute MyAttr) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +// CHECK: OpLoad %uint %gl_InstanceID + uint _7 = InstanceIndex(); +// CHECK: OpLoad %uint [[g]] + uint _8 = InstanceID(); +// CHECK: OpLoad %uint %gl_PrimitiveID + uint _9 = PrimitiveIndex(); +// CHECK: OpLoad %v3float [[h]] + float3 _10 = ObjectRayOrigin(); +// CHECK: OpLoad %v3float [[i]] + float3 _11 = ObjectRayDirection(); +// CHECK: OpLoad %mat4v3float [[j]] + float3x4 _12 = ObjectToWorld3x4(); +// CHECK: OpLoad %mat4v3float [[j]] + float4x3 _13 = ObjectToWorld4x3(); +// CHECK: OpLoad %mat4v3float [[k]] + float3x4 _14 = WorldToObject3x4(); +// CHECK: OpLoad %mat4v3float [[k]] + float4x3 _15 = WorldToObject4x3(); +// CHECK: OpLoad %uint [[l]] + uint _16 = HitKind(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; +// CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0 + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); +} + +[shader("closesthit")] +void MyCHitMain2(inout Payload MyPayload, in Attribute MyAttr) { + MyPayload.color = float4(0.0f,1.0f,0.0f,1.0f); +} + +[shader("callable")] +void MyCallMain(inout CallData myCallData) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 a = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 b = DispatchRaysDimensions(); +} + +[shader("callable")] +void MyCallMain2(inout CallData myCallData) { + myCallData.data = float4(0.0f,1.0f,0.0f,1.0f); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv new file mode 100644 index 0000000..6fd997e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv.yaml new file mode 100644 index 0000000..7b88721 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.library.spv.yaml @@ -0,0 +1,433 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 39 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 58 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 45 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 43 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 50 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 66 + op: 24 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000308 # MATRIX VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "rs" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 634, set: 630 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv2 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 9 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv4 + spirv_id: 10 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td3 + word_offset: { location: 0 } + - &iv5 + spirv_id: 11 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv6 + spirv_id: 13 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv7 + spirv_id: 14 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5327 # InInstanceCustomIndexKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv8 + spirv_id: 15 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 7 # PrimitiveId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } + - &iv9 + spirv_id: 16 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5323 # InObjectRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv10 + spirv_id: 17 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5324 # InObjectRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv11 + spirv_id: 18 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5330 # InObjectToWorldKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv12 + spirv_id: 19 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5331 # InWorldToObjectKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 4, row_count: 3, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td5 + word_offset: { location: 0 } + - &iv13 + spirv_id: 22 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5333 # InHitKindKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "MyRayGenMain" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5313 # RayGenerationKHR + shader_stage: 0x00000100 # RAYGEN + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "rs" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "rs" + input_variable_count: 14, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + - *iv6 # + - *iv7 # + - *iv8 # + - *iv9 # + - *iv10 # + - *iv11 # + - *iv12 # + - *iv13 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.hlsl new file mode 100644 index 0000000..88634ca --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.hlsl @@ -0,0 +1,32 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV +// CHECK: OpDecorate [[c:%\d+]] BuiltIn WorldRayOriginNV +// CHECK: OpDecorate [[d:%\d+]] BuiltIn WorldRayDirectionNV +// CHECK: OpDecorate [[e:%\d+]] BuiltIn RayTminNV +// CHECK: OpDecorate [[f:%\d+]] BuiltIn IncomingRayFlagsNV + +// CHECK: OpTypePointer IncomingRayPayloadNV %Payload +struct Payload +{ + float4 color; +}; + +[shader("miss")] +void main(inout Payload MyPayload) { + +// CHECK: OpLoad %v3uint [[a]] + uint3 _1 = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 _2 = DispatchRaysDimensions(); +// CHECK: OpLoad %v3float [[c]] + float3 _3 = WorldRayOrigin(); +// CHECK: OpLoad %v3float [[d]] + float3 _4 = WorldRayDirection(); +// CHECK: OpLoad %float [[e]] + float _5 = RayTMin(); +// CHECK: OpLoad %uint [[f]] + uint _6 = RayFlags(); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv new file mode 100644 index 0000000..8f9700f Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv.yaml new file mode 100644 index 0000000..20c5a08 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.miss.spv.yaml @@ -0,0 +1,209 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 16 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 10 + op: 22 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 13 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td0 + word_offset: { location: 0 } + - &iv2 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5321 # InWorldRayOriginKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv3 + spirv_id: 6 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5322 # InWorldRayDirectionKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 106 # VK_FORMAT_R32G32B32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } + - &iv4 + spirv_id: 7 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5325 # InRayTminKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 100 # VK_FORMAT_R32_SFLOAT + type_description: *td2 + word_offset: { location: 0 } + - &iv5 + spirv_id: 8 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5351 # InIncomingRayFlagsKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td3 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5317 # MissKHR + shader_stage: 0x00000800 # MISS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 6, + input_variables: + - *iv0 # + - *iv1 # + - *iv2 # + - *iv3 # + - *iv4 # + - *iv5 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.hlsl b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.hlsl new file mode 100644 index 0000000..aa0c449 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.hlsl @@ -0,0 +1,38 @@ +// Run: %dxc -T lib_6_3 -fspv-extension=SPV_NV_ray_tracing +// CHECK: OpCapability RayTracingNV +// CHECK: OpExtension "SPV_NV_ray_tracing" +// CHECK: OpDecorate [[a:%\d+]] BuiltIn LaunchIdNV +// CHECK: OpDecorate [[b:%\d+]] BuiltIn LaunchSizeNV + +// CHECK-COUNT-1: [[rstype:%\d+]] = OpTypeAccelerationStructureNV +RaytracingAccelerationStructure rs; + +struct Payload +{ + float4 color; +}; +struct CallData +{ + float4 data; +}; + +[shader("raygeneration")] +void main() { + +// CHECK: OpLoad %v3uint [[a]] + uint3 a = DispatchRaysIndex(); +// CHECK: OpLoad %v3uint [[b]] + uint3 b = DispatchRaysDimensions(); + + Payload myPayload = { float4(0.0f,0.0f,0.0f,0.0f) }; + CallData myCallData = { float4(0.0f,0.0f,0.0f,0.0f) }; + RayDesc rayDesc; + rayDesc.Origin = float3(0.0f, 0.0f, 0.0f); + rayDesc.Direction = float3(0.0f, 0.0f, -1.0f); + rayDesc.TMin = 0.0f; + rayDesc.TMax = 1000.0f; + // CHECK: OpTraceNV {{%\d+}} %uint_0 %uint_255 %uint_0 %uint_1 %uint_0 {{%\d+}} {{%\d+}} {{%\d+}} {{%\d+}} %uint_0 + TraceRay(rs, 0x0, 0xff, 0, 1, 0, rayDesc, myPayload); + // CHECK: OpExecuteCallableNV %uint_0 %uint_0 + CallShader(0, myCallData); +} diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv new file mode 100644 index 0000000..96d2cb4 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv.yaml b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv.yaml new file mode 100644 index 0000000..2dbac18 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/raytrace/raytracing.nv.raygen.spv.yaml @@ -0,0 +1,137 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 5341 + type_name: "accelerationStructureNV" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00100000 # ??? + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 22 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: "rs" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 1000150000 # VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 96, set: 92 } +all_interface_variables: + - &iv0 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5319 # InLaunchIdKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } + - &iv1 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 5320 # InLaunchSizeKHR + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td1 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "main" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 630 + spirv_execution_model: 5313 # RayGenerationKHR + shader_stage: 0x00000100 # RAYGEN + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "rs" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "rs" + input_variable_count: 2, + input_variables: + - *iv0 # + - *iv1 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/basic.comp b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.comp new file mode 100644 index 0000000..fec4bc5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.comp @@ -0,0 +1,13 @@ +#version 450 + +layout(constant_id = 3) const int SIZE = 2; + +layout(set = 0, binding = 0, std430) buffer SSBO { + float val[SIZE]; + float dummy; +} ssbo; + +void main() { + ssbo.val[0] = 0.0; +} + diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv new file mode 100644 index 0000000..7bb1222 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv.yaml new file mode 100644 index 0000000..f15705c --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/basic.spv.yaml @@ -0,0 +1,155 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 6 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 10 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 +all_block_variables: + - &bv0 + name: "val" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "dummy" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "ssbo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "ssbo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "ssbo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 83, set: 79 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "ssbo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "ssbo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 1, + specialization_constants: + - name: "SIZE" + spirv_id: 8 + constant_id: 3 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/convert.comp b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.comp new file mode 100644 index 0000000..ad73700 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.comp @@ -0,0 +1,34 @@ +#version 450 + +#extension GL_EXT_shader_explicit_arithmetic_types_int64: enable + +layout(local_size_x = 1) in; + +layout(constant_id = 0) const int64_t SONE = 1; +layout(constant_id = 1) const uint64_t UONE = 1; +layout(constant_id = 2) const float F_ONE = 1.0; +layout(constant_id = 3) const double D_ONE = 1.0; + +const uint U_SONE = uint(SONE); +const uint U_UONE = uint(UONE); + +const int S_SONE = int(SONE); +const int S_UONE = int(UONE); + +const float F_ONE2 = float(D_ONE); +const double D_ONE2 = double(F_ONE); + +#define DUMMY_SSBO(name, bind, size) layout(std430, set = 0, binding = bind) buffer SSBO_##name { float val[size]; float dummy; } name + +DUMMY_SSBO(U_Sone, 0, U_SONE); +DUMMY_SSBO(U_Uone, 1, U_UONE); +DUMMY_SSBO(S_Sone, 2, S_SONE); +DUMMY_SSBO(S_Uone, 3, S_UONE); + +void main() +{ + U_Sone.val[0] = F_ONE; + U_Uone.val[0] = F_ONE; + S_Sone.val[0] = F_ONE2; + S_Uone.val[0] = F_ONE2; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv new file mode 100644 index 0000000..948b8a3 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv.yaml new file mode 100644 index 0000000..8615964 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/convert.spv.yaml @@ -0,0 +1,530 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 14 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 6 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 15 + op: 30 + type_name: "SSBO_U_Sone" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 25 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [113,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 6 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 26 + op: 30 + type_name: "SSBO_U_Uone" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 + - &td6 + id: 31 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [114,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 6 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 32 + op: 30 + type_name: "SSBO_S_Sone" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td6 + - *td7 + - &td9 + id: 41 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td10 + id: 6 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 42 + op: 30 + type_name: "SSBO_S_Uone" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td9 + - *td10 +all_block_variables: + - &bv0 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "U_Sone" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 + - &bv3 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [113,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "U_Uone" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv3 + - *bv4 + type_description: *td5 + - &bv6 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [114,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "S_Sone" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv6 + - *bv7 + type_description: *td8 + - &bv9 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "S_Uone" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv9 + - *bv10 + type_description: *td11 +all_descriptor_bindings: + - &db0 + spirv_id: 17 + name: "U_Sone" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "U_Sone" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 191, set: 187 } + - &db1 + spirv_id: 28 + name: "U_Uone" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "U_Uone" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 224, set: 220 } + - &db2 + spirv_id: 34 + name: "S_Sone" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv8 # "S_Sone" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 249, set: 245 } + - &db3 + spirv_id: 44 + name: "S_Uone" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "S_Uone" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 278, set: 274 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 4 + descriptor_bindings: + - *db0 # "U_Sone" + - *db1 # "U_Uone" + - *db2 # "S_Sone" + - *db3 # "S_Uone" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 4 + bindings: + - *db0 # "U_Sone" + - *db1 # "U_Uone" + - *db2 # "S_Sone" + - *db3 # "S_Uone" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 4, + specialization_constants: + - name: "SONE" + spirv_id: 8 + constant_id: 0 + - name: "F_ONE" + spirv_id: 19 + constant_id: 2 + - name: "UONE" + spirv_id: 23 + constant_id: 1 + - name: "D_ONE" + spirv_id: 36 + constant_id: 3 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id.comp b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id.comp new file mode 100644 index 0000000..733a21e --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id.comp @@ -0,0 +1,7 @@ +#version 450 + +// note Z is not and ID +// Vulkan 1.3 is needed for glslang to use LocalSizeId over LocalSize +layout(local_size_x_id = 8, local_size_y_id = 4, local_size_z = 4) in; + +void main() { } diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv new file mode 100644 index 0000000..cbbe5b0 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv.yaml new file mode 100644 index 0000000..ff5476d --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_10.spv.yaml @@ -0,0 +1,33 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 2, + specialization_constants: + - name: + spirv_id: 7 + constant_id: 8 + - name: + spirv_id: 8 + constant_id: 4 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv new file mode 100644 index 0000000..1a9497b Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv.yaml new file mode 100644 index 0000000..7180f52 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/local_size_id_13.spv.yaml @@ -0,0 +1,39 @@ +%YAML 1.1 +--- +all_type_descriptions: +all_block_variables: +all_descriptor_bindings: +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 0 + descriptor_bindings: + descriptor_set_count: 0 + descriptor_sets: + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 4, + specialization_constants: + - name: + spirv_id: 7 + constant_id: 8 + - name: + spirv_id: 8 + constant_id: 4 + - name: + spirv_id: 10 + constant_id: 8 + - name: + spirv_id: 11 + constant_id: 4 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.glsl b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.glsl new file mode 100644 index 0000000..0c0d0b5 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.glsl @@ -0,0 +1,12 @@ +#version 450 + +layout(constant_id = 8) const int SIZE_A = 4; +layout(constant_id = 5) const int SIZE_B = 3; +layout(set = 0, binding = 0, std430) buffer SSBO { + float a[SIZE_A]; + float b[SIZE_B]; +} ssbo; + +void main() { + ssbo.a[2] = ssbo.b[1]; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv new file mode 100644 index 0000000..50dbfbf Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv.yaml new file mode 100644 index 0000000..20bc96f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/ssbo_array.spv.yaml @@ -0,0 +1,158 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 28 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 11 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [3,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 12 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 16 + absolute_offset: 16 + size: 12 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [3,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "ssbo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 +all_descriptor_bindings: + - &db0 + spirv_id: 14 + name: "ssbo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "ssbo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 94, set: 90 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "ssbo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "ssbo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 2, + specialization_constants: + - name: "SIZE_A" + spirv_id: 8 + constant_id: 8 + - name: "SIZE_B" + spirv_id: 10 + constant_id: 5 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.comp b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.comp new file mode 100644 index 0000000..edd2977 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.comp @@ -0,0 +1,310 @@ +#version 450 +layout(local_size_x_id = 8, local_size_y = 1, local_size_z = 1) in; + +layout(constant_id = 2) const int SONE = 1; +layout(constant_id = 3) const int STWO = 2; +const int _141 = (SONE + STWO); +const uint _144 = (uint(_141) + 0u); +layout(constant_id = 5) const uint UONE = 1u; +const uint _145 = (_144 + UONE); +layout(constant_id = 6) const uint UTWO = 2u; +const uint IADD = (_145 + UTWO); +const uint _147 = (IADD - 5u); +layout(constant_id = 4) const int SNEG_TWO = -2; +const uint _152 = (uint(SNEG_TWO) + 0u); +const uint ISUB = (UTWO - _152); +const uint _154 = (ISUB - 3u); +const uint IMUL = (UTWO * UTWO); +const uint _156 = (IMUL - 3u); +const uint UDIV = (UTWO / UTWO); +layout(constant_id = 7) const int SNEG_THREE = -3; +const int SDIV = (STWO / SNEG_THREE); +const int _160 = (SDIV + 1); +const int SREM = STWO - SNEG_THREE * (STWO / SNEG_THREE); +const int _162 = (SREM - 1); +const int SMOD = (STWO % SNEG_THREE); +const int _165 = (SMOD + 2); +const uint UMOD = (IADD % IMUL); +const uint _168 = (UMOD - 1u); +const uint _170 = (ISUB - 3u); +const uint LSHL = (IADD << _170); +const uint _172 = (LSHL - 11u); +const uint _174 = (ISUB - 3u); +const uint RSHL = (IADD >> _174); +const uint _176 = (RSHL - 2u); +const int _178 = int(IADD + 0u); +const int _179 = (-_178); +const int _180 = (1 - SDIV); +const int RSHA = (_179 >> _180); +const int _182 = (RSHA + 4); +const uint _184 = (ISUB - 3u); +const bool IEQ = (IADD == _184); +const int _186 = IEQ ? 2 : 1; +const uint _188 = (ISUB - 3u); +const bool INEQ = (IADD != _188); +const int _189 = INEQ ? 1 : 2; +const uint _191 = (ISUB - 3u); +const bool ULT = (IADD < _191); +const int _192 = ULT ? 2 : 1; +const uint _194 = (ISUB - 3u); +const bool ULE = (IADD <= _194); +const int _195 = ULE ? 2 : 1; +const uint _197 = (ISUB - 3u); +const bool UGT = (IADD > _197); +const int _198 = UGT ? 1 : 2; +const uint _200 = (ISUB - 3u); +const bool UGE = (IADD >= _200); +const int _201 = UGE ? 1 : 2; +const bool SLT = (SMOD < SREM); +const int _203 = SLT ? 1 : 2; +const bool SLE = (SMOD <= SREM); +const int _205 = SLE ? 1 : 2; +const bool SGT = (SMOD > SREM); +const int _207 = SGT ? 2 : 1; +const bool SGE = (SMOD >= SREM); +const int _209 = SGE ? 2 : 1; +const bool LOR = (IEQ || SLT); +const int _211 = LOR ? 1 : 2; +const bool LAND = (IEQ && SLT); +const int _213 = LAND ? 2 : 1; +const bool LNOT = (!LOR); +const int _215 = LNOT ? 2 : 1; +const uint AND = (IADD & IADD); +const uint _217 = (AND - 5u); +const uint _219 = (ISUB - 3u); +const uint OR = (IADD | _219); +const uint _221 = (OR - 6u); +const uint XOR = (IADD ^ IADD); +const uint _223 = (XOR + 1u); +const uint NOT = (~XOR); +const uint _226 = (NOT - 4294967294u); +const bool LEQ = (LAND == LNOT); +const int _228 = LEQ ? 1 : 2; +const bool LNEQ = (LAND != LNOT); +const int _230 = LNEQ ? 2 : 1; +const uint _232 = (ISUB - 3u); +const uint SEL = IEQ ? IADD : _232; +layout(constant_id = 0) const bool TRUE = true; +layout(constant_id = 1) const bool FALSE = false; + +layout(set = 0, binding = 0, std430) buffer SSBO_IAdd +{ + float val[_147]; + float dummy; +} IAdd; + +layout(set = 0, binding = 1, std430) buffer SSBO_ISub +{ + float val[_154]; + float dummy; +} ISub; + +layout(set = 0, binding = 2, std430) buffer SSBO_IMul +{ + float val[_156]; + float dummy; +} IMul; + +layout(set = 0, binding = 3, std430) buffer SSBO_UDiv +{ + float val[UDIV]; + float dummy; +} UDiv; + +layout(set = 0, binding = 4, std430) buffer SSBO_SDiv +{ + float val[_160]; + float dummy; +} SDiv; + +layout(set = 0, binding = 5, std430) buffer SSBO_SRem +{ + float val[_162]; + float dummy; +} SRem; + +layout(set = 0, binding = 6, std430) buffer SSBO_SMod +{ + float val[_165]; + float dummy; +} SMod; + +layout(set = 0, binding = 7, std430) buffer SSBO_UMod +{ + float val[_168]; + float dummy; +} UMod; + +layout(set = 0, binding = 8, std430) buffer SSBO_LShl +{ + float val[_172]; + float dummy; +} LShl; + +layout(set = 0, binding = 9, std430) buffer SSBO_RShl +{ + float val[_176]; + float dummy; +} RShl; + +layout(set = 0, binding = 10, std430) buffer SSBO_RSha +{ + float val[_182]; + float dummy; +} RSha; + +layout(set = 0, binding = 11, std430) buffer SSBO_IEq +{ + float val[_186]; + float dummy; +} IEq; + +layout(set = 0, binding = 12, std430) buffer SSBO_INeq +{ + float val[_189]; + float dummy; +} INeq; + +layout(set = 0, binding = 13, std430) buffer SSBO_Ult +{ + float val[_192]; + float dummy; +} Ult; + +layout(set = 0, binding = 14, std430) buffer SSBO_Ule +{ + float val[_195]; + float dummy; +} Ule; + +layout(set = 0, binding = 15, std430) buffer SSBO_Ugt +{ + float val[_198]; + float dummy; +} Ugt; + +layout(set = 0, binding = 16, std430) buffer SSBO_Uge +{ + float val[_201]; + float dummy; +} Uge; + +layout(set = 0, binding = 17, std430) buffer SSBO_Slt +{ + float val[_203]; + float dummy; +} Slt; + +layout(set = 0, binding = 18, std430) buffer SSBO_Sle +{ + float val[_205]; + float dummy; +} Sle; + +layout(set = 0, binding = 19, std430) buffer SSBO_Sgt +{ + float val[_207]; + float dummy; +} Sgt; + +layout(set = 0, binding = 20, std430) buffer SSBO_Sge +{ + float val[_209]; + float dummy; +} Sge; + +layout(set = 0, binding = 21, std430) buffer SSBO_Lor +{ + float val[_211]; + float dummy; +} Lor; + +layout(set = 0, binding = 22, std430) buffer SSBO_Land +{ + float val[_213]; + float dummy; +} Land; + +layout(set = 0, binding = 23, std430) buffer SSBO_Lnot +{ + float val[_215]; + float dummy; +} Lnot; + +layout(set = 0, binding = 24, std430) buffer SSBO_And +{ + float val[_217]; + float dummy; +} And; + +layout(set = 0, binding = 25, std430) buffer SSBO_Or +{ + float val[_221]; + float dummy; +} Or; + +layout(set = 0, binding = 26, std430) buffer SSBO_Xor +{ + float val[_223]; + float dummy; +} Xor; + +layout(set = 0, binding = 27, std430) buffer SSBO_Not +{ + float val[_226]; + float dummy; +} Not; + +layout(set = 0, binding = 28, std430) buffer SSBO_Leq +{ + float val[_228]; + float dummy; +} Leq; + +layout(set = 0, binding = 29, std430) buffer SSBO_Lneq +{ + float val[_230]; + float dummy; +} Lneq; + +layout(set = 0, binding = 30, std430) buffer SSBO_Sel +{ + float val[SEL]; + float dummy; +} Sel; + +void main() +{ + IAdd.val[0] = 0.0; + ISub.val[0] = 0.0; + IMul.val[0] = 0.0; + UDiv.val[0] = 0.0; + SDiv.val[0] = 0.0; + SRem.val[0] = 0.0; + SMod.val[0] = 0.0; + UMod.val[0] = 0.0; + LShl.val[0] = 0.0; + RShl.val[0] = 0.0; + RSha.val[0] = 0.0; + IEq.val[0] = 0.0; + INeq.val[0] = 0.0; + Ult.val[0] = 0.0; + Ule.val[0] = 0.0; + Ugt.val[0] = 0.0; + Uge.val[0] = 0.0; + Slt.val[0] = 0.0; + Sle.val[0] = 0.0; + Sgt.val[0] = 0.0; + Sge.val[0] = 0.0; + Lor.val[0] = 0.0; + Land.val[0] = 0.0; + Lnot.val[0] = 0.0; + And.val[0] = 0.0; + Or.val[0] = 0.0; + Xor.val[0] = 0.0; + Not.val[0] = 0.0; + Leq.val[0] = 0.0; + Lneq.val[0] = 0.0; + Sel.val[0] = 0.0; +} + diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv new file mode 100644 index 0000000..7a8f602 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv.yaml new file mode 100644 index 0000000..058be88 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/test_32bit.spv.yaml @@ -0,0 +1,3839 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 104 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 39 + op: 30 + type_name: "SSBO_IAdd" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 105 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 42 + op: 30 + type_name: "SSBO_ISub" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 + - &td6 + id: 106 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 44 + op: 30 + type_name: "SSBO_IMul" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td6 + - *td7 + - &td9 + id: 107 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [134,], stride: 4 } + member_count: 0 + members: + - &td10 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 46 + op: 30 + type_name: "SSBO_UDiv" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td9 + - *td10 + - &td12 + id: 108 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td13 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 49 + op: 30 + type_name: "SSBO_SDiv" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td12 + - *td13 + - &td15 + id: 109 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td16 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 51 + op: 30 + type_name: "SSBO_SRem" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td15 + - *td16 + - &td18 + id: 110 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td19 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 53 + op: 30 + type_name: "SSBO_SMod" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td18 + - *td19 + - &td21 + id: 111 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td22 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 55 + op: 30 + type_name: "SSBO_UMod" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td21 + - *td22 + - &td24 + id: 112 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td25 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 57 + op: 30 + type_name: "SSBO_LShl" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td24 + - *td25 + - &td27 + id: 113 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td28 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td29 + id: 59 + op: 30 + type_name: "SSBO_RShl" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td27 + - *td28 + - &td30 + id: 114 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td31 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td32 + id: 61 + op: 30 + type_name: "SSBO_RSha" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td30 + - *td31 + - &td33 + id: 115 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td34 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td35 + id: 63 + op: 30 + type_name: "SSBO_IEq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td33 + - *td34 + - &td36 + id: 116 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td37 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td38 + id: 65 + op: 30 + type_name: "SSBO_INeq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td36 + - *td37 + - &td39 + id: 117 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td40 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td41 + id: 67 + op: 30 + type_name: "SSBO_Ult" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td39 + - *td40 + - &td42 + id: 118 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td43 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td44 + id: 69 + op: 30 + type_name: "SSBO_Ule" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td42 + - *td43 + - &td45 + id: 119 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td46 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td47 + id: 71 + op: 30 + type_name: "SSBO_Ugt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td45 + - *td46 + - &td48 + id: 120 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td49 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td50 + id: 73 + op: 30 + type_name: "SSBO_Uge" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td48 + - *td49 + - &td51 + id: 121 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td52 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td53 + id: 75 + op: 30 + type_name: "SSBO_Slt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td51 + - *td52 + - &td54 + id: 122 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td55 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td56 + id: 77 + op: 30 + type_name: "SSBO_Sle" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td54 + - *td55 + - &td57 + id: 123 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td58 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td59 + id: 79 + op: 30 + type_name: "SSBO_Sgt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td57 + - *td58 + - &td60 + id: 124 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td61 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td62 + id: 81 + op: 30 + type_name: "SSBO_Sge" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td60 + - *td61 + - &td63 + id: 125 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td64 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td65 + id: 83 + op: 30 + type_name: "SSBO_Lor" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td63 + - *td64 + - &td66 + id: 126 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td67 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td68 + id: 85 + op: 30 + type_name: "SSBO_Land" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td66 + - *td67 + - &td69 + id: 127 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td70 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td71 + id: 87 + op: 30 + type_name: "SSBO_Lnot" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td69 + - *td70 + - &td72 + id: 128 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td73 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td74 + id: 89 + op: 30 + type_name: "SSBO_And" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td72 + - *td73 + - &td75 + id: 129 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td76 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td77 + id: 91 + op: 30 + type_name: "SSBO_Or" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td75 + - *td76 + - &td78 + id: 130 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td79 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td80 + id: 93 + op: 30 + type_name: "SSBO_Xor" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td78 + - *td79 + - &td81 + id: 131 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td82 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td83 + id: 95 + op: 30 + type_name: "SSBO_Not" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td81 + - *td82 + - &td84 + id: 132 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td85 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td86 + id: 97 + op: 30 + type_name: "SSBO_Leq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td84 + - *td85 + - &td87 + id: 133 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td88 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td89 + id: 99 + op: 30 + type_name: "SSBO_Lneq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td87 + - *td88 + - &td90 + id: 134 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td91 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td92 + id: 101 + op: 30 + type_name: "SSBO_Sel" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td90 + - *td91 +all_block_variables: + - &bv0 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "IAdd" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 + - &bv3 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "ISub" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv3 + - *bv4 + type_description: *td5 + - &bv6 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "IMul" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv6 + - *bv7 + type_description: *td8 + - &bv9 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [134,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "UDiv" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv9 + - *bv10 + type_description: *td11 + - &bv12 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "SDiv" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv12 + - *bv13 + type_description: *td14 + - &bv15 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "SRem" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv15 + - *bv16 + type_description: *td17 + - &bv18 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "SMod" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv18 + - *bv19 + type_description: *td20 + - &bv21 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "UMod" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv21 + - *bv22 + type_description: *td23 + - &bv24 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "LShl" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv24 + - *bv25 + type_description: *td26 + - &bv27 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td27 + - &bv28 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv29 + name: "RShl" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv27 + - *bv28 + type_description: *td29 + - &bv30 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td30 + - &bv31 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td31 + - &bv32 + name: "RSha" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv30 + - *bv31 + type_description: *td32 + - &bv33 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td33 + - &bv34 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td34 + - &bv35 + name: "IEq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv33 + - *bv34 + type_description: *td35 + - &bv36 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td36 + - &bv37 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td37 + - &bv38 + name: "INeq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv36 + - *bv37 + type_description: *td38 + - &bv39 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td39 + - &bv40 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td40 + - &bv41 + name: "Ult" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv39 + - *bv40 + type_description: *td41 + - &bv42 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td42 + - &bv43 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td43 + - &bv44 + name: "Ule" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv42 + - *bv43 + type_description: *td44 + - &bv45 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td45 + - &bv46 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td46 + - &bv47 + name: "Ugt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv45 + - *bv46 + type_description: *td47 + - &bv48 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td48 + - &bv49 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td49 + - &bv50 + name: "Uge" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv48 + - *bv49 + type_description: *td50 + - &bv51 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td51 + - &bv52 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td52 + - &bv53 + name: "Slt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv51 + - *bv52 + type_description: *td53 + - &bv54 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td54 + - &bv55 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td55 + - &bv56 + name: "Sle" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv54 + - *bv55 + type_description: *td56 + - &bv57 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td57 + - &bv58 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td58 + - &bv59 + name: "Sgt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv57 + - *bv58 + type_description: *td59 + - &bv60 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td60 + - &bv61 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td61 + - &bv62 + name: "Sge" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv60 + - *bv61 + type_description: *td62 + - &bv63 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td63 + - &bv64 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td64 + - &bv65 + name: "Lor" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv63 + - *bv64 + type_description: *td65 + - &bv66 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td66 + - &bv67 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td67 + - &bv68 + name: "Land" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv66 + - *bv67 + type_description: *td68 + - &bv69 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td69 + - &bv70 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td70 + - &bv71 + name: "Lnot" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv69 + - *bv70 + type_description: *td71 + - &bv72 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td72 + - &bv73 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td73 + - &bv74 + name: "And" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv72 + - *bv73 + type_description: *td74 + - &bv75 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td75 + - &bv76 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td76 + - &bv77 + name: "Or" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv75 + - *bv76 + type_description: *td77 + - &bv78 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td78 + - &bv79 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td79 + - &bv80 + name: "Xor" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv78 + - *bv79 + type_description: *td80 + - &bv81 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td81 + - &bv82 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td82 + - &bv83 + name: "Not" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv81 + - *bv82 + type_description: *td83 + - &bv84 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td84 + - &bv85 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td85 + - &bv86 + name: "Leq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv84 + - *bv85 + type_description: *td86 + - &bv87 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td87 + - &bv88 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td88 + - &bv89 + name: "Lneq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv87 + - *bv88 + type_description: *td89 + - &bv90 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td90 + - &bv91 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td91 + - &bv92 + name: "Sel" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv90 + - *bv91 + type_description: *td92 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "IAdd" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "IAdd" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 806, set: 802 } + - &db1 + spirv_id: 4 + name: "ISub" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "ISub" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 835, set: 831 } + - &db2 + spirv_id: 5 + name: "IMul" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv8 # "IMul" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 860, set: 856 } + - &db3 + spirv_id: 6 + name: "UDiv" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "UDiv" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 885, set: 881 } + - &db4 + spirv_id: 7 + name: "SDiv" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv14 # "SDiv" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td14 + word_offset: { binding: 914, set: 910 } + - &db5 + spirv_id: 8 + name: "SRem" + binding: 5 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv17 # "SRem" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 939, set: 935 } + - &db6 + spirv_id: 9 + name: "SMod" + binding: 6 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv20 # "SMod" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td20 + word_offset: { binding: 964, set: 960 } + - &db7 + spirv_id: 10 + name: "UMod" + binding: 7 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv23 # "UMod" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td23 + word_offset: { binding: 989, set: 985 } + - &db8 + spirv_id: 11 + name: "LShl" + binding: 8 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv26 # "LShl" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td26 + word_offset: { binding: 1014, set: 1010 } + - &db9 + spirv_id: 12 + name: "RShl" + binding: 9 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv29 # "RShl" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1039, set: 1035 } + - &db10 + spirv_id: 13 + name: "RSha" + binding: 10 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv32 # "RSha" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td32 + word_offset: { binding: 1064, set: 1060 } + - &db11 + spirv_id: 14 + name: "IEq" + binding: 11 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv35 # "IEq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td35 + word_offset: { binding: 1089, set: 1085 } + - &db12 + spirv_id: 15 + name: "INeq" + binding: 12 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv38 # "INeq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td38 + word_offset: { binding: 1114, set: 1110 } + - &db13 + spirv_id: 16 + name: "Ult" + binding: 13 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv41 # "Ult" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td41 + word_offset: { binding: 1139, set: 1135 } + - &db14 + spirv_id: 17 + name: "Ule" + binding: 14 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv44 # "Ule" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td44 + word_offset: { binding: 1164, set: 1160 } + - &db15 + spirv_id: 18 + name: "Ugt" + binding: 15 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv47 # "Ugt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td47 + word_offset: { binding: 1189, set: 1185 } + - &db16 + spirv_id: 19 + name: "Uge" + binding: 16 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv50 # "Uge" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td50 + word_offset: { binding: 1214, set: 1210 } + - &db17 + spirv_id: 20 + name: "Slt" + binding: 17 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv53 # "Slt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td53 + word_offset: { binding: 1239, set: 1235 } + - &db18 + spirv_id: 21 + name: "Sle" + binding: 18 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv56 # "Sle" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td56 + word_offset: { binding: 1264, set: 1260 } + - &db19 + spirv_id: 22 + name: "Sgt" + binding: 19 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv59 # "Sgt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td59 + word_offset: { binding: 1289, set: 1285 } + - &db20 + spirv_id: 23 + name: "Sge" + binding: 20 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv62 # "Sge" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td62 + word_offset: { binding: 1314, set: 1310 } + - &db21 + spirv_id: 24 + name: "Lor" + binding: 21 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv65 # "Lor" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td65 + word_offset: { binding: 1339, set: 1335 } + - &db22 + spirv_id: 25 + name: "Land" + binding: 22 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv68 # "Land" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td68 + word_offset: { binding: 1364, set: 1360 } + - &db23 + spirv_id: 26 + name: "Lnot" + binding: 23 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv71 # "Lnot" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td71 + word_offset: { binding: 1389, set: 1385 } + - &db24 + spirv_id: 27 + name: "And" + binding: 24 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv74 # "And" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td74 + word_offset: { binding: 1414, set: 1410 } + - &db25 + spirv_id: 28 + name: "Or" + binding: 25 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv77 # "Or" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td77 + word_offset: { binding: 1439, set: 1435 } + - &db26 + spirv_id: 29 + name: "Xor" + binding: 26 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv80 # "Xor" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td80 + word_offset: { binding: 1464, set: 1460 } + - &db27 + spirv_id: 30 + name: "Not" + binding: 27 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv83 # "Not" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td83 + word_offset: { binding: 1489, set: 1485 } + - &db28 + spirv_id: 31 + name: "Leq" + binding: 28 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv86 # "Leq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td86 + word_offset: { binding: 1514, set: 1510 } + - &db29 + spirv_id: 32 + name: "Lneq" + binding: 29 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv89 # "Lneq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td89 + word_offset: { binding: 1539, set: 1535 } + - &db30 + spirv_id: 33 + name: "Sel" + binding: 30 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv92 # "Sel" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td92 + word_offset: { binding: 1564, set: 1560 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 31 + descriptor_bindings: + - *db0 # "IAdd" + - *db1 # "ISub" + - *db2 # "IMul" + - *db3 # "UDiv" + - *db4 # "SDiv" + - *db5 # "SRem" + - *db6 # "SMod" + - *db7 # "UMod" + - *db8 # "LShl" + - *db9 # "RShl" + - *db10 # "RSha" + - *db11 # "IEq" + - *db12 # "INeq" + - *db13 # "Ult" + - *db14 # "Ule" + - *db15 # "Ugt" + - *db16 # "Uge" + - *db17 # "Slt" + - *db18 # "Sle" + - *db19 # "Sgt" + - *db20 # "Sge" + - *db21 # "Lor" + - *db22 # "Land" + - *db23 # "Lnot" + - *db24 # "And" + - *db25 # "Or" + - *db26 # "Xor" + - *db27 # "Not" + - *db28 # "Leq" + - *db29 # "Lneq" + - *db30 # "Sel" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 31 + bindings: + - *db0 # "IAdd" + - *db1 # "ISub" + - *db2 # "IMul" + - *db3 # "UDiv" + - *db4 # "SDiv" + - *db5 # "SRem" + - *db6 # "SMod" + - *db7 # "UMod" + - *db8 # "LShl" + - *db9 # "RShl" + - *db10 # "RSha" + - *db11 # "IEq" + - *db12 # "INeq" + - *db13 # "Ult" + - *db14 # "Ule" + - *db15 # "Ugt" + - *db16 # "Uge" + - *db17 # "Slt" + - *db18 # "Sle" + - *db19 # "Sgt" + - *db20 # "Sge" + - *db21 # "Lor" + - *db22 # "Land" + - *db23 # "Lnot" + - *db24 # "And" + - *db25 # "Or" + - *db26 # "Xor" + - *db27 # "Not" + - *db28 # "Leq" + - *db29 # "Lneq" + - *db30 # "Sel" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 9, + specialization_constants: + - name: "SONE" + spirv_id: 34 + constant_id: 2 + - name: "STWO" + spirv_id: 35 + constant_id: 3 + - name: "UONE" + spirv_id: 36 + constant_id: 5 + - name: "UTWO" + spirv_id: 37 + constant_id: 6 + - name: "SNEG_TWO" + spirv_id: 40 + constant_id: 4 + - name: "SNEG_THREE" + spirv_id: 47 + constant_id: 7 + - name: + spirv_id: 135 + constant_id: 8 + - name: "TRUE" + spirv_id: 102 + constant_id: 0 + - name: "FALSE" + spirv_id: 103 + constant_id: 1 +... diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv b/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv new file mode 100644 index 0000000..e739b65 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv.yaml b/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv.yaml new file mode 100644 index 0000000..7fad803 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spec_constants/test_64bit.spv.yaml @@ -0,0 +1,3839 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 104 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 39 + op: 30 + type_name: "SSBO_IAdd" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 105 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 42 + op: 30 + type_name: "SSBO_ISub" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 + - &td6 + id: 106 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td7 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 44 + op: 30 + type_name: "SSBO_IMul" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td6 + - *td7 + - &td9 + id: 107 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [134,], stride: 4 } + member_count: 0 + members: + - &td10 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 46 + op: 30 + type_name: "SSBO_UDiv" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td9 + - *td10 + - &td12 + id: 108 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td13 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 49 + op: 30 + type_name: "SSBO_SDiv" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td12 + - *td13 + - &td15 + id: 109 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td16 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td17 + id: 51 + op: 30 + type_name: "SSBO_SRem" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td15 + - *td16 + - &td18 + id: 110 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td19 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td20 + id: 53 + op: 30 + type_name: "SSBO_SMod" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td18 + - *td19 + - &td21 + id: 111 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td22 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td23 + id: 55 + op: 30 + type_name: "SSBO_UMod" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td21 + - *td22 + - &td24 + id: 112 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td25 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td26 + id: 57 + op: 30 + type_name: "SSBO_LShl" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td24 + - *td25 + - &td27 + id: 113 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td28 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td29 + id: 59 + op: 30 + type_name: "SSBO_RShl" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td27 + - *td28 + - &td30 + id: 114 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td31 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td32 + id: 61 + op: 30 + type_name: "SSBO_RSha" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td30 + - *td31 + - &td33 + id: 115 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td34 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td35 + id: 63 + op: 30 + type_name: "SSBO_IEq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td33 + - *td34 + - &td36 + id: 116 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td37 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td38 + id: 65 + op: 30 + type_name: "SSBO_INeq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td36 + - *td37 + - &td39 + id: 117 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td40 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td41 + id: 67 + op: 30 + type_name: "SSBO_Ult" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td39 + - *td40 + - &td42 + id: 118 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td43 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td44 + id: 69 + op: 30 + type_name: "SSBO_Ule" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td42 + - *td43 + - &td45 + id: 119 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td46 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td47 + id: 71 + op: 30 + type_name: "SSBO_Ugt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td45 + - *td46 + - &td48 + id: 120 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td49 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td50 + id: 73 + op: 30 + type_name: "SSBO_Uge" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td48 + - *td49 + - &td51 + id: 121 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td52 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td53 + id: 75 + op: 30 + type_name: "SSBO_Slt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td51 + - *td52 + - &td54 + id: 122 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td55 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td56 + id: 77 + op: 30 + type_name: "SSBO_Sle" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td54 + - *td55 + - &td57 + id: 123 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td58 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td59 + id: 79 + op: 30 + type_name: "SSBO_Sgt" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td57 + - *td58 + - &td60 + id: 124 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td61 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td62 + id: 81 + op: 30 + type_name: "SSBO_Sge" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td60 + - *td61 + - &td63 + id: 125 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td64 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td65 + id: 83 + op: 30 + type_name: "SSBO_Lor" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td63 + - *td64 + - &td66 + id: 126 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td67 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td68 + id: 85 + op: 30 + type_name: "SSBO_Land" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td66 + - *td67 + - &td69 + id: 127 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td70 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td71 + id: 87 + op: 30 + type_name: "SSBO_Lnot" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td69 + - *td70 + - &td72 + id: 128 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td73 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td74 + id: 89 + op: 30 + type_name: "SSBO_And" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td72 + - *td73 + - &td75 + id: 129 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td76 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td77 + id: 91 + op: 30 + type_name: "SSBO_Or" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td75 + - *td76 + - &td78 + id: 130 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [128,], stride: 4 } + member_count: 0 + members: + - &td79 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td80 + id: 93 + op: 30 + type_name: "SSBO_Xor" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td78 + - *td79 + - &td81 + id: 131 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [130,], stride: 4 } + member_count: 0 + members: + - &td82 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td83 + id: 95 + op: 30 + type_name: "SSBO_Not" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td81 + - *td82 + - &td84 + id: 132 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td85 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td86 + id: 97 + op: 30 + type_name: "SSBO_Leq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td84 + - *td85 + - &td87 + id: 133 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td88 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td89 + id: 99 + op: 30 + type_name: "SSBO_Lneq" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td87 + - *td88 + - &td90 + id: 134 + op: 28 + type_name: + struct_member_name: "val" + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [169,], stride: 4 } + member_count: 0 + members: + - &td91 + id: 139 + op: 22 + type_name: + struct_member_name: "dummy" + storage_class: 0 # UniformConstant + type_flags: 0x00000008 # FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td92 + id: 101 + op: 30 + type_name: "SSBO_Sel" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td90 + - *td91 +all_block_variables: + - &bv0 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "IAdd" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv0 + - *bv1 + type_description: *td2 + - &bv3 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "ISub" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv3 + - *bv4 + type_description: *td5 + - &bv6 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "IMul" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv6 + - *bv7 + type_description: *td8 + - &bv9 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [134,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "UDiv" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv9 + - *bv10 + type_description: *td11 + - &bv12 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td13 + - &bv14 + name: "SDiv" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv12 + - *bv13 + type_description: *td14 + - &bv15 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td16 + - &bv17 + name: "SRem" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv15 + - *bv16 + type_description: *td17 + - &bv18 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td18 + - &bv19 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td19 + - &bv20 + name: "SMod" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv18 + - *bv19 + type_description: *td20 + - &bv21 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td21 + - &bv22 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td22 + - &bv23 + name: "UMod" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv21 + - *bv22 + type_description: *td23 + - &bv24 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td24 + - &bv25 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td25 + - &bv26 + name: "LShl" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv24 + - *bv25 + type_description: *td26 + - &bv27 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td27 + - &bv28 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td28 + - &bv29 + name: "RShl" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv27 + - *bv28 + type_description: *td29 + - &bv30 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td30 + - &bv31 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td31 + - &bv32 + name: "RSha" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv30 + - *bv31 + type_description: *td32 + - &bv33 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td33 + - &bv34 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td34 + - &bv35 + name: "IEq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv33 + - *bv34 + type_description: *td35 + - &bv36 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td36 + - &bv37 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td37 + - &bv38 + name: "INeq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv36 + - *bv37 + type_description: *td38 + - &bv39 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td39 + - &bv40 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td40 + - &bv41 + name: "Ult" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv39 + - *bv40 + type_description: *td41 + - &bv42 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td42 + - &bv43 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td43 + - &bv44 + name: "Ule" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv42 + - *bv43 + type_description: *td44 + - &bv45 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td45 + - &bv46 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td46 + - &bv47 + name: "Ugt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv45 + - *bv46 + type_description: *td47 + - &bv48 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td48 + - &bv49 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td49 + - &bv50 + name: "Uge" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv48 + - *bv49 + type_description: *td50 + - &bv51 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td51 + - &bv52 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td52 + - &bv53 + name: "Slt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv51 + - *bv52 + type_description: *td53 + - &bv54 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td54 + - &bv55 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td55 + - &bv56 + name: "Sle" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv54 + - *bv55 + type_description: *td56 + - &bv57 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td57 + - &bv58 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td58 + - &bv59 + name: "Sgt" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv57 + - *bv58 + type_description: *td59 + - &bv60 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td60 + - &bv61 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td61 + - &bv62 + name: "Sge" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv60 + - *bv61 + type_description: *td62 + - &bv63 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td63 + - &bv64 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td64 + - &bv65 + name: "Lor" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv63 + - *bv64 + type_description: *td65 + - &bv66 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td66 + - &bv67 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td67 + - &bv68 + name: "Land" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv66 + - *bv67 + type_description: *td68 + - &bv69 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td69 + - &bv70 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td70 + - &bv71 + name: "Lnot" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv69 + - *bv70 + type_description: *td71 + - &bv72 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td72 + - &bv73 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td73 + - &bv74 + name: "And" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv72 + - *bv73 + type_description: *td74 + - &bv75 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td75 + - &bv76 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td76 + - &bv77 + name: "Or" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv75 + - *bv76 + type_description: *td77 + - &bv78 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [128,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td78 + - &bv79 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td79 + - &bv80 + name: "Xor" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv78 + - *bv79 + type_description: *td80 + - &bv81 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [130,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td81 + - &bv82 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td82 + - &bv83 + name: "Not" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv81 + - *bv82 + type_description: *td83 + - &bv84 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td84 + - &bv85 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td85 + - &bv86 + name: "Leq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv84 + - *bv85 + type_description: *td86 + - &bv87 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td87 + - &bv88 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td88 + - &bv89 + name: "Lneq" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv87 + - *bv88 + type_description: *td89 + - &bv90 + name: "val" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [169,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td90 + - &bv91 + name: "dummy" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td91 + - &bv92 + name: "Sel" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv90 + - *bv91 + type_description: *td92 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "IAdd" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv2 # "IAdd" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td2 + word_offset: { binding: 808, set: 804 } + - &db1 + spirv_id: 4 + name: "ISub" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "ISub" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 837, set: 833 } + - &db2 + spirv_id: 5 + name: "IMul" + binding: 2 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv8 # "IMul" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 862, set: 858 } + - &db3 + spirv_id: 6 + name: "UDiv" + binding: 3 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "UDiv" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 887, set: 883 } + - &db4 + spirv_id: 7 + name: "SDiv" + binding: 4 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv14 # "SDiv" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td14 + word_offset: { binding: 916, set: 912 } + - &db5 + spirv_id: 8 + name: "SRem" + binding: 5 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv17 # "SRem" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 941, set: 937 } + - &db6 + spirv_id: 9 + name: "SMod" + binding: 6 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv20 # "SMod" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td20 + word_offset: { binding: 966, set: 962 } + - &db7 + spirv_id: 10 + name: "UMod" + binding: 7 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv23 # "UMod" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td23 + word_offset: { binding: 991, set: 987 } + - &db8 + spirv_id: 11 + name: "LShl" + binding: 8 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv26 # "LShl" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td26 + word_offset: { binding: 1016, set: 1012 } + - &db9 + spirv_id: 12 + name: "RShl" + binding: 9 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv29 # "RShl" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td29 + word_offset: { binding: 1041, set: 1037 } + - &db10 + spirv_id: 13 + name: "RSha" + binding: 10 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv32 # "RSha" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td32 + word_offset: { binding: 1066, set: 1062 } + - &db11 + spirv_id: 14 + name: "IEq" + binding: 11 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv35 # "IEq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td35 + word_offset: { binding: 1091, set: 1087 } + - &db12 + spirv_id: 15 + name: "INeq" + binding: 12 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv38 # "INeq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td38 + word_offset: { binding: 1116, set: 1112 } + - &db13 + spirv_id: 16 + name: "Ult" + binding: 13 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv41 # "Ult" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td41 + word_offset: { binding: 1141, set: 1137 } + - &db14 + spirv_id: 17 + name: "Ule" + binding: 14 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv44 # "Ule" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td44 + word_offset: { binding: 1166, set: 1162 } + - &db15 + spirv_id: 18 + name: "Ugt" + binding: 15 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv47 # "Ugt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td47 + word_offset: { binding: 1191, set: 1187 } + - &db16 + spirv_id: 19 + name: "Uge" + binding: 16 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv50 # "Uge" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td50 + word_offset: { binding: 1216, set: 1212 } + - &db17 + spirv_id: 20 + name: "Slt" + binding: 17 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv53 # "Slt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td53 + word_offset: { binding: 1241, set: 1237 } + - &db18 + spirv_id: 21 + name: "Sle" + binding: 18 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv56 # "Sle" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td56 + word_offset: { binding: 1266, set: 1262 } + - &db19 + spirv_id: 22 + name: "Sgt" + binding: 19 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv59 # "Sgt" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td59 + word_offset: { binding: 1291, set: 1287 } + - &db20 + spirv_id: 23 + name: "Sge" + binding: 20 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv62 # "Sge" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td62 + word_offset: { binding: 1316, set: 1312 } + - &db21 + spirv_id: 24 + name: "Lor" + binding: 21 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv65 # "Lor" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td65 + word_offset: { binding: 1341, set: 1337 } + - &db22 + spirv_id: 25 + name: "Land" + binding: 22 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv68 # "Land" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td68 + word_offset: { binding: 1366, set: 1362 } + - &db23 + spirv_id: 26 + name: "Lnot" + binding: 23 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv71 # "Lnot" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td71 + word_offset: { binding: 1391, set: 1387 } + - &db24 + spirv_id: 27 + name: "And" + binding: 24 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv74 # "And" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td74 + word_offset: { binding: 1416, set: 1412 } + - &db25 + spirv_id: 28 + name: "Or" + binding: 25 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv77 # "Or" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td77 + word_offset: { binding: 1441, set: 1437 } + - &db26 + spirv_id: 29 + name: "Xor" + binding: 26 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv80 # "Xor" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td80 + word_offset: { binding: 1466, set: 1462 } + - &db27 + spirv_id: 30 + name: "Not" + binding: 27 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv83 # "Not" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td83 + word_offset: { binding: 1491, set: 1487 } + - &db28 + spirv_id: 31 + name: "Leq" + binding: 28 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv86 # "Leq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td86 + word_offset: { binding: 1516, set: 1512 } + - &db29 + spirv_id: 32 + name: "Lneq" + binding: 29 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv89 # "Lneq" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td89 + word_offset: { binding: 1541, set: 1537 } + - &db30 + spirv_id: 33 + name: "Sel" + binding: 30 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv92 # "Sel" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td92 + word_offset: { binding: 1566, set: 1562 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 31 + descriptor_bindings: + - *db0 # "IAdd" + - *db1 # "ISub" + - *db2 # "IMul" + - *db3 # "UDiv" + - *db4 # "SDiv" + - *db5 # "SRem" + - *db6 # "SMod" + - *db7 # "UMod" + - *db8 # "LShl" + - *db9 # "RShl" + - *db10 # "RSha" + - *db11 # "IEq" + - *db12 # "INeq" + - *db13 # "Ult" + - *db14 # "Ule" + - *db15 # "Ugt" + - *db16 # "Uge" + - *db17 # "Slt" + - *db18 # "Sle" + - *db19 # "Sgt" + - *db20 # "Sge" + - *db21 # "Lor" + - *db22 # "Land" + - *db23 # "Lnot" + - *db24 # "And" + - *db25 # "Or" + - *db26 # "Xor" + - *db27 # "Not" + - *db28 # "Leq" + - *db29 # "Lneq" + - *db30 # "Sel" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 31 + bindings: + - *db0 # "IAdd" + - *db1 # "ISub" + - *db2 # "IMul" + - *db3 # "UDiv" + - *db4 # "SDiv" + - *db5 # "SRem" + - *db6 # "SMod" + - *db7 # "UMod" + - *db8 # "LShl" + - *db9 # "RShl" + - *db10 # "RSha" + - *db11 # "IEq" + - *db12 # "INeq" + - *db13 # "Ult" + - *db14 # "Ule" + - *db15 # "Ugt" + - *db16 # "Uge" + - *db17 # "Slt" + - *db18 # "Sle" + - *db19 # "Sgt" + - *db20 # "Sge" + - *db21 # "Lor" + - *db22 # "Land" + - *db23 # "Lnot" + - *db24 # "And" + - *db25 # "Or" + - *db26 # "Xor" + - *db27 # "Not" + - *db28 # "Leq" + - *db29 # "Lneq" + - *db30 # "Sel" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 9, + specialization_constants: + - name: "SONE" + spirv_id: 34 + constant_id: 2 + - name: "STWO" + spirv_id: 35 + constant_id: 3 + - name: "UONE" + spirv_id: 36 + constant_id: 5 + - name: "UTWO" + spirv_id: 37 + constant_id: 6 + - name: "SNEG_TWO" + spirv_id: 40 + constant_id: 4 + - name: "SNEG_THREE" + spirv_id: 47 + constant_id: 7 + - name: + spirv_id: 135 + constant_id: 8 + - name: "TRUE" + spirv_id: 102 + constant_id: 0 + - name: "FALSE" + spirv_id: 103 + constant_id: 1 +... diff --git a/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.hlsl b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.hlsl new file mode 100644 index 0000000..50cd4c3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.hlsl @@ -0,0 +1,6 @@ +Texture2D Tex0; + +float4 vsmain(float4 P : POSITION, uint instanceId :SV_InstanceID) : SV_Position +{ + return P + Tex0[uint2(instanceId % 16, instanceId / 16)]; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv new file mode 100644 index 0000000..ecb893d Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv.yaml b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv.yaml new file mode 100644 index 0000000..5e664a1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/spirv15/VertexShader.spv.yaml @@ -0,0 +1,192 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 25 + type_name: "type.2d.image" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00010008 # EXTERNAL_IMAGE FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 13 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 8 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: +all_descriptor_bindings: + - &db0 + spirv_id: 7 + name: "Tex0" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 2 # VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + resource_type: 4 # SRV + image: { dim: 1, depth: 2, arrayed: 0, ms: 0, sampled: 1, image_format: 0 } # dim=2D image_format=Unknown + block: *bv0 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td0 + word_offset: { binding: 76, set: 72 } +all_interface_variables: + - &iv0 + spirv_id: 2 + name: "in.var.POSITION" + location: 0 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000000 # NONE + built_in: -1 # ??? (-1) + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 68 } + - &iv1 + spirv_id: 3 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 43 # InstanceIndex + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } + - &iv2 + spirv_id: 4 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 4425 # BaseInstance + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } + - &iv3 + spirv_id: 5 + name: + location: 4294967295 + storage_class: 3 # Output + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 0 # Position + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 109 # VK_FORMAT_R32G32B32A32_SFLOAT + type_description: *td1 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "vsmain" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 0 # Vertex + shader_stage: 0x00000001 # VS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "Tex0" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "Tex0" + input_variable_count: 3, + input_variables: + - *iv0 # "in.var.POSITION" + - *iv1 # + - *iv2 # + output_variable_count: 1, + output_variables: + - *iv3 # + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/test-spirv-reflect.cpp b/lib/All/SPIRV-Reflect/tests/test-spirv-reflect.cpp new file mode 100644 index 0000000..0d1c765 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/test-spirv-reflect.cpp @@ -0,0 +1,1292 @@ +#include +#include +#include +#include +#include +#include + +#include "../common/output_stream.h" +#include "gtest/gtest.h" +#include "spirv_reflect.h" + +#if defined(_MSC_VER) +#include +#define posix_chdir(d) _chdir(d) +#else +#include +#define posix_chdir(d) chdir(d) +#endif + +#if defined(SPIRV_REFLECT_HAS_VULKAN_H) +// clang-format off +// Verify that SpvReflect enums match their Vk equivalents where appropriate +#include +// SpvReflectFormat == VkFormat +static_assert((uint32_t)SPV_REFLECT_FORMAT_UNDEFINED == (uint32_t)VK_FORMAT_UNDEFINED, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32_UINT == (uint32_t)VK_FORMAT_R32_UINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32_SINT == (uint32_t)VK_FORMAT_R32_SINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32_SFLOAT == (uint32_t)VK_FORMAT_R32_SFLOAT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32_UINT == (uint32_t)VK_FORMAT_R32G32_UINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32_SINT == (uint32_t)VK_FORMAT_R32G32_SINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32_SFLOAT == (uint32_t)VK_FORMAT_R32G32_SFLOAT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32_UINT == (uint32_t)VK_FORMAT_R32G32B32_UINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32_SINT == (uint32_t)VK_FORMAT_R32G32B32_SINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32_SFLOAT == (uint32_t)VK_FORMAT_R32G32B32_SFLOAT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32A32_UINT == (uint32_t)VK_FORMAT_R32G32B32A32_UINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32A32_SINT == (uint32_t)VK_FORMAT_R32G32B32A32_SINT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT == (uint32_t)VK_FORMAT_R32G32B32A32_SFLOAT, "SpvReflect/Vk enum mismatch"); +// SpvReflectDescriptorType == VkDescriptorType +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER == (uint32_t)VK_DESCRIPTOR_TYPE_SAMPLER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER == (uint32_t)VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE == (uint32_t)VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE == (uint32_t)VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER == (uint32_t)VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == (uint32_t)VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER == (uint32_t)VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER == (uint32_t)VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == (uint32_t)VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC == (uint32_t)VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT == (uint32_t)VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "SpvReflect/Vk enum mismatch"); +// SpvReflectShaderStageFlagBits == VkShaderStageFlagBits +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_VERTEX_BIT == (uint32_t)VK_SHADER_STAGE_VERTEX_BIT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT == (uint32_t)VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT == (uint32_t)VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT == (uint32_t)VK_SHADER_STAGE_GEOMETRY_BIT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT == (uint32_t)VK_SHADER_STAGE_FRAGMENT_BIT, "SpvReflect/Vk enum mismatch"); +static_assert((uint32_t)SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT == (uint32_t)VK_SHADER_STAGE_COMPUTE_BIT, "SpvReflect/Vk enum mismatch"); +#endif // defined(SPIRV_REFLECT_HAS_VULKAN_H) +// clang-format on + +TEST(SpirvReflectTestCase, SourceLanguage) { + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageESSL), "ESSL"); + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageGLSL), "GLSL"); + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageOpenCL_C), "OpenCL_C"); + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageOpenCL_CPP), + "OpenCL_CPP"); + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageHLSL), "HLSL"); + + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageUnknown), "Unknown"); + // Invalid inputs + EXPECT_STREQ(spvReflectSourceLanguage(SpvSourceLanguageMax), "Unknown"); + EXPECT_STREQ(spvReflectSourceLanguage( + static_cast(SpvSourceLanguageMax - 1)), + "Unknown"); +} + +class SpirvReflectTest : public ::testing::TestWithParam { + public: + // optional: initialize static data to be shared by all tests in this test + // case. Note that for parameterized tests, the specific parameter value is a + // non-static member data + static void SetUpTestCase() { + FILE* f = fopen("tests/glsl/built_in_format.spv", "r"); + if (!f) { + posix_chdir(".."); + f = fopen("tests/glsl/built_in_format.spv", "r"); + } + EXPECT_NE(f, nullptr) << "Couldn't find test shaders!"; + if (f) { + fclose(f); + } + } + static void TearDownTestCase() {} + + protected: + SpirvReflectTest() { + // set-up work for each test + } + + ~SpirvReflectTest() override { + // clean-up work that doesn't throw exceptions + } + + // optional: called after constructor & before destructor, respectively. + // Used if you have initialization steps that can throw exceptions or must + // otherwise be deferred. + void SetUp() override { + // called after constructor before each test + spirv_path_ = GetParam(); + std::ifstream spirv_file(spirv_path_, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + } + + // optional: + void TearDown() override { + // called before destructor after all tests + spvReflectDestroyShaderModule(&module_); + } + + // members here will be accessible in all tests in this test case + std::string spirv_path_; + std::vector spirv_; + SpvReflectShaderModule module_; + + // static members will be accessible to all tests in this test case + static std::string test_shaders_dir; +}; + +TEST_P(SpirvReflectTest, GetCodeSize) { + EXPECT_EQ(spvReflectGetCodeSize(&module_), spirv_.size()); +} +TEST(SpirvReflectTestCase, GetCodeSize_Errors) { + // NULL module + EXPECT_EQ(spvReflectGetCodeSize(nullptr), 0); +} + +TEST_P(SpirvReflectTest, GetCode) { + int code_compare = + memcmp(spvReflectGetCode(&module_), spirv_.data(), spirv_.size()); + EXPECT_EQ(code_compare, 0); +} +TEST(SpirvReflectTestCase, GetCode_Errors) { + // NULL module + EXPECT_EQ(spvReflectGetCode(nullptr), nullptr); +} + +TEST_P(SpirvReflectTest, GetDescriptorBinding) { + uint32_t binding_count = 0; + SpvReflectResult result; + result = + spvReflectEnumerateDescriptorBindings(&module_, &binding_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector bindings(binding_count); + result = spvReflectEnumerateDescriptorBindings(&module_, &binding_count, + bindings.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* db : bindings) { + const SpvReflectDescriptorBinding* also_db = + spvReflectGetDescriptorBinding(&module_, db->binding, db->set, &result); + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(db, also_db); + } +} +TEST_P(SpirvReflectTest, EnumerateDescriptorBindings_Errors) { + uint32_t binding_count = 0; + // NULL module + EXPECT_EQ( + spvReflectEnumerateDescriptorBindings(nullptr, &binding_count, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL binding count + EXPECT_EQ(spvReflectEnumerateDescriptorBindings(&module_, nullptr, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // binding count / module binding count mismatch + EXPECT_EQ( + spvReflectEnumerateDescriptorBindings(&module_, &binding_count, nullptr), + SPV_REFLECT_RESULT_SUCCESS); + uint32_t bad_binding_count = binding_count + 1; + std::vector bindings(bad_binding_count); + EXPECT_EQ(spvReflectEnumerateDescriptorBindings(&module_, &bad_binding_count, + bindings.data()), + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH); +} +TEST_P(SpirvReflectTest, GetDescriptorBinding_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetDescriptorBinding(nullptr, 0, 0, nullptr), nullptr); + EXPECT_EQ(spvReflectGetDescriptorBinding(nullptr, 0, 0, &result), nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // Invalid binding number + EXPECT_EQ(spvReflectGetDescriptorBinding(&module_, 0xdeadbeef, 0, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetDescriptorBinding(&module_, 0xdeadbeef, 0, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // Invalid set number + EXPECT_EQ(spvReflectGetDescriptorBinding(&module_, 0, 0xdeadbeef, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetDescriptorBinding(&module_, 0, 0xdeadbeef, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetDescriptorSet) { + uint32_t set_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector sets(set_count); + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, sets.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* ds : sets) { + const SpvReflectDescriptorSet* also_ds = + spvReflectGetDescriptorSet(&module_, ds->set, &result); + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(ds, also_ds); + } +} +TEST_P(SpirvReflectTest, EnumerateDescriptorSets_Errors) { + uint32_t set_count = 0; + // NULL module + EXPECT_EQ(spvReflectEnumerateDescriptorSets(nullptr, &set_count, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL set count + EXPECT_EQ(spvReflectEnumerateDescriptorSets(&module_, nullptr, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // set count / module set count mismatch + EXPECT_EQ(spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr), + SPV_REFLECT_RESULT_SUCCESS); + uint32_t bad_set_count = set_count + 1; + std::vector sets(bad_set_count); + EXPECT_EQ( + spvReflectEnumerateDescriptorSets(&module_, &bad_set_count, sets.data()), + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH); +} +TEST_P(SpirvReflectTest, GetDescriptorSet_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetDescriptorSet(nullptr, 0, nullptr), nullptr); + EXPECT_EQ(spvReflectGetDescriptorSet(nullptr, 0, &result), nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // Invalid set number + EXPECT_EQ(spvReflectGetDescriptorSet(&module_, 0xdeadbeef, nullptr), nullptr); + EXPECT_EQ(spvReflectGetDescriptorSet(&module_, 0xdeadbeef, &result), nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetInputVariableByLocation) { + uint32_t iv_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateInputVariables(&module_, &iv_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector ivars(iv_count); + result = spvReflectEnumerateInputVariables(&module_, &iv_count, ivars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* iv : ivars) { + const SpvReflectInterfaceVariable* also_iv = + spvReflectGetInputVariableByLocation(&module_, iv->location, &result); + if (iv->location == UINT32_MAX) { + // Not all elements have valid locations. + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + EXPECT_EQ(also_iv, nullptr); + } else { + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(iv, also_iv); + } + } +} +TEST_P(SpirvReflectTest, EnumerateInputVariables_Errors) { + uint32_t var_count = 0; + // NULL module + EXPECT_EQ(spvReflectEnumerateInputVariables(nullptr, &var_count, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL var count + EXPECT_EQ(spvReflectEnumerateInputVariables(&module_, nullptr, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // var count / module var count mismatch + EXPECT_EQ(spvReflectEnumerateInputVariables(&module_, &var_count, nullptr), + SPV_REFLECT_RESULT_SUCCESS); + uint32_t bad_var_count = var_count + 1; + std::vector vars(bad_var_count); + EXPECT_EQ( + spvReflectEnumerateInputVariables(&module_, &bad_var_count, vars.data()), + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH); +} +TEST_P(SpirvReflectTest, GetInputVariableByLocation_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetInputVariableByLocation(nullptr, 0, nullptr), nullptr); + EXPECT_EQ(spvReflectGetInputVariableByLocation(nullptr, 0, &result), nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // explicitly invalid location (UINT32_MAX is *always* not found) + EXPECT_EQ(spvReflectGetInputVariableByLocation(&module_, UINT32_MAX, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableByLocation(&module_, UINT32_MAX, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // implicitly invalid location (0xdeadbeef is potentially valid) + EXPECT_EQ(spvReflectGetInputVariableByLocation(&module_, 0xdeadbeef, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableByLocation(&module_, 0xdeadbeef, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetInputVariableBySemantic) { + uint32_t iv_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateInputVariables(&module_, &iv_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector ivars(iv_count); + result = spvReflectEnumerateInputVariables(&module_, &iv_count, ivars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* iv : ivars) { + const SpvReflectInterfaceVariable* also_iv = + spvReflectGetInputVariableBySemantic(&module_, iv->semantic, &result); + if (iv->semantic == nullptr) { + // Not all elements have valid semantics + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + EXPECT_EQ(also_iv, nullptr); + } else if (iv->semantic[0] == '\0') { + // Not all elements have valid semantics + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + EXPECT_EQ(also_iv, nullptr); + } else { + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(iv, also_iv); + } + } +} +TEST_P(SpirvReflectTest, GetInputVariableBySemantic_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetInputVariableBySemantic(nullptr, nullptr, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableBySemantic(nullptr, nullptr, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL semantic + EXPECT_EQ(spvReflectGetInputVariableBySemantic(&module_, nullptr, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableBySemantic(&module_, nullptr, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // empty semantic ("" is explicitly not found) + EXPECT_EQ(spvReflectGetInputVariableBySemantic(&module_, "", nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableBySemantic(&module_, "", &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // implicitly invalid semantic + EXPECT_EQ(spvReflectGetInputVariableBySemantic( + &module_, "SV_PLAUSIBLE_BUT_INVALID", nullptr), + nullptr); + EXPECT_EQ(spvReflectGetInputVariableBySemantic( + &module_, "SV_PLAUSIBLE_BUT_INVALID", &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetOutputVariableByLocation) { + uint32_t ov_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateOutputVariables(&module_, &ov_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector ovars(ov_count); + result = + spvReflectEnumerateOutputVariables(&module_, &ov_count, ovars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* ov : ovars) { + const SpvReflectInterfaceVariable* also_ov = + spvReflectGetOutputVariableByLocation(&module_, ov->location, &result); + if (ov->location == UINT32_MAX) { + // Not all elements have valid locations. + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + EXPECT_EQ(also_ov, nullptr); + } else { + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(ov, also_ov); + } + } +} +TEST_P(SpirvReflectTest, EnumerateOutputVariables_Errors) { + uint32_t var_count = 0; + // NULL module + EXPECT_EQ(spvReflectEnumerateOutputVariables(nullptr, &var_count, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL var count + EXPECT_EQ(spvReflectEnumerateOutputVariables(&module_, nullptr, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // var count / module var count mismatch + EXPECT_EQ(spvReflectEnumerateOutputVariables(&module_, &var_count, nullptr), + SPV_REFLECT_RESULT_SUCCESS); + uint32_t bad_var_count = var_count + 1; + std::vector vars(bad_var_count); + EXPECT_EQ( + spvReflectEnumerateOutputVariables(&module_, &bad_var_count, vars.data()), + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH); +} +TEST_P(SpirvReflectTest, GetOutputVariableByLocation_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetOutputVariableByLocation(nullptr, 0, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetOutputVariableByLocation(nullptr, 0, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // explicitly invalid location (UINT32_MAX is *always* not found) + EXPECT_EQ( + spvReflectGetOutputVariableByLocation(&module_, UINT32_MAX, nullptr), + nullptr); + EXPECT_EQ( + spvReflectGetOutputVariableByLocation(&module_, UINT32_MAX, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // implicitly invalid location (0xdeadbeef is potentially valid) + EXPECT_EQ( + spvReflectGetOutputVariableByLocation(&module_, 0xdeadbeef, nullptr), + nullptr); + EXPECT_EQ( + spvReflectGetOutputVariableByLocation(&module_, 0xdeadbeef, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetOutputVariableBySemantic) { + uint32_t ov_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateOutputVariables(&module_, &ov_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector ovars(ov_count); + result = + spvReflectEnumerateOutputVariables(&module_, &ov_count, ovars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (const auto* ov : ovars) { + const SpvReflectInterfaceVariable* also_ov = + spvReflectGetOutputVariableBySemantic(&module_, ov->semantic, &result); + if (ov->semantic == nullptr) { + // Not all elements have valid semantics + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + EXPECT_EQ(also_ov, nullptr); + } else if (ov->semantic[0] == '\0') { + // Not all elements have valid semantics + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + EXPECT_EQ(also_ov, nullptr); + } else { + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(ov, also_ov); + } + } +} +TEST_P(SpirvReflectTest, GetOutputVariableBySemantic_Errors) { + SpvReflectResult result; + // NULL module + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(nullptr, nullptr, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(nullptr, nullptr, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL semantic + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(&module_, nullptr, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(&module_, nullptr, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // empty semantic ("" is explicitly not found) + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(&module_, "", nullptr), + nullptr); + EXPECT_EQ(spvReflectGetOutputVariableBySemantic(&module_, "", &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // implicitly invalid semantic + EXPECT_EQ(spvReflectGetOutputVariableBySemantic( + &module_, "SV_PLAUSIBLE_BUT_INVALID", nullptr), + nullptr); + EXPECT_EQ(spvReflectGetOutputVariableBySemantic( + &module_, "SV_PLAUSIBLE_BUT_INVALID", &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, GetPushConstantBlock) { + uint32_t block_count = 0; + SpvReflectResult result; + result = + spvReflectEnumeratePushConstantBlocks(&module_, &block_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + std::vector blocks(block_count); + result = spvReflectEnumeratePushConstantBlocks(&module_, &block_count, + blocks.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + for (uint32_t i = 0; i < block_count; ++i) { + const SpvReflectBlockVariable* b = blocks[i]; + const SpvReflectBlockVariable* also_b = + spvReflectGetPushConstantBlock(&module_, i, &result); + EXPECT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(b, also_b); + } +} +TEST_P(SpirvReflectTest, EnumeratePushConstantBlocks_Errors) { + uint32_t block_count = 0; + // NULL module + EXPECT_EQ( + spvReflectEnumeratePushConstantBlocks(nullptr, &block_count, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL var count + EXPECT_EQ(spvReflectEnumeratePushConstantBlocks(&module_, nullptr, nullptr), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // var count / module var count mismatch + EXPECT_EQ( + spvReflectEnumeratePushConstantBlocks(&module_, &block_count, nullptr), + SPV_REFLECT_RESULT_SUCCESS); + uint32_t bad_block_count = block_count + 1; + std::vector blocks(bad_block_count); + EXPECT_EQ(spvReflectEnumeratePushConstantBlocks(&module_, &bad_block_count, + blocks.data()), + SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH); +} +TEST_P(SpirvReflectTest, GetPushConstantBlock_Errors) { + uint32_t block_count = 0; + SpvReflectResult result; + result = + spvReflectEnumeratePushConstantBlocks(&module_, &block_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + // NULL module + EXPECT_EQ(spvReflectGetPushConstantBlock(nullptr, 0, nullptr), nullptr); + EXPECT_EQ(spvReflectGetPushConstantBlock(nullptr, 0, &result), nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // invalid block index + EXPECT_EQ(spvReflectGetPushConstantBlock(&module_, block_count, nullptr), + nullptr); + EXPECT_EQ(spvReflectGetPushConstantBlock(&module_, block_count, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); +} + +TEST_P(SpirvReflectTest, ChangeDescriptorBindingNumber) { + uint32_t binding_count = 0; + SpvReflectResult result; + result = + spvReflectEnumerateDescriptorBindings(&module_, &binding_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + if (binding_count == 0) { + return; // can't change binding numbers if there are no bindings! + } + std::vector bindings(binding_count); + result = spvReflectEnumerateDescriptorBindings(&module_, &binding_count, + bindings.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + uint32_t set_count = 0; + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_GT(set_count, 0U); + std::vector sets(set_count); + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, sets.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + SpvReflectDescriptorBinding* b = bindings[0]; + const uint32_t new_binding_number = 1000; + const uint32_t set_number = b->set; + // Make sure no binding exists at the binding number we're about to change to. + ASSERT_EQ(spvReflectGetDescriptorBinding(&module_, new_binding_number, + set_number, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // Modify the binding number (leaving the set number unchanged) + result = spvReflectChangeDescriptorBindingNumbers( + &module_, b, new_binding_number, SPV_REFLECT_SET_NUMBER_DONT_CHANGE); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + // We should now be able to retrieve the binding at the new number + const SpvReflectDescriptorBinding* new_binding = + spvReflectGetDescriptorBinding(&module_, new_binding_number, set_number, + &result); + ASSERT_NE(new_binding, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(new_binding->binding, new_binding_number); + EXPECT_EQ(new_binding->set, set_number); + // The set count & sets contents should not have changed, since we didn't + // change the set number. + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(set_count, sets.size()); + std::vector new_sets(set_count); + result = + spvReflectEnumerateDescriptorSets(&module_, &set_count, new_sets.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(sets, new_sets); + + // TODO: confirm that the modified SPIR-V code is still valid, either by + // running spirv-val or calling vkCreateShaderModule(). +} +TEST_P(SpirvReflectTest, ChangeDescriptorBindingNumbers_Errors) { + // NULL module + EXPECT_EQ(spvReflectChangeDescriptorBindingNumbers(nullptr, nullptr, 0, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL descriptor binding + EXPECT_EQ(spvReflectChangeDescriptorBindingNumbers(&module_, nullptr, 0, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); +} + +TEST_P(SpirvReflectTest, ChangeDescriptorSetNumber) { + uint32_t binding_count = 0; + SpvReflectResult result; + result = + spvReflectEnumerateDescriptorBindings(&module_, &binding_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + if (binding_count == 0) { + return; // can't change set numbers if there are no bindings! + } + std::vector bindings(binding_count); + result = spvReflectEnumerateDescriptorBindings(&module_, &binding_count, + bindings.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + uint32_t set_count = 0; + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_GT(set_count, 0U); + std::vector sets(set_count); + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, sets.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + SpvReflectDescriptorSet* s = sets[0]; + + const uint32_t new_set_number = 13; + const uint32_t set_binding_count = s->binding_count; + // Make sure no set exists at the binding number we're about to change to. + ASSERT_EQ(spvReflectGetDescriptorSet(&module_, new_set_number, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // Modify the set number + result = spvReflectChangeDescriptorSetNumber(&module_, s, new_set_number); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + // We should now be able to retrieve the set at the new number + const SpvReflectDescriptorSet* new_set = + spvReflectGetDescriptorSet(&module_, new_set_number, &result); + ASSERT_NE(new_set, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(new_set->set, new_set_number); + EXPECT_EQ(new_set->binding_count, set_binding_count); + // The set count should not have changed, since we didn't + // change the set number. + result = spvReflectEnumerateDescriptorSets(&module_, &set_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(set_count, sets.size()); + + // TODO: confirm that the modified SPIR-V code is still valid, either by + // running spirv-val or calling vkCreateShaderModule(). +} +TEST_P(SpirvReflectTest, ChangeDescriptorSetNumber_Errors) { + // NULL module + EXPECT_EQ(spvReflectChangeDescriptorSetNumber(nullptr, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL descriptor set + EXPECT_EQ(spvReflectChangeDescriptorSetNumber(&module_, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); +} + +TEST_P(SpirvReflectTest, ChangeInputVariableLocation) { + uint32_t iv_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateInputVariables(&module_, &iv_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + if (iv_count == 0) { + return; // can't change variable locations if there are no variables! + } + std::vector ivars(iv_count); + result = spvReflectEnumerateInputVariables(&module_, &iv_count, ivars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + SpvReflectInterfaceVariable* iv = ivars[0]; + + const uint32_t new_location = 37; + // Make sure no var exists at the location we're about to change to. + ASSERT_EQ( + spvReflectGetInputVariableByLocation(&module_, new_location, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // Modify the location + result = spvReflectChangeInputVariableLocation(&module_, iv, new_location); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + // We should now be able to retrieve the variable at its new location + const SpvReflectInterfaceVariable* new_iv = + spvReflectGetInputVariableByLocation(&module_, new_location, &result); + ASSERT_NE(new_iv, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(new_iv->location, new_location); + // The variable count should not have changed + result = spvReflectEnumerateInputVariables(&module_, &iv_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(iv_count, ivars.size()); + + // TODO: confirm that the modified SPIR-V code is still valid, either by + // running spirv-val or calling vkCreateShaderModule(). +} +TEST_P(SpirvReflectTest, ChangeInputVariableLocation_Errors) { + // NULL module + EXPECT_EQ(spvReflectChangeInputVariableLocation(nullptr, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL variable + EXPECT_EQ(spvReflectChangeInputVariableLocation(&module_, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); +} + +TEST_P(SpirvReflectTest, ChangeOutputVariableLocation) { + uint32_t ov_count = 0; + SpvReflectResult result; + result = spvReflectEnumerateOutputVariables(&module_, &ov_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + if (ov_count == 0) { + return; // can't change variable locations if there are no variables! + } + std::vector ovars(ov_count); + result = + spvReflectEnumerateOutputVariables(&module_, &ov_count, ovars.data()); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + + SpvReflectInterfaceVariable* ov = ovars[0]; + + const uint32_t new_location = 37; + // Make sure no var exists at the location we're about to change to. + ASSERT_EQ( + spvReflectGetOutputVariableByLocation(&module_, new_location, &result), + nullptr); + EXPECT_EQ(result, SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND); + // Modify the location + result = spvReflectChangeOutputVariableLocation(&module_, ov, new_location); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + // We should now be able to retrieve the variable at its new location + const SpvReflectInterfaceVariable* new_ov = + spvReflectGetOutputVariableByLocation(&module_, new_location, &result); + ASSERT_NE(new_ov, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(new_ov->location, new_location); + // The variable count should not have changed + result = spvReflectEnumerateOutputVariables(&module_, &ov_count, nullptr); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + EXPECT_EQ(ov_count, ovars.size()); + + // TODO: confirm that the modified SPIR-V code is still valid, either by + // running spirv-val or calling vkCreateShaderModule(). +} +TEST_P(SpirvReflectTest, ChangeOutputVariableLocation_Errors) { + // NULL module + EXPECT_EQ(spvReflectChangeOutputVariableLocation(nullptr, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); + // NULL variable + EXPECT_EQ(spvReflectChangeOutputVariableLocation(&module_, nullptr, 0), + SPV_REFLECT_RESULT_ERROR_NULL_POINTER); +} + +TEST_P(SpirvReflectTest, CheckYamlOutput) { + const uint32_t yaml_verbosity = 1; + SpvReflectToYaml yamlizer(module_, yaml_verbosity); + std::stringstream test_yaml; + test_yaml << yamlizer; + std::string test_yaml_str = test_yaml.str(); + + std::string golden_yaml_path = spirv_path_ + ".yaml"; + std::ifstream golden_yaml_file(golden_yaml_path); + ASSERT_TRUE(golden_yaml_file.good()); + std::stringstream golden_yaml; + golden_yaml << golden_yaml_file.rdbuf(); + golden_yaml_file.close(); + std::string golden_yaml_str = golden_yaml.str(); + + // Quick workaround for potential line ending differences, perf be damned! + test_yaml_str = std::regex_replace(test_yaml_str, std::regex("\r"), ""); + golden_yaml_str = std::regex_replace(golden_yaml_str, std::regex("\r"), ""); + + ASSERT_EQ(test_yaml_str.size(), golden_yaml_str.size()); + // TODO: I wish there were a better way to show what changed, but the + // differences (if any) tend to be pretty large, even for small changes. + bool yaml_contents_match = (test_yaml_str == golden_yaml_str); + EXPECT_TRUE(yaml_contents_match) + << "YAML output mismatch; try regenerating the golden YAML with " + "\"tests/build_golden_yaml.py\" and see what changed."; +} + +namespace { +// TODO - have this glob search all .spv files +const std::vector all_spirv_paths = { + // clang-format off + "../tests/16bit/vert_in_out_16.spv", + "../tests/access_chains/array_length_from_access_chain.spv", + "../tests/access_chains/pointer_access_chain_phy_storage_buffer.spv", + "../tests/cbuffer_unused/cbuffer_unused_001.spv", + "../tests/glsl/built_in_format.spv", + "../tests/entry_exec_mode/comp_local_size.spv", + "../tests/entry_exec_mode/geom_inv_out_vert.spv", + "../tests/execution_mode/local_size_id_spec.spv", + "../tests/execution_mode/local_size_id.spv", + "../tests/glsl/buffer_handle_0.spv", + "../tests/glsl/buffer_handle_1.spv", + "../tests/glsl/buffer_handle_2.spv", + "../tests/glsl/buffer_handle_3.spv", + "../tests/glsl/buffer_handle_4.spv", + "../tests/glsl/buffer_handle_5.spv", + "../tests/glsl/buffer_handle_6.spv", + "../tests/glsl/buffer_handle_7.spv", + "../tests/glsl/buffer_handle_8.spv", + "../tests/glsl/buffer_handle_9.spv", + "../tests/glsl/buffer_handle_uvec2_pc.spv", + "../tests/glsl/buffer_handle_uvec2_ssbo.spv", + "../tests/glsl/buffer_pointer.spv", + "../tests/glsl/built_in_format.spv", + "../tests/glsl/fn_struct_param.spv", + "../tests/glsl/frag_array_input.spv", + "../tests/glsl/frag_barycentric.spv", + "../tests/glsl/input_attachment.spv", + "../tests/glsl/io_vars_vs.spv", + "../tests/glsl/matrix_major_order_glsl.spv", + "../tests/glsl/non_writable_image.spv", + "../tests/glsl/readonly_writeonly.spv", + "../tests/glsl/runtime_array_of_array_of_struct.spv", + "../tests/glsl/storage_buffer.spv", + "../tests/glsl/texel_buffer.spv", + "../tests/hlsl/append_consume.spv", + "../tests/hlsl/array_of_structured_buffer.spv", + "../tests/hlsl/binding_array.spv", + "../tests/hlsl/binding_types.spv", + "../tests/hlsl/cbuffer.spv", + "../tests/hlsl/constantbuffer.spv", + "../tests/hlsl/constantbuffer_nested_structs.spv", + "../tests/hlsl/counter_buffers.spv", + "../tests/hlsl/localsize.spv", + "../tests/hlsl/matrix_major_order_hlsl.spv", + "../tests/hlsl/pushconstant.spv", + "../tests/hlsl/semantics.spv", + "../tests/hlsl/structuredbuffer.spv", + "../tests/hlsl/user_type.spv", + "../tests/interface/geom_input_builtin_array.spv", + "../tests/interface/vertex_input_builtin_block.spv", + "../tests/interface/vertex_input_builtin_non_block.spv", + "../tests/issues/77/hlsl/array_from_ubo.spv", + "../tests/issues/77/hlsl/array_from_ubo_with_O0.spv", + "../tests/issues/77/hlsl/rocketz.spv", + "../tests/issues/102/function_parameter_access.spv", + "../tests/issues/178/vertex_input_struct.spv", + "../tests/issues/178/vertex_input_struct2.spv", + "../tests/issues/227/null_node.spv", + "../tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv", + "../tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv", + "../tests/multi_entrypoint/multi_entrypoint.spv", + "../tests/push_constants/non_zero_block_offset.spv", + "../tests/push_constants/pointer_in_struct.spv", + "../tests/push_constants/pointer_in_struct_2.spv", + "../tests/push_constants/push_constant_basic_0.spv", + "../tests/push_constants/push_constant_basic_1.spv", + "../tests/push_constants/push_constant_basic_2.spv", + "../tests/push_constants/push_constant_basic_3.spv", + "../tests/raytrace/rayquery_equal.cs.spv", + "../tests/raytrace/rayquery_init_ds.spv", + "../tests/raytrace/rayquery_init_gs.spv", + "../tests/raytrace/rayquery_init_hs.spv", + "../tests/raytrace/rayquery_init_ps.spv", + "../tests/raytrace/rayquery_init_rahit.spv", + "../tests/raytrace/rayquery_init_rcall.spv", + "../tests/raytrace/rayquery_init_rchit.spv", + "../tests/raytrace/rayquery_init_rgen.spv", + "../tests/raytrace/rayquery_init_rmiss.spv", + "../tests/raytrace/raytracing.acceleration-structure.spv", + "../tests/raytrace/raytracing.khr.closesthit.spv", + "../tests/raytrace/raytracing.nv.acceleration-structure.spv", + "../tests/raytrace/raytracing.nv.anyhit.spv", + "../tests/raytrace/raytracing.nv.callable.spv", + "../tests/raytrace/raytracing.nv.closesthit.spv", + "../tests/raytrace/raytracing.nv.enum.spv", + "../tests/raytrace/raytracing.nv.intersection.spv", + "../tests/raytrace/raytracing.nv.library.spv", + "../tests/raytrace/raytracing.nv.miss.spv", + "../tests/raytrace/raytracing.nv.raygen.spv", + "../tests/spec_constants/basic.spv", + "../tests/spec_constants/convert.spv", + "../tests/spec_constants/local_size_id_10.spv", + "../tests/spec_constants/local_size_id_13.spv", + "../tests/spec_constants/ssbo_array.spv", + "../tests/spec_constants/test_32bit.spv", + "../tests/spec_constants/test_64bit.spv", + "../tests/spirv15/VertexShader.spv", + "../tests/user_type/byte_address_buffer_0.spv", + "../tests/user_type/byte_address_buffer_1.spv", + "../tests/user_type/byte_address_buffer_2.spv", + "../tests/user_type/byte_address_buffer_3.spv", + "../tests/user_type/rw_byte_address_buffer.spv", + "../tests/variable_access/atomics_0.spv", + "../tests/variable_access/atomics_1.spv", + "../tests/variable_access/copy_array_0.spv", + "../tests/variable_access/copy_array_1.spv", + "../tests/variable_access/copy_array_2.spv", + "../tests/variable_access/copy_array_3.spv", + "../tests/variable_access/copy_memory.spv", + "../tests/variable_access/copy_struct_0.spv", + "../tests/variable_access/copy_struct_1.spv", + "../tests/variable_access/descriptor_indexing_0.spv", + "../tests/variable_access/descriptor_indexing_1.spv", + "../tests/variable_access/phy_storage_buffer_used_0.spv", + "../tests/variable_access/phy_storage_buffer_used_1.spv", + "../tests/variable_access/phy_storage_buffer_used_2.spv", + "../tests/variable_access/phy_storage_buffer_used_3.spv", + // clang-format on +}; +} // namespace +INSTANTIATE_TEST_CASE_P(ForAllShaders, SpirvReflectTest, + ::testing::ValuesIn(all_spirv_paths)); + +TEST(SpirvReflectTestCase, TestComputeLocalSize) { + std::vector spirv_; + SpvReflectShaderModule module_; + const std::string spirv_path = "../tests/entry_exec_mode/comp_local_size.spv"; + std::ifstream spirv_file(spirv_path, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + + ASSERT_EQ(module_.entry_point_count, 1); + ASSERT_EQ(module_.entry_points[0].shader_stage, + SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT); + ASSERT_EQ(module_.entry_points[0].local_size.x, 1); + ASSERT_EQ(module_.entry_points[0].local_size.y, 1); + ASSERT_EQ(module_.entry_points[0].local_size.z, 1); + + spvReflectDestroyShaderModule(&module_); +} + +TEST(SpirvReflectTestCase, TestTaskShaderEXT) { + std::vector spirv_; + SpvReflectShaderModule module_; + const std::string spirv_path = + "../tests/mesh_shader_ext/mesh_shader_ext.task.hlsl.spv"; + std::ifstream spirv_file(spirv_path, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + + ASSERT_EQ(module_.entry_point_count, 1); + ASSERT_EQ(module_.entry_points[0].shader_stage, + SPV_REFLECT_SHADER_STAGE_TASK_BIT_EXT); + + spvReflectDestroyShaderModule(&module_); +} + +TEST(SpirvReflectTestCase, TestMeshShaderEXT) { + std::vector spirv_; + SpvReflectShaderModule module_; + const std::string spirv_path = + "../tests/mesh_shader_ext/mesh_shader_ext.mesh.hlsl.spv"; + std::ifstream spirv_file(spirv_path, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + + ASSERT_EQ(module_.entry_point_count, 1); + ASSERT_EQ(module_.entry_points[0].shader_stage, + SPV_REFLECT_SHADER_STAGE_MESH_BIT_EXT); + + spvReflectDestroyShaderModule(&module_); +} + +TEST(SpirvReflectTestCase, TestGeometryInvocationsOutputVertices) { + std::vector spirv_; + SpvReflectShaderModule module_; + const std::string spirv_path = + "../tests/entry_exec_mode/geom_inv_out_vert.spv"; + std::ifstream spirv_file(spirv_path, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + + ASSERT_EQ(module_.entry_point_count, 1); + ASSERT_EQ(module_.entry_points[0].shader_stage, + SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT); + ASSERT_EQ(module_.entry_points[0].invocations, 2); + ASSERT_EQ(module_.entry_points[0].output_vertices, 2); + + spvReflectDestroyShaderModule(&module_); +} + +class SpirvReflectMultiEntryPointTest : public ::testing::TestWithParam { + protected: + void SetUp() override { + // called after constructor before each test + const std::string spirv_path = + "../tests/multi_entrypoint/multi_entrypoint.spv"; + std::ifstream spirv_file(spirv_path, std::ios::binary | std::ios::ate); + std::streampos spirv_file_nbytes = spirv_file.tellg(); + spirv_file.seekg(0); + spirv_.resize(spirv_file_nbytes); + spirv_file.read(reinterpret_cast(spirv_.data()), spirv_.size()); + + SpvReflectResult result = + spvReflectCreateShaderModule(spirv_.size(), spirv_.data(), &module_); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result) + << "spvReflectCreateShaderModule() failed"; + } + + // optional: + void TearDown() override { + // called before destructor after all tests + spvReflectDestroyShaderModule(&module_); + } + + const char* eps_[2] = {"entry_vert", "entry_frag"}; + std::vector spirv_; + SpvReflectShaderModule module_; +}; + +TEST_F(SpirvReflectMultiEntryPointTest, GetEntryPoint) { + ASSERT_EQ(&module_.entry_points[0], + spvReflectGetEntryPoint(&module_, eps_[0])); + ASSERT_EQ(&module_.entry_points[1], + spvReflectGetEntryPoint(&module_, eps_[1])); + ASSERT_EQ(NULL, spvReflectGetEntryPoint(&module_, "entry_tess")); +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetDescriptorBindings0) { + uint32_t binding_count = 0; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[0], &binding_count, NULL)); + ASSERT_EQ(binding_count, 1); + SpvReflectDescriptorBinding* binding; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[0], &binding_count, &binding)); + ASSERT_EQ(binding->set, 0); + ASSERT_EQ(binding->binding, 1); + ASSERT_EQ(strcmp(binding->name, "ubo"), 0); + ASSERT_EQ(binding->descriptor_type, + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + + SpvReflectResult result; + ASSERT_EQ(binding, + spvReflectGetEntryPointDescriptorBinding( + &module_, eps_[0], binding->binding, binding->set, &result)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetDescriptorBindings1) { + uint32_t binding_count = 0; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[1], &binding_count, NULL)); + ASSERT_EQ(binding_count, 2); + SpvReflectDescriptorBinding* bindings[2]; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[1], &binding_count, bindings)); + ASSERT_EQ(bindings[0]->set, 0); + ASSERT_EQ(bindings[0]->binding, 0); + ASSERT_EQ(strcmp(bindings[0]->name, "tex"), 0); + ASSERT_EQ(bindings[0]->descriptor_type, + SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + + ASSERT_EQ(bindings[1]->set, 0); + ASSERT_EQ(bindings[1]->binding, 1); + ASSERT_EQ(strcmp(bindings[1]->name, "ubo"), 0); + ASSERT_EQ(bindings[1]->descriptor_type, + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + + for (size_t i = 0; i < 2; ++i) { + SpvReflectResult result; + ASSERT_EQ(bindings[i], spvReflectGetEntryPointDescriptorBinding( + &module_, eps_[1], bindings[i]->binding, + bindings[i]->set, &result)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + } +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetDescriptorBindingsShared) { + uint32_t vert_count = 1; + SpvReflectDescriptorBinding* vert_binding; + + uint32_t frag_count = 2; + SpvReflectDescriptorBinding* frag_binding[2]; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[0], &vert_count, &vert_binding)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorBindings( + &module_, eps_[1], &frag_count, frag_binding)); + ASSERT_EQ(vert_binding, frag_binding[1]); +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetDescriptorSets0) { + uint32_t set_count; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorSets(&module_, eps_[0], + &set_count, NULL)); + ASSERT_EQ(set_count, 1); + SpvReflectDescriptorSet* set; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorSets(&module_, eps_[0], + &set_count, &set)); + ASSERT_EQ(set->set, 0); + ASSERT_EQ(set->binding_count, 1); + ASSERT_EQ(set, &module_.entry_points[0].descriptor_sets[0]); + + SpvReflectResult result; + ASSERT_EQ(set, spvReflectGetEntryPointDescriptorSet(&module_, eps_[0], + set->set, &result)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetDescriptorSets1) { + uint32_t set_count; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorSets(&module_, eps_[1], + &set_count, NULL)); + ASSERT_EQ(set_count, 1); + SpvReflectDescriptorSet* set; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointDescriptorSets(&module_, eps_[1], + &set_count, &set)); + ASSERT_EQ(set->set, 0); + ASSERT_EQ(set->binding_count, 2); + ASSERT_EQ(set, &module_.entry_points[1].descriptor_sets[0]); + + SpvReflectResult result; + ASSERT_EQ(set, spvReflectGetEntryPointDescriptorSet(&module_, eps_[1], + set->set, &result)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetInputVariables) { + const uint32_t counts[2] = {2, 1}; + const char* names[2][2] = {{"iUV", "pos"}, {"iUV", NULL}}; + for (size_t i = 0; i < 2; ++i) { + uint32_t count = 0; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointInputVariables(&module_, eps_[i], + &count, NULL)); + ASSERT_EQ(count, counts[i]); + + // 2 is the max count + SpvReflectInterfaceVariable* vars[2]; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointInputVariables(&module_, eps_[i], + &count, vars)); + for (size_t j = 0; j < counts[i]; ++j) { + if (vars[j]->decoration_flags & SPV_REFLECT_DECORATION_BUILT_IN) { + // built-ins don't have reasonable locations + continue; + } + SpvReflectResult result; + const SpvReflectInterfaceVariable* var = + spvReflectGetEntryPointInputVariableByLocation( + &module_, eps_[i], vars[j]->location, &result); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + ASSERT_EQ(var, vars[j]); + ASSERT_EQ(strcmp(var->name, names[i][var->location]), 0); + } + } +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetOutputVariables) { + const uint32_t counts[2] = {2, 1}; + // One of the outputs from the first entry point is a builtin so it has no + // position. + const char* names[2][1] = {{"oUV"}, {"colour"}}; + for (size_t i = 0; i < 2; ++i) { + uint32_t count = 0; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointOutputVariables(&module_, eps_[i], + &count, NULL)); + ASSERT_EQ(count, counts[i]); + + // 2 is the max count + SpvReflectInterfaceVariable* vars[2]; + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointOutputVariables(&module_, eps_[i], + &count, vars)); + for (size_t j = 0; j < counts[i]; ++j) { + if (vars[j]->decoration_flags & SPV_REFLECT_DECORATION_BUILT_IN) { + // built-ins don't have reasonable locations + continue; + } + SpvReflectResult result; + const SpvReflectInterfaceVariable* var = + spvReflectGetEntryPointOutputVariableByLocation( + &module_, eps_[i], vars[j]->location, &result); + ASSERT_EQ(result, SPV_REFLECT_RESULT_SUCCESS); + ASSERT_EQ(var, vars[j]); + ASSERT_EQ(strcmp(var->name, names[i][var->location]), 0); + } + } +} + +TEST_F(SpirvReflectMultiEntryPointTest, GetPushConstants) { + for (size_t i = 0; i < 2; ++i) { + SpvReflectBlockVariable* var; + uint32_t count = 0; + ASSERT_EQ(SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH, + spvReflectEnumerateEntryPointPushConstantBlocks(&module_, eps_[i], + &count, &var)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointPushConstantBlocks(&module_, eps_[i], + &count, NULL)); + ASSERT_EQ(count, 1); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectEnumerateEntryPointPushConstantBlocks(&module_, eps_[i], + &count, &var)); + SpvReflectResult result; + ASSERT_EQ(var, spvReflectGetEntryPointPushConstantBlock(&module_, eps_[i], + &result)); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + } +} + +TEST_F(SpirvReflectMultiEntryPointTest, ChangeDescriptorBindingNumber) { + const SpvReflectDescriptorBinding* binding = + spvReflectGetEntryPointDescriptorBinding(&module_, eps_[0], 1, 0, NULL); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectChangeDescriptorBindingNumbers(&module_, binding, 2, 1)); + // Change descriptor binding numbers doesn't currently resort so it won't + // invalidate binding, but if that changes this test will need to be fixed. + ASSERT_EQ(binding->set, 1); + ASSERT_EQ(binding->binding, 2); + + SpvReflectResult result; + const SpvReflectDescriptorSet* set0 = + spvReflectGetEntryPointDescriptorSet(&module_, eps_[0], 1, &result); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + ASSERT_EQ(set0->binding_count, 1); + const SpvReflectDescriptorSet* set1 = + spvReflectGetEntryPointDescriptorSet(&module_, eps_[1], 1, &result); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + ASSERT_EQ(set1->binding_count, 1); + + ASSERT_EQ(set0->bindings[0], set1->bindings[0]); +} + +TEST_F(SpirvReflectMultiEntryPointTest, ChangeDescriptorSetNumber) { + const SpvReflectDescriptorSet* set = + spvReflectGetDescriptorSet(&module_, 0, NULL); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, + spvReflectChangeDescriptorSetNumber(&module_, set, 1)); + // Change descriptor binding numbers doesn't currently resort so it won't + // invalidate binding, but if that changes this test will need to be fixed. + ASSERT_EQ(set->set, 1); + + SpvReflectResult result; + const SpvReflectDescriptorSet* set0 = + spvReflectGetEntryPointDescriptorSet(&module_, eps_[0], 1, &result); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + ASSERT_EQ(set0->binding_count, 1); + const SpvReflectDescriptorSet* set1 = + spvReflectGetEntryPointDescriptorSet(&module_, eps_[1], 1, &result); + ASSERT_EQ(SPV_REFLECT_RESULT_SUCCESS, result); + ASSERT_EQ(set1->binding_count, 2); + + ASSERT_EQ(set0->bindings[0], set1->bindings[1]); + ASSERT_EQ(set0->bindings[0]->set, 1); +} diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.hlsl b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.hlsl new file mode 100644 index 0000000..e7ca179 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.hlsl @@ -0,0 +1,48 @@ +// dxc -spirv -fspv-reflect -T lib_6_4 -fspv-target-env=vulkan1.2 +struct MaterialData_t +{ + float4 g_vTest; + float2 g_vTest2; // accessed + float3 g_vTest3; + uint g_tTexture1; // accessed + uint g_tTexture2; + bool g_bTest1; // accessed + bool g_bTest2; +}; + +static MaterialData_t _g_MaterialData; + +ByteAddressBuffer g_MaterialData : register ( t4 , space1 ); + +struct Payload_t +{ + float2 vTest; + bool bTest; + uint tTest; +}; + +struct PayloadShadow_t +{ + float m_flVisibility; +}; + +[ shader ( "closesthit" ) ] +void ClosestHit0 ( inout Payload_t payload , in BuiltInTriangleIntersectionAttributes attrs ) +{ + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + payload.vTest = _g_MaterialData.g_vTest2; + payload.bTest = _g_MaterialData.g_bTest1; + payload.tTest = _g_MaterialData.g_tTexture1; +} + +[ shader ( "anyhit" ) ] +void AnyHit1 ( inout PayloadShadow_t payload , in BuiltInTriangleIntersectionAttributes attrs ) +{ + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + { + payload . m_flVisibility = 0.0 ; + AcceptHitAndEndSearch ( ) ; + } +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv new file mode 100644 index 0000000..88027c5 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv.yaml new file mode 100644 index 0000000..c12d087 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_0.spv.yaml @@ -0,0 +1,155 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 13 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "g_MaterialData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "g_MaterialData" + binding: 4 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "g_MaterialData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + ByteAddressBuffer offsets: [4, 5, 11, 13] + type_description: *td1 + word_offset: { binding: 129, set: 125 } + user_type: ByteAddressBuffer +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "ClosestHit0" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 640 + spirv_execution_model: 5316 # ClosestHitKHR + shader_stage: 0x00000400 # CLOSEST_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "g_MaterialData" + descriptor_set_count: 1 + descriptor_sets: + - set: 1 + binding_count: 1 + bindings: + - *db0 # "g_MaterialData" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.hlsl b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.hlsl new file mode 100644 index 0000000..5451d00 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.hlsl @@ -0,0 +1,25 @@ +// dxc -spirv -fspv-reflect -T cs_6_0 -E csmain -fspv-target-env=vulkan1.2 +uint g_global; + +struct MaterialData_t { + float4 g_vTest; + float2 g_vTest2; + float3 g_vTest3; + uint g_tTexture1; + uint g_tTexture2; + bool g_bTest1; + bool g_bTest2; +}; + +static MaterialData_t _g_MaterialData; + +ByteAddressBuffer g_MaterialData : register (t4 , space1); +RWStructuredBuffer Output : register(u1); + +[numthreads(1, 1, 1)] +void csmain(uint3 tid : SV_DispatchThreadID) { + uint2 a = g_MaterialData.Load2( tid.x + g_global ); + uint b = g_MaterialData.Load( tid.x + g_global ); + uint2 c = g_MaterialData.Load2(4); + Output[tid.x] = a * uint2(b, b) * c; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv new file mode 100644 index 0000000..6086158 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv.yaml new file mode 100644 index 0000000..735636b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_1.spv.yaml @@ -0,0 +1,333 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 11 + op: 21 + type_name: + struct_member_name: "g_global" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 30 + type_name: "type.$Globals" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 10 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000104 # ARRAY VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 8 } + member_count: 0 + members: + - &td3 + id: 8 + op: 30 + type_name: "type.RWStructuredBuffer.v2uint" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 9 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td5 + id: 7 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 21 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "g_global" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "$Globals" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "Output" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "g_MaterialData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "$Globals" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "$Globals" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 128, set: 124 } + - &db1 + spirv_id: 5 + name: "Output" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "Output" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 120, set: 116 } + user_type: RWStructuredBuffer + - &db2 + spirv_id: 4 + name: "g_MaterialData" + binding: 4 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "g_MaterialData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + ByteAddressBuffer offsets: [1, 2] + type_description: *td5 + word_offset: { binding: 112, set: 108 } + user_type: ByteAddressBuffer +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_DispatchThreadID" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td6 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "csmain" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 3 + descriptor_bindings: + - *db0 # "$Globals" + - *db1 # "Output" + - *db2 # "g_MaterialData" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "$Globals" + - *db1 # "Output" + - set: 1 + binding_count: 1 + bindings: + - *db2 # "g_MaterialData" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.hlsl b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.hlsl new file mode 100644 index 0000000..29a48fc --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.hlsl @@ -0,0 +1,19 @@ +// dxc -spirv -fspv-reflect -T cs_6_0 -E csmain -fspv-target-env=vulkan1.2 +struct MaterialData_t { + uint g_tTexture0; + uint g_tTexture1; + uint g_tTexture2; + uint g_tTexture3; +}; + +static MaterialData_t _g_MaterialData; + +ByteAddressBuffer g_MaterialData : register (t4 , space1); +RWStructuredBuffer Output : register(u1); + +[numthreads(1, 1, 1)] +void csmain(uint3 tid : SV_DispatchThreadID) { + uint2 a = g_MaterialData.Load2(0); + uint b = g_MaterialData.Load(1); + Output[tid.x] = a * uint2(b, b); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv new file mode 100644 index 0000000..f1cc534 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv.yaml new file mode 100644 index 0000000..4b7b92a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_2.spv.yaml @@ -0,0 +1,246 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 8 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000104 # ARRAY VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 8 } + member_count: 0 + members: + - &td1 + id: 6 + op: 30 + type_name: "type.RWStructuredBuffer.v2uint" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 7 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td3 + id: 5 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 17 + op: 23 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "Output" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "g_MaterialData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 4 + name: "Output" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "Output" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 102, set: 98 } + user_type: RWStructuredBuffer + - &db1 + spirv_id: 3 + name: "g_MaterialData" + binding: 4 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "g_MaterialData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + ByteAddressBuffer offsets: [0, 1] + type_description: *td3 + word_offset: { binding: 94, set: 90 } + user_type: ByteAddressBuffer +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: "SV_DispatchThreadID" + decoration_flags: 0x00000010 # BUILT_IN + built_in: 28 # GlobalInvocationId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 3 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 104 # VK_FORMAT_R32G32B32_UINT + type_description: *td4 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "csmain" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 600 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "Output" + - *db1 # "g_MaterialData" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "Output" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "g_MaterialData" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.hlsl b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.hlsl new file mode 100644 index 0000000..773c91b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.hlsl @@ -0,0 +1,36 @@ +// dxc -spirv -fspv-reflect -T lib_6_4 -fspv-target-env=vulkan1.2 +struct MaterialData_t { + float4 g_vTest0; + float4 g_vTest1; // accessed + float4 g_vTest2; // accessed twice, but only listed once + float4 g_vTest3; // accessed + float4 g_vTest4; +}; + +static MaterialData_t _g_MaterialData; + +ByteAddressBuffer g_MaterialData : register ( t4 , space1 ); + +struct PayloadShadow_t { + float m_flVisibility; +}; + +[ shader ( "anyhit" ) ] +void AnyHit1 ( inout PayloadShadow_t payload , in BuiltInTriangleIntersectionAttributes attrs ) { + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + { + payload . m_flVisibility = _g_MaterialData.g_vTest1.x + _g_MaterialData.g_vTest2.x; + AcceptHitAndEndSearch ( ) ; + } +} + +[ shader ( "anyhit" ) ] +void AnyHit0 ( inout PayloadShadow_t payload , in BuiltInTriangleIntersectionAttributes attrs ) { + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + { + payload . m_flVisibility = _g_MaterialData.g_vTest2.x + _g_MaterialData.g_vTest3.x; + AcceptHitAndEndSearch ( ) ; + } +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv new file mode 100644 index 0000000..03fbc9f Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv.yaml b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv.yaml new file mode 100644 index 0000000..a171200 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/byte_address_buffer_3.spv.yaml @@ -0,0 +1,155 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "type.ByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "g_MaterialData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000080 # NON_WRITABLE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "g_MaterialData" + binding: 4 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000080 # NON_WRITABLE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 4 # SRV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "g_MaterialData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + ByteAddressBuffer offsets: [4, 8, 12] + type_description: *td1 + word_offset: { binding: 107, set: 103 } + user_type: ByteAddressBuffer +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "AnyHit1" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 640 + spirv_execution_model: 5315 # AnyHitKHR + shader_stage: 0x00000200 # ANY_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "g_MaterialData" + descriptor_set_count: 1 + descriptor_sets: + - set: 1 + binding_count: 1 + bindings: + - *db0 # "g_MaterialData" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.hlsl b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.hlsl new file mode 100644 index 0000000..6f0a776 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.hlsl @@ -0,0 +1,48 @@ +// dxc -spirv -fspv-reflect -T lib_6_4 -fspv-target-env=vulkan1.2 +struct MaterialData_t +{ + float4 g_vTest; + float2 g_vTest2; // accessed + float3 g_vTest3; + uint g_tTexture1; // accessed + uint g_tTexture2; + bool g_bTest1; // accessed + bool g_bTest2; +}; + +static MaterialData_t _g_MaterialData; + +RWByteAddressBuffer g_MaterialData : register ( u4 , space1 ); + +struct Payload_t +{ + float2 vTest; + bool bTest; + uint tTest; +}; + +struct PayloadShadow_t +{ + float m_flVisibility; +}; + +[ shader ( "closesthit" ) ] +void ClosestHit0 ( inout Payload_t payload , in BuiltInTriangleIntersectionAttributes attrs ) +{ + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + payload.vTest = _g_MaterialData.g_vTest2; + payload.bTest = _g_MaterialData.g_bTest1; + payload.tTest = _g_MaterialData.g_tTexture1; +} + +[ shader ( "anyhit" ) ] +void AnyHit1 ( inout PayloadShadow_t payload , in BuiltInTriangleIntersectionAttributes attrs ) +{ + _g_MaterialData = g_MaterialData.Load( InstanceIndex() ); + + { + payload . m_flVisibility = 0.0 ; + AcceptHitAndEndSearch ( ) ; + } +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv new file mode 100644 index 0000000..9fb6e1e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv.yaml b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv.yaml new file mode 100644 index 0000000..700c731 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/user_type/rw_byte_address_buffer.spv.yaml @@ -0,0 +1,155 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 29 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 7 + op: 30 + type_name: "type.RWByteAddressBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 13 + op: 21 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "g_MaterialData" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: "g_MaterialData" + binding: 4 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # "g_MaterialData" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + ByteAddressBuffer offsets: [4, 5, 11, 13] + type_description: *td1 + word_offset: { binding: 130, set: 126 } + user_type: RWByteAddressBuffer +all_interface_variables: + - &iv0 + spirv_id: 2 + name: + location: 4294967295 + storage_class: 1 # Input + semantic: + decoration_flags: 0x00000010 # BUILT_IN + built_in: 6 # InstanceId + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + format: 98 # VK_FORMAT_R32_UINT + type_description: *td2 + word_offset: { location: 0 } +module: + generator: 14 # Google spiregg + entry_point_name: "ClosestHit0" + entry_point_id: 1 + source_language: 5 # HLSL + source_language_version: 640 + spirv_execution_model: 5316 # ClosestHitKHR + shader_stage: 0x00000400 # CLOSEST_HIT + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "g_MaterialData" + descriptor_set_count: 1 + descriptor_sets: + - set: 1 + binding_count: 1 + bindings: + - *db0 # "g_MaterialData" + input_variable_count: 1, + input_variables: + - *iv0 # + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.glsl new file mode 100644 index 0000000..e52f28c --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.glsl @@ -0,0 +1,17 @@ +#version 460 +#extension GL_KHR_memory_scope_semantics : enable + +layout(set=0, binding=0) buffer SSBO { + uint a; + uint b; // UNUSED + uint c; + uint d; + uint e; // UNUSED + uint f; +}; + +void main() { + uint x = atomicLoad(a, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsRelaxed); + atomicStore(c, 0u, gl_ScopeDevice, gl_StorageSemanticsBuffer, gl_SemanticsRelaxed); + atomicExchange(d, f); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv new file mode 100644 index 0000000..1e18caa Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv.yaml new file mode 100644 index 0000000..f5182b7 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_0.spv.yaml @@ -0,0 +1,292 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 6 + op: 21 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 6 + op: 21 + type_name: + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 6 + op: 21 + type_name: + struct_member_name: "f" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 9 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 6 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 + - *td5 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "d" + offset: 12 + absolute_offset: 12 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "e" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "f" + offset: 20 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 6 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + - *bv5 + type_description: *td6 +all_descriptor_bindings: + - &db0 + spirv_id: 11 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td6 + word_offset: { binding: 113, set: 117 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 460 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.slang b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.slang new file mode 100644 index 0000000..83b4c1a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.slang @@ -0,0 +1,18 @@ +struct SSBOData { + Atomic a; + Atomic b; // UNUSED + Atomic c; + Atomic d; // UNUSED + Atomic e; // UNUSED + Atomic f; +}; + +[[vk::binding(0, 0)]] +RWStructuredBuffer ssbo; + +[shader("compute")] +void main() { + uint x = ssbo[0].a.load(); + ssbo[0].c.exchange(0); + ssbo[0].f.store(0); +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv new file mode 100755 index 0000000..ea139d3 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv.yaml new file mode 100644 index 0000000..9033fe7 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/atomics_1.spv.yaml @@ -0,0 +1,327 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 5 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 5 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 5 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 5 + op: 21 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 5 + op: 21 + type_name: + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 5 + op: 21 + type_name: + struct_member_name: "f" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 11 + op: 29 + type_name: "SSBOData_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 24 } + member_count: 6 + members: + - *td0 + - *td1 + - *td2 + - *td3 + - *td4 + - *td5 + - &td7 + id: 10 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td6 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 8 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "d" + offset: 12 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "e" + offset: 16 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "f" + offset: 20 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: + offset: 0 + absolute_offset: 0 + size: 24 + padded_size: 24 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 6 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + - *bv4 + - *bv5 + type_description: *td6 + - &bv7 + name: "ssbo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv6 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 13 + name: "ssbo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # "ssbo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 126, set: 130 } +all_interface_variables: +module: + generator: 0 # ??? + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "ssbo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "ssbo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.glsl new file mode 100644 index 0000000..0681ef3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.glsl @@ -0,0 +1,11 @@ +#version 450 +layout(set = 0, binding = 0) buffer foo { + uvec4 a; // not used + uint b[4]; // used + uint c; // not used +}; + +void main() { + uint d[4] = {4, 5, 6, 7}; + b = d; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv new file mode 100644 index 0000000..7c1b522 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv.yaml new file mode 100644 index 0000000..638d068 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_0.spv.yaml @@ -0,0 +1,187 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 15 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 3 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 7 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 4 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 16 + absolute_offset: 16 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: + offset: 32 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 +all_descriptor_bindings: + - &db0 + spirv_id: 2 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 47, set: 51 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.slang b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.slang new file mode 100644 index 0000000..11aa90a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.slang @@ -0,0 +1,14 @@ +struct Bar { + uint4 a; + uint b[4]; + uint c; +}; + +[[vk::binding(0, 0)]] +RWStructuredBuffer foo; + +[shader("compute")] +void main() { + uint d[4] = {4, 5, 6, 7}; + foo[0].b = d; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv new file mode 100644 index 0000000..5923fb4 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv.yaml new file mode 100644 index 0000000..be7a4d1 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_1.spv.yaml @@ -0,0 +1,257 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 10 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 8 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 16 + op: 29 + type_name: "Bar_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td0 + - *td2 + - *td3 + - &td5 + id: 15 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "data" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "b" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: "c" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "foo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 18 + name: "foo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "foo" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 122, set: 126 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "foo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "foo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.glsl new file mode 100644 index 0000000..d1287da --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.glsl @@ -0,0 +1,16 @@ +#version 450 +layout(set = 0, binding = 0, std430) buffer foo1 { + uvec4 a; + uint b[4]; + uint c; +}; + +layout(set = 0, binding = 1, std430) buffer foo2 { + uint d; + uint e[4]; + uvec2 f; +}; + +void main() { + b = e; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv new file mode 100755 index 0000000..5c14189 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv.yaml new file mode 100644 index 0000000..4ff64d4 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_2.spv.yaml @@ -0,0 +1,344 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 9 + op: 28 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 30 + type_name: "foo1" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td2 + - &td4 + id: 6 + op: 21 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 15 + op: 28 + type_name: + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td6 + id: 16 + op: 23 + type_name: + struct_member_name: "f" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 17 + op: 30 + type_name: "foo2" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td4 + - *td5 + - *td6 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 16 + absolute_offset: 16 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 32 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv2 + type_description: *td3 + - &bv4 + name: "d" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "e" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: "f" + offset: 24 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 2 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv4 + - *bv5 + - *bv6 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 12 + name: "" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td3 + word_offset: { binding: 97, set: 101 } + - &db1 + spirv_id: 19 + name: "" + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv7 # "" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 127, set: 131 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "" + - *db1 # "" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # "" + - *db1 # "" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.slang b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.slang new file mode 100644 index 0000000..ee8b01b --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.slang @@ -0,0 +1,22 @@ +struct Bar1 { + uint4 a; + uint b[4]; + uint c; +}; + +struct Bar2 { + uint4 d; + uint e[4]; + uint f; +}; + +[[vk::binding(0, 0)]] +RWStructuredBuffer foo1; + +[[vk::binding(0, 1)]] +RWStructuredBuffer foo2; + +[shader("compute")] +void main() { + foo1[0].b = foo2[0].e; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv new file mode 100755 index 0000000..c1db7ff Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv.yaml new file mode 100644 index 0000000..21db8f3 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_array_3.spv.yaml @@ -0,0 +1,487 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 10 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 8 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 16 + op: 29 + type_name: "Bar1_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td0 + - *td2 + - *td3 + - &td5 + id: 15 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td4 + - &td6 + id: 9 + op: 23 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 11 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td8 + id: 10 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 8 + op: 21 + type_name: + struct_member_name: "f" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 26 + op: 29 + type_name: "Bar2_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td6 + - *td8 + - *td9 + - &td11 + id: 25 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td10 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "data" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "b" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: "c" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "foo1" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv4 + type_description: *td5 + - &bv6 + name: "d" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: "data" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: "e" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv7 + type_description: *td8 + - &bv9 + name: "f" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv6 + - *bv8 + - *bv9 + type_description: *td10 + - &bv11 + name: "foo2" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv10 + type_description: *td11 +all_descriptor_bindings: + - &db0 + spirv_id: 18 + name: "foo1" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "foo1" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 152, set: 156 } + - &db1 + spirv_id: 28 + name: "foo2" + binding: 0 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv11 # "foo2" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td11 + word_offset: { binding: 195, set: 199 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "foo1" + - *db1 # "foo2" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "foo1" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "foo2" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv new file mode 100644 index 0000000..fbbde8e Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv.yaml new file mode 100644 index 0000000..9e88367 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_memory.spv.yaml @@ -0,0 +1,169 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 2 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000008 # ARRAY FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [32,], stride: 4 } + member_count: 0 + members: + - &td1 + id: 3 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [32,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: + offset: 0 + absolute_offset: 0 + size: 128 + padded_size: 128 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [32,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv3 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv2 + type_description: *td1 +all_descriptor_bindings: + - &db0 + spirv_id: 5 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv1 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 48, set: 44 } + - &db1 + spirv_id: 4 + name: + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv3 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td1 + word_offset: { binding: 40, set: 36 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 1 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # + - *db1 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # + - *db1 # + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.glsl new file mode 100644 index 0000000..df3955a --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.glsl @@ -0,0 +1,23 @@ +#version 450 + +struct Bar { + uint x; + uint y; + uint z[2]; +}; + +layout(set = 0, binding = 0, std430) buffer foo1 { + uvec4 a; + Bar b; + uint c; +}; + +layout(set = 0, binding = 1, std430) buffer foo2 { + uvec4 d; + Bar e; + uint f; +}; + +void main() { + b = e; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv new file mode 100644 index 0000000..3207d0b Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv.yaml new file mode 100644 index 0000000..0855b58 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_0.spv.yaml @@ -0,0 +1,554 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 12 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 5 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 6 + op: 30 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td1 + - *td2 + - *td3 + - &td5 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td6 + id: 7 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td4 + - *td5 + - &td7 + id: 12 + op: 23 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td9 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 5 + op: 28 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td11 + id: 6 + op: 30 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td8 + - *td9 + - *td10 + - &td12 + id: 11 + op: 21 + type_name: + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td13 + id: 8 + op: 30 + type_name: + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td7 + - *td11 + - *td12 +all_block_variables: + - &bv0 + name: + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: + offset: 0 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: + offset: 4 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: + offset: 8 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: + offset: 16 + absolute_offset: 16 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv1 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: + offset: 32 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td5 + - &bv6 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv4 + - *bv5 + type_description: *td6 + - &bv7 + name: + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv8 + name: + offset: 0 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td8 + - &bv9 + name: + offset: 4 + absolute_offset: 20 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: + offset: 8 + absolute_offset: 24 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: + offset: 16 + absolute_offset: 16 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv8 + - *bv9 + - *bv10 + type_description: *td11 + - &bv12 + name: + offset: 32 + absolute_offset: 32 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv7 + - *bv11 + - *bv12 + type_description: *td13 +all_descriptor_bindings: + - &db0 + spirv_id: 3 + name: + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td6 + word_offset: { binding: 69, set: 73 } + - &db1 + spirv_id: 4 + name: + binding: 1 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv13 # + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td13 + word_offset: { binding: 95, set: 99 } +all_interface_variables: +module: + generator: 7 # Khronos SPIR-V Tools Assembler + entry_point_name: "main" + entry_point_id: 2 + source_language: 0 # Unknown + source_language_version: 0 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # + - *db1 # + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 2 + bindings: + - *db0 # + - *db1 # + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.slang b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.slang new file mode 100644 index 0000000..3caa372 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.slang @@ -0,0 +1,28 @@ +struct Bar { + uint x; + uint y; + uint z[2]; +}; + +struct FooBuffer1 { + float4 a; + Bar b; + uint d; +}; + +struct FooBuffer2 { + float4 d; + Bar e; + uint f; +}; + +[[vk::binding(0, 0)]] +RWStructuredBuffer foo1; + +[[vk::binding(0, 1)]] +RWStructuredBuffer foo2; + +[shader("compute")] +void main() { + foo1[0].b = foo2[0].e; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv new file mode 100755 index 0000000..3b67a09 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv.yaml new file mode 100644 index 0000000..cbd6e96 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/copy_struct_1.spv.yaml @@ -0,0 +1,697 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 9 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 11 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 11 + op: 21 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 13 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td4 + id: 12 + op: 30 + type_name: "_Array_std430_uint2" + struct_member_name: "z" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td3 + - &td5 + id: 10 + op: 30 + type_name: "Bar_std430" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td1 + - *td2 + - *td4 + - &td6 + id: 11 + op: 21 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 18 + op: 29 + type_name: "FooBuffer1_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td0 + - *td5 + - *td6 + - &td8 + id: 17 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 9 + op: 23 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000108 # VECTOR FLOAT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 11 + op: 21 + type_name: + struct_member_name: "x" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 11 + op: 21 + type_name: + struct_member_name: "y" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 13 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [2,], stride: 4 } + member_count: 0 + members: + - &td13 + id: 12 + op: 30 + type_name: "_Array_std430_uint2" + struct_member_name: "z" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td12 + - &td14 + id: 10 + op: 30 + type_name: "Bar_std430" + struct_member_name: "e" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td10 + - *td11 + - *td13 + - &td15 + id: 11 + op: 21 + type_name: + struct_member_name: "f" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td16 + id: 28 + op: 29 + type_name: "FooBuffer2_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td9 + - *td14 + - *td15 + - &td17 + id: 27 + op: 30 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td16 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "y" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "data" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "z" + offset: 8 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv3 + type_description: *td4 + - &bv5 + name: "b" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv1 + - *bv2 + - *bv4 + type_description: *td5 + - &bv6 + name: "d" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv7 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv5 + - *bv6 + type_description: *td7 + - &bv8 + name: "foo1" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv7 + type_description: *td8 + - &bv9 + name: "d" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv10 + name: "x" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv11 + name: "y" + offset: 4 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv12 + name: "data" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [2,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td12 + - &bv13 + name: "z" + offset: 8 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv12 + type_description: *td13 + - &bv14 + name: "e" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv10 + - *bv11 + - *bv13 + type_description: *td14 + - &bv15 + name: "f" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv16 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv9 + - *bv14 + - *bv15 + type_description: *td16 + - &bv17 + name: "foo2" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv16 + type_description: *td17 +all_descriptor_bindings: + - &db0 + spirv_id: 20 + name: "foo1" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv8 # "foo1" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td8 + word_offset: { binding: 184, set: 188 } + - &db1 + spirv_id: 30 + name: "foo2" + binding: 0 + input_attachment_index: 0 + set: 1 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv17 # "foo2" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td17 + word_offset: { binding: 219, set: 223 } +all_interface_variables: +module: + generator: 0 # ??? + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 2 + descriptor_bindings: + - *db0 # "foo1" + - *db1 # "foo2" + descriptor_set_count: 2 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "foo1" + - set: 1 + binding_count: 1 + bindings: + - *db1 # "foo2" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.glsl new file mode 100644 index 0000000..49bb500 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.glsl @@ -0,0 +1,12 @@ +#version 450 +layout(set = 0, binding = 0) buffer foo { + uint a; + uint b; + uint c; + uint d; +} bar[4]; + +void main() { + bar[1].b = 0; + bar[3].d = 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv new file mode 100644 index 0000000..45fb2ee Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv.yaml new file mode 100644 index 0000000..aa373e9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_0.spv.yaml @@ -0,0 +1,222 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 21 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 21 + type_name: + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 6 + op: 21 + type_name: + struct_member_name: "d" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 9 + op: 28 + type_name: "foo" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000002 # BUFFER_BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 0 } + member_count: 4 + members: + - *td0 + - *td1 + - *td2 + - *td3 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "b" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "c" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td2 + - &bv3 + name: "d" + offset: 12 + absolute_offset: 12 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: "bar" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 4 + members: + - *bv0 + - *bv1 + - *bv2 + - *bv3 + type_description: *td4 +all_descriptor_bindings: + - &db0 + spirv_id: 11 + name: "bar" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv4 # "bar" + array: { dims_count: 1, dims: [4,] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td4 + word_offset: { binding: 82, set: 86 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "bar" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "bar" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.slang b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.slang new file mode 100644 index 0000000..1c8a1bd --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.slang @@ -0,0 +1,13 @@ +struct Bar { + uint4 a; + uint b[4]; + uint c; +}; + +[[vk::binding(0, 0)]] +RWStructuredBuffer foo[8]; + +[shader("compute")] +void main() { + foo[4][0].b[3] = 0; +} \ No newline at end of file diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv new file mode 100644 index 0000000..884c898 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv.yaml new file mode 100644 index 0000000..1ef79f9 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/descriptor_indexing_1.spv.yaml @@ -0,0 +1,257 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 23 + type_name: + struct_member_name: "a" + storage_class: 0 # UniformConstant + type_flags: 0x00000104 # VECTOR INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 12 + op: 28 + type_name: + struct_member_name: "data" + storage_class: 0 # UniformConstant + type_flags: 0x20000004 # ARRAY INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [4,], stride: 4 } + member_count: 0 + members: + - &td2 + id: 11 + op: 30 + type_name: "_Array_std430_uint4" + struct_member_name: "b" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td1 + - &td3 + id: 9 + op: 21 + type_name: + struct_member_name: "c" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 7 + op: 29 + type_name: "Bar_std430" + struct_member_name: + storage_class: 0 # UniformConstant + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [0,], stride: 48 } + member_count: 3 + members: + - *td0 + - *td2 + - *td3 + - &td5 + id: 5 + op: 28 + type_name: "RWStructuredBuffer" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x30080000 # ARRAY STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 1, dims: [8,], stride: 0 } + member_count: 1 + members: + - *td4 +all_block_variables: + - &bv0 + name: "a" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 4 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "data" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 1, dims: [4,], stride: 4 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "b" + offset: 16 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv1 + type_description: *td2 + - &bv3 + name: "c" + offset: 32 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td3 + - &bv4 + name: + offset: 0 + absolute_offset: 0 + size: 36 + padded_size: 36 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 3 + members: + - *bv0 + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "foo" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 17 + name: "foo" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "foo" + array: { dims_count: 1, dims: [8,] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 122, set: 126 } +all_interface_variables: +module: + generator: 0 # ??? + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "foo" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "foo" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.glsl new file mode 100644 index 0000000..5d79419 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.glsl @@ -0,0 +1,21 @@ +#version 450 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference, std430) buffer Node { + uint payload; +}; + +layout(buffer_reference, std430) buffer BadNode { + uint bad_payload; +}; + +layout(set = 0, binding = 0, std430) buffer SSBO { + Node first_node; + BadNode bad_node; // used + uint placeholder; +} x; + +void main() { + x.placeholder = 0; + x.first_node.payload = 3; +} diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv new file mode 100644 index 0000000..79c92e9 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv.yaml new file mode 100644 index 0000000..10a887f --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_0.spv.yaml @@ -0,0 +1,291 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 8 + op: 21 + type_name: + struct_member_name: "payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 6 + op: 32 + type_name: "Node" + struct_member_name: "first_node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 8 + op: 21 + type_name: + struct_member_name: "bad_payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 7 + op: 32 + type_name: "BadNode" + struct_member_name: "bad_node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td2 + - &td4 + id: 8 + op: 21 + type_name: + struct_member_name: "placeholder" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 9 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td1 + - *td3 + - *td4 + - &td6 + id: 8 + op: 21 + type_name: + struct_member_name: "payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 8 + op: 21 + type_name: + struct_member_name: "bad_payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "payload" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv1 + name: "first_node" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv0 + type_description: *td1 + - &bv2 + name: "bad_payload" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv3 + name: "bad_node" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv2 + type_description: *td3 + - &bv4 + name: "placeholder" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td4 + - &bv5 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv1 + - *bv3 + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 13 + name: "x" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "x" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 144, set: 148 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "x" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.glsl b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.glsl new file mode 100644 index 0000000..7838a40 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.glsl @@ -0,0 +1,26 @@ +#version 450 +#extension GL_EXT_buffer_reference : enable + +layout(buffer_reference) buffer Node; + +layout(buffer_reference, std430) buffer Node { + Node next; + uint payload; +}; + +layout(buffer_reference) buffer BadNode; +layout(buffer_reference, std430) buffer BadNode { + BadNode bad_next; + uint bad_payload; +}; + +layout(set = 0, binding = 0, std430) buffer SSBO { + Node first_node; + BadNode bad_node; // used + uint placeholder; +} x; + +void main() { + x.placeholder = 0; + x.first_node.next.payload = 3; +} diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv new file mode 100644 index 0000000..13c9e8b Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv.yaml new file mode 100644 index 0000000..79eebe6 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_1.spv.yaml @@ -0,0 +1,439 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 6 + op: 32 + type_name: + struct_member_name: "next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td1 + id: 8 + op: 21 + type_name: + struct_member_name: "payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 6 + op: 32 + type_name: "Node" + struct_member_name: "first_node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td0 + - *td1 + - &td3 + id: 7 + op: 32 + type_name: + struct_member_name: "bad_next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td4 + id: 8 + op: 21 + type_name: + struct_member_name: "bad_payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td5 + id: 7 + op: 32 + type_name: "BadNode" + struct_member_name: "bad_node" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td3 + - *td4 + - &td6 + id: 8 + op: 21 + type_name: + struct_member_name: "placeholder" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 9 + op: 30 + type_name: "SSBO" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td2 + - *td5 + - *td6 + - &td8 + id: 6 + op: 32 + type_name: + struct_member_name: "next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td9 + id: 8 + op: 21 + type_name: + struct_member_name: "payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 6 + op: 32 + type_name: "Node" + struct_member_name: "next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td8 + - *td9 + - &td11 + id: 8 + op: 21 + type_name: + struct_member_name: "payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td12 + id: 7 + op: 32 + type_name: + struct_member_name: "bad_next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - [forward pointer] + - &td13 + id: 8 + op: 21 + type_name: + struct_member_name: "bad_payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td14 + id: 7 + op: 32 + type_name: "BadNode" + struct_member_name: "bad_next" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td12 + - *td13 + - &td15 + id: 8 + op: 21 + type_name: + struct_member_name: "bad_payload" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "payload" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td11 + - &bv1 + name: "first_node" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - [recursive] + - *bv0 + type_description: *td2 + - &bv2 + name: "bad_payload" + offset: 8 + absolute_offset: 8 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td15 + - &bv3 + name: "bad_node" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - [recursive] + - *bv2 + type_description: *td5 + - &bv4 + name: "placeholder" + offset: 16 + absolute_offset: 16 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td6 + - &bv5 + name: "x" + offset: 0 + absolute_offset: 0 + size: 0 + padded_size: 0 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv1 + - *bv3 + - *bv4 + type_description: *td7 +all_descriptor_bindings: + - &db0 + spirv_id: 13 + name: "x" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 7 # VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + resource_type: 8 # UAV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "x" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td7 + word_offset: { binding: 165, set: 169 } +all_interface_variables: +module: + generator: 8 # Khronos Glslang Reference Front End + entry_point_name: "main" + entry_point_id: 4 + source_language: 2 # GLSL + source_language_version: 450 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "x" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "x" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.slang b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.slang new file mode 100644 index 0000000..7005f32 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.slang @@ -0,0 +1,15 @@ +uniform uint* data_ptr; // creates a ptr chain access +uniform uint* data_ptr_usused; + +struct Data{ + int unused_var; + int used_var; +} +uniform Data* data_struct; + +[numthreads(1,1,1)] +void computeMain() +{ + data_ptr[0] = 1; + data_struct->used_var = 1; +} diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv new file mode 100644 index 0000000..ed77b0a Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv.yaml new file mode 100644 index 0000000..d3e5bef --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_2.spv.yaml @@ -0,0 +1,291 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 7 + op: 32 + type_name: + struct_member_name: "data_ptr" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 7 + op: 32 + type_name: + struct_member_name: "data_ptr_usused" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x40000004 # REF INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td2 + id: 12 + op: 21 + type_name: + struct_member_name: "unused_var" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 12 + op: 21 + type_name: + struct_member_name: "used_var" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 9 + op: 32 + type_name: "Data_natural" + struct_member_name: "data_struct" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td2 + - *td3 + - &td5 + id: 5 + op: 30 + type_name: "GlobalParams_std140" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 3 + members: + - *td0 + - *td1 + - *td4 + - &td6 + id: 12 + op: 21 + type_name: + struct_member_name: "unused_var" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td7 + id: 12 + op: 21 + type_name: + struct_member_name: "used_var" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: +all_block_variables: + - &bv0 + name: "data_ptr" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 0 + members: + type_description: *td0 + - &bv1 + name: "data_ptr_usused" + offset: 8 + absolute_offset: 8 + size: 8 + padded_size: 8 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td1 + - &bv2 + name: "unused_var" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td6 + - &bv3 + name: "used_var" + offset: 4 + absolute_offset: 4 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv4 + name: "data_struct" + offset: 16 + absolute_offset: 16 + size: 8 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv2 + - *bv3 + type_description: *td4 + - &bv5 + name: "globalParams" + offset: 0 + absolute_offset: 0 + size: 32 + padded_size: 32 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 3 + members: + - *bv0 + - *bv1 + - *bv4 + type_description: *td5 +all_descriptor_bindings: + - &db0 + spirv_id: 11 + name: "globalParams" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv5 # "globalParams" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td5 + word_offset: { binding: 120, set: 124 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "globalParams" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "globalParams" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.slang b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.slang new file mode 100644 index 0000000..e7bfbbe --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.slang @@ -0,0 +1,20 @@ +struct DataUsed{ + int unused_var_2; + int used_var_2; +}; + +struct DataUnused{ + int unused_var_3; +}; + +struct Data{ + DataUnused unused_struct; + DataUsed used_struct; +} +uniform Data* data_struct; + +[numthreads(1,1,1)] +void computeMain() +{ + data_struct->used_struct.used_var_2 = 1; +} diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv new file mode 100644 index 0000000..9f18d78 Binary files /dev/null and b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv differ diff --git a/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv.yaml b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv.yaml new file mode 100644 index 0000000..2d0e5e2 --- /dev/null +++ b/lib/All/SPIRV-Reflect/tests/variable_access/phy_storage_buffer_used_3.spv.yaml @@ -0,0 +1,380 @@ +%YAML 1.1 +--- +all_type_descriptions: + - &td0 + id: 10 + op: 21 + type_name: + struct_member_name: "unused_var_3" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td1 + id: 23 + op: 30 + type_name: "DataUnused_natural" + struct_member_name: "unused_struct" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td0 + - &td2 + id: 10 + op: 21 + type_name: + struct_member_name: "unused_var_2" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td3 + id: 10 + op: 21 + type_name: + struct_member_name: "used_var_2" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td4 + id: 16 + op: 30 + type_name: "DataUsed_natural" + struct_member_name: "used_struct" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td2 + - *td3 + - &td5 + id: 7 + op: 32 + type_name: "Data_natural" + struct_member_name: "data_struct" + storage_class: 5349 # PhysicalStorageBuffer + type_flags: 0x50080000 # STRUCT REF EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td1 + - *td4 + - &td6 + id: 5 + op: 30 + type_name: "GlobalParams_std140" + struct_member_name: + storage_class: -1 # NOT APPLICABLE + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000001 # BLOCK + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td5 + - &td7 + id: 10 + op: 21 + type_name: + struct_member_name: "unused_var_3" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td8 + id: 23 + op: 30 + type_name: "DataUnused_natural" + struct_member_name: "unused_struct" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 1 + members: + - *td7 + - &td9 + id: 10 + op: 21 + type_name: + struct_member_name: "unused_var_2" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td10 + id: 10 + op: 21 + type_name: + struct_member_name: "used_var_2" + storage_class: 0 # UniformConstant + type_flags: 0x00000004 # INT + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 0 + members: + - &td11 + id: 16 + op: 30 + type_name: "DataUsed_natural" + struct_member_name: "used_struct" + storage_class: 0 # UniformConstant + type_flags: 0x10080000 # STRUCT EXTERNAL_BLOCK + decoration_flags: 0x00000000 # NONE + traits: + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + array: { dims_count: 0, dims: [], stride: 0 } + member_count: 2 + members: + - *td9 + - *td10 +all_block_variables: + - &bv0 + name: "unused_var_3" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td7 + - &bv1 + name: "unused_struct" + offset: 0 + absolute_offset: 0 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 1 + members: + - *bv0 + type_description: *td8 + - &bv2 + name: "unused_var_2" + offset: 0 + absolute_offset: 4 + size: 4 + padded_size: 4 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td9 + - &bv3 + name: "used_var_2" + offset: 4 + absolute_offset: 8 + size: 4 + padded_size: 12 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 32, signedness: 1 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 0 + members: + type_description: *td10 + - &bv4 + name: "used_struct" + offset: 4 + absolute_offset: 4 + size: 16 + padded_size: 28 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000001 # UNUSED + member_count: 2 + members: + - *bv2 + - *bv3 + type_description: *td11 + - &bv5 + name: "data_struct" + offset: 0 + absolute_offset: 0 + size: 8 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 2 + members: + - *bv1 + - *bv4 + type_description: *td5 + - &bv6 + name: "globalParams" + offset: 0 + absolute_offset: 0 + size: 16 + padded_size: 16 + decorations: 0x00000000 # NONE + numeric: + scalar: { width: 0, signedness: 0 } + vector: { component_count: 0 } + matrix: { column_count: 0, row_count: 0, stride: 0 } + array: { dims_count: 0, dims: [], stride: 0 } + flags: 0x00000000 # NONE + member_count: 1 + members: + - *bv5 + type_description: *td6 +all_descriptor_bindings: + - &db0 + spirv_id: 9 + name: "globalParams" + binding: 0 + input_attachment_index: 0 + set: 0 + decoration_flags: 0x00000000 # NONE + descriptor_type: 6 # VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + resource_type: 2 # CBV + image: { dim: 0, depth: 0, arrayed: 0, ms: 0, sampled: 0, image_format: 0 } # dim=1D image_format=Unknown + block: *bv6 # "globalParams" + array: { dims_count: 0, dims: [] } + accessed: 1 + uav_counter_id: 4294967295 + uav_counter_binding: + type_description: *td6 + word_offset: { binding: 128, set: 132 } +all_interface_variables: +module: + generator: 40 # Slang Shader Compiler + entry_point_name: "main" + entry_point_id: 2 + source_language: 11 # Slang + source_language_version: 1 + spirv_execution_model: 5 # GLCompute + shader_stage: 0x00000020 # CS + descriptor_binding_count: 1 + descriptor_bindings: + - *db0 # "globalParams" + descriptor_set_count: 1 + descriptor_sets: + - set: 0 + binding_count: 1 + bindings: + - *db0 # "globalParams" + input_variable_count: 0, + input_variables: + output_variable_count: 0, + output_variables: + push_constant_count: 0, + push_constants: + specialization_constant_count: 0, + specialization_constants: +... diff --git a/lib/All/VulkanMemoryAllocator/include/vk_mem_alloc.h b/lib/All/VulkanMemoryAllocator/include/vk_mem_alloc.h new file mode 100644 index 0000000..8df0364 --- /dev/null +++ b/lib/All/VulkanMemoryAllocator/include/vk_mem_alloc.h @@ -0,0 +1,19530 @@ +// +// Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H +#define AMD_VULKAN_MEMORY_ALLOCATOR_H + +/** \mainpage Vulkan Memory Allocator + +Version 3.3.0 + +Copyright (c) 2017-2025 Advanced Micro Devices, Inc. All rights reserved. \n +License: MIT \n +See also: [product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/), +[repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) + + +API documentation divided into groups: [Topics](topics.html) + +General documentation chapters: + +- \subpage faq +- \subpage quick_start + - [Project setup](@ref quick_start_project_setup) + - [Initialization](@ref quick_start_initialization) + - [Resource allocation](@ref quick_start_resource_allocation) +- \subpage choosing_memory_type + - [Usage](@ref choosing_memory_type_usage) + - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags) + - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types) + - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools) + - [Dedicated allocations](@ref choosing_memory_type_dedicated_allocations) +- \subpage memory_mapping + - [Copy functions](@ref memory_mapping_copy_functions) + - [Mapping functions](@ref memory_mapping_mapping_functions) + - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory) + - [Cache flush and invalidate](@ref memory_mapping_cache_control) +- \subpage staying_within_budget + - [Querying for budget](@ref staying_within_budget_querying_for_budget) + - [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage) +- \subpage resource_aliasing +- \subpage custom_memory_pools + - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex) + - [When not to use custom pools](@ref custom_memory_pools_when_not_use) + - [Linear allocation algorithm](@ref linear_algorithm) + - [Free-at-once](@ref linear_algorithm_free_at_once) + - [Stack](@ref linear_algorithm_stack) + - [Double stack](@ref linear_algorithm_double_stack) + - [Ring buffer](@ref linear_algorithm_ring_buffer) +- \subpage defragmentation +- \subpage statistics + - [Numeric statistics](@ref statistics_numeric_statistics) + - [JSON dump](@ref statistics_json_dump) +- \subpage allocation_annotation + - [Allocation user data](@ref allocation_user_data) + - [Allocation names](@ref allocation_names) +- \subpage virtual_allocator +- \subpage debugging_memory_usage + - [Memory initialization](@ref debugging_memory_usage_initialization) + - [Margins](@ref debugging_memory_usage_margins) + - [Corruption detection](@ref debugging_memory_usage_corruption_detection) + - [Leak detection features](@ref debugging_memory_usage_leak_detection) +- \subpage other_api_interop +- \subpage usage_patterns + - [GPU-only resource](@ref usage_patterns_gpu_only) + - [Staging copy for upload](@ref usage_patterns_staging_copy_upload) + - [Readback](@ref usage_patterns_readback) + - [Advanced data uploading](@ref usage_patterns_advanced_data_uploading) + - [Other use cases](@ref usage_patterns_other_use_cases) +- \subpage configuration + - [Pointers to Vulkan functions](@ref config_Vulkan_functions) + - [Custom host memory allocator](@ref custom_memory_allocator) + - [Device memory allocation callbacks](@ref allocation_callbacks) + - [Device heap memory limit](@ref heap_memory_limit) +- Extension support + - \subpage vk_khr_dedicated_allocation + - \subpage enabling_buffer_device_address + - \subpage vk_ext_memory_priority + - \subpage vk_amd_device_coherent_memory + - \subpage vk_khr_external_memory_win32 +- \subpage general_considerations + - [Thread safety](@ref general_considerations_thread_safety) + - [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility) + - [Validation layer warnings](@ref general_considerations_validation_layer_warnings) + - [Allocation algorithm](@ref general_considerations_allocation_algorithm) + - [Features not supported](@ref general_considerations_features_not_supported) + +\defgroup group_init Library initialization + +\brief API elements related to the initialization and management of the entire library, especially #VmaAllocator object. + +\defgroup group_alloc Memory allocation + +\brief API elements related to the allocation, deallocation, and management of Vulkan memory, buffers, images. +Most basic ones being: vmaCreateBuffer(), vmaCreateImage(). + +\defgroup group_virtual Virtual allocator + +\brief API elements related to the mechanism of \ref virtual_allocator - using the core allocation algorithm +for user-defined purpose without allocating any real GPU memory. + +\defgroup group_stats Statistics + +\brief API elements that query current status of the allocator, from memory usage, budget, to full dump of the internal state in JSON format. +See documentation chapter: \ref statistics. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(VULKAN_H_) +#include +#endif + +#if !defined(VMA_VULKAN_VERSION) + #if defined(VK_VERSION_1_4) + #define VMA_VULKAN_VERSION 1004000 + #elif defined(VK_VERSION_1_3) + #define VMA_VULKAN_VERSION 1003000 + #elif defined(VK_VERSION_1_2) + #define VMA_VULKAN_VERSION 1002000 + #elif defined(VK_VERSION_1_1) + #define VMA_VULKAN_VERSION 1001000 + #else + #define VMA_VULKAN_VERSION 1000000 + #endif +#endif + +#if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS + extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties; + extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties; + extern PFN_vkAllocateMemory vkAllocateMemory; + extern PFN_vkFreeMemory vkFreeMemory; + extern PFN_vkMapMemory vkMapMemory; + extern PFN_vkUnmapMemory vkUnmapMemory; + extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges; + extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges; + extern PFN_vkBindBufferMemory vkBindBufferMemory; + extern PFN_vkBindImageMemory vkBindImageMemory; + extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements; + extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements; + extern PFN_vkCreateBuffer vkCreateBuffer; + extern PFN_vkDestroyBuffer vkDestroyBuffer; + extern PFN_vkCreateImage vkCreateImage; + extern PFN_vkDestroyImage vkDestroyImage; + extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer; + #if VMA_VULKAN_VERSION >= 1001000 + extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2; + extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2; + extern PFN_vkBindBufferMemory2 vkBindBufferMemory2; + extern PFN_vkBindImageMemory2 vkBindImageMemory2; + extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2; + #endif // #if VMA_VULKAN_VERSION >= 1001000 +#endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES + +#if !defined(VMA_DEDICATED_ALLOCATION) + #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation + #define VMA_DEDICATED_ALLOCATION 1 + #else + #define VMA_DEDICATED_ALLOCATION 0 + #endif +#endif + +#if !defined(VMA_BIND_MEMORY2) + #if VK_KHR_bind_memory2 + #define VMA_BIND_MEMORY2 1 + #else + #define VMA_BIND_MEMORY2 0 + #endif +#endif + +#if !defined(VMA_MEMORY_BUDGET) + #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000) + #define VMA_MEMORY_BUDGET 1 + #else + #define VMA_MEMORY_BUDGET 0 + #endif +#endif + +// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers. +#if !defined(VMA_BUFFER_DEVICE_ADDRESS) + #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000 + #define VMA_BUFFER_DEVICE_ADDRESS 1 + #else + #define VMA_BUFFER_DEVICE_ADDRESS 0 + #endif +#endif + +// Defined to 1 when VK_EXT_memory_priority device extension is defined in Vulkan headers. +#if !defined(VMA_MEMORY_PRIORITY) + #if VK_EXT_memory_priority + #define VMA_MEMORY_PRIORITY 1 + #else + #define VMA_MEMORY_PRIORITY 0 + #endif +#endif + +// Defined to 1 when VK_KHR_maintenance4 device extension is defined in Vulkan headers. +#if !defined(VMA_KHR_MAINTENANCE4) + #if VK_KHR_maintenance4 + #define VMA_KHR_MAINTENANCE4 1 + #else + #define VMA_KHR_MAINTENANCE4 0 + #endif +#endif + +// Defined to 1 when VK_KHR_maintenance5 device extension is defined in Vulkan headers. +#if !defined(VMA_KHR_MAINTENANCE5) + #if VK_KHR_maintenance5 + #define VMA_KHR_MAINTENANCE5 1 + #else + #define VMA_KHR_MAINTENANCE5 0 + #endif +#endif + + +// Defined to 1 when VK_KHR_external_memory device extension is defined in Vulkan headers. +#if !defined(VMA_EXTERNAL_MEMORY) + #if VK_KHR_external_memory + #define VMA_EXTERNAL_MEMORY 1 + #else + #define VMA_EXTERNAL_MEMORY 0 + #endif +#endif + +// Defined to 1 when VK_KHR_external_memory_win32 device extension is defined in Vulkan headers. +#if !defined(VMA_EXTERNAL_MEMORY_WIN32) + #if VK_KHR_external_memory_win32 + #define VMA_EXTERNAL_MEMORY_WIN32 1 + #else + #define VMA_EXTERNAL_MEMORY_WIN32 0 + #endif +#endif + +// Define these macros to decorate all public functions with additional code, +// before and after returned type, appropriately. This may be useful for +// exporting the functions when compiling VMA as a separate library. Example: +// #define VMA_CALL_PRE __declspec(dllexport) +// #define VMA_CALL_POST __cdecl +#ifndef VMA_CALL_PRE + #define VMA_CALL_PRE +#endif +#ifndef VMA_CALL_POST + #define VMA_CALL_POST +#endif + +// Define this macro to decorate pNext pointers with an attribute specifying the Vulkan +// structure that will be extended via the pNext chain. +#ifndef VMA_EXTENDS_VK_STRUCT + #define VMA_EXTENDS_VK_STRUCT(vkStruct) +#endif + +// Define this macro to decorate pointers with an attribute specifying the +// length of the array they point to if they are not null. +// +// The length may be one of +// - The name of another parameter in the argument list where the pointer is declared +// - The name of another member in the struct where the pointer is declared +// - The name of a member of a struct type, meaning the value of that member in +// the context of the call. For example +// VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount"), +// this means the number of memory heaps available in the device associated +// with the VmaAllocator being dealt with. +#ifndef VMA_LEN_IF_NOT_NULL + #define VMA_LEN_IF_NOT_NULL(len) +#endif + +// The VMA_NULLABLE macro is defined to be _Nullable when compiling with Clang. +// see: https://clang.llvm.org/docs/AttributeReference.html#nullable +#ifndef VMA_NULLABLE + #ifdef __clang__ + #define VMA_NULLABLE _Nullable + #else + #define VMA_NULLABLE + #endif +#endif + +// The VMA_NOT_NULL macro is defined to be _Nonnull when compiling with Clang. +// see: https://clang.llvm.org/docs/AttributeReference.html#nonnull +#ifndef VMA_NOT_NULL + #ifdef __clang__ + #define VMA_NOT_NULL _Nonnull + #else + #define VMA_NOT_NULL + #endif +#endif + +// If non-dispatchable handles are represented as pointers then we can give +// then nullability annotations +#ifndef VMA_NOT_NULL_NON_DISPATCHABLE + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VMA_NOT_NULL_NON_DISPATCHABLE VMA_NOT_NULL + #else + #define VMA_NOT_NULL_NON_DISPATCHABLE + #endif +#endif + +#ifndef VMA_NULLABLE_NON_DISPATCHABLE + #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + #define VMA_NULLABLE_NON_DISPATCHABLE VMA_NULLABLE + #else + #define VMA_NULLABLE_NON_DISPATCHABLE + #endif +#endif + +#ifndef VMA_STATS_STRING_ENABLED + #define VMA_STATS_STRING_ENABLED 1 +#endif + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// INTERFACE +// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// Sections for managing code placement in file, only for development purposes e.g. for convenient folding inside an IDE. +#ifndef _VMA_ENUM_DECLARATIONS + +/** +\addtogroup group_init +@{ +*/ + +/// Flags for created #VmaAllocator. +typedef enum VmaAllocatorCreateFlagBits +{ + /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you. + + Using this flag may increase performance because internal mutexes are not used. + */ + VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001, + /** \brief Enables usage of VK_KHR_dedicated_allocation extension. + + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + + Using this extension will automatically allocate dedicated blocks of memory for + some buffers and images instead of suballocating place for them out of bigger + memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT + flag) when it is recommended by the driver. It may improve performance on some + GPUs. + + You may set this flag only if you found out that following device extensions are + supported, you enabled them while creating Vulkan device passed as + VmaAllocatorCreateInfo::device, and you want them to be used internally by this + library: + + - VK_KHR_get_memory_requirements2 (device extension) + - VK_KHR_dedicated_allocation (device extension) + + When this flag is set, you can experience following warnings reported by Vulkan + validation layer. You can ignore them. + + > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. + */ + VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002, + /** + Enables usage of VK_KHR_bind_memory2 extension. + + The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`. + When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1. + + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library. + + The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`, + which allow to pass a chain of `pNext` structures while binding. + This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2(). + */ + VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004, + /** + Enables usage of VK_EXT_memory_budget extension. + + You may set this flag only if you found out that this device extension is supported, + you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + and you want it to be used internally by this library, along with another instance extension + VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted). + + The extension provides query for current memory usage and budget, which will probably + be more accurate than an estimation used by the library otherwise. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008, + /** + Enables usage of VK_AMD_device_coherent_memory extension. + + You may set this flag only if you: + + - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device, + - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device, + - want it to be used internally by this library. + + The extension and accompanying device feature provide access to memory types with + `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags. + They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR. + + When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. + To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type, + returning `VK_ERROR_FEATURE_NOT_PRESENT`. + */ + VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010, + /** + Enables usage of "buffer device address" feature, which allows you to use function + `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader. + + You may set this flag only if you: + + 1. (For Vulkan version < 1.2) Found as available and enabled device extension + VK_KHR_buffer_device_address. + This extension is promoted to core Vulkan 1.2. + 2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress`. + + When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT` using VMA. + The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT` to + allocated memory blocks wherever it might be needed. + + For more information, see documentation chapter \ref enabling_buffer_device_address. + */ + VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020, + /** + Enables usage of VK_EXT_memory_priority extension in the library. + + You may set this flag only if you found available and enabled this device extension, + along with `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority == VK_TRUE`, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + + When this flag is used, VmaAllocationCreateInfo::priority and VmaPoolCreateInfo::priority + are used to set priorities of allocated Vulkan memory. Without it, these variables are ignored. + + A priority must be a floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + Larger values are higher priority. The granularity of the priorities is implementation-dependent. + It is automatically passed to every call to `vkAllocateMemory` done by the library using structure `VkMemoryPriorityAllocateInfoEXT`. + The value to be used for default priority is 0.5. + For more details, see the documentation of the VK_EXT_memory_priority extension. + */ + VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT = 0x00000040, + /** + Enables usage of VK_KHR_maintenance4 extension in the library. + + You may set this flag only if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + */ + VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT = 0x00000080, + /** + Enables usage of VK_KHR_maintenance5 extension in the library. + + You should set this flag if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + */ + VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT = 0x00000100, + + /** + Enables usage of VK_KHR_external_memory_win32 extension in the library. + + You should set this flag if you found available and enabled this device extension, + while creating Vulkan device passed as VmaAllocatorCreateInfo::device. + For more information, see \ref vk_khr_external_memory_win32. + */ + VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT = 0x00000200, + + VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaAllocatorCreateFlagBits; +/// See #VmaAllocatorCreateFlagBits. +typedef VkFlags VmaAllocatorCreateFlags; + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/// \brief Intended usage of the allocated memory. +typedef enum VmaMemoryUsage +{ + /** No intended memory usage specified. + Use other members of VmaAllocationCreateInfo to specify your requirements. + */ + VMA_MEMORY_USAGE_UNKNOWN = 0, + /** + \deprecated Obsolete, preserved for backward compatibility. + Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_GPU_ONLY = 1, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`. + */ + VMA_MEMORY_USAGE_CPU_ONLY = 2, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_CPU_TO_GPU = 3, + /** + \deprecated Obsolete, preserved for backward compatibility. + Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`. + */ + VMA_MEMORY_USAGE_GPU_TO_CPU = 4, + /** + \deprecated Obsolete, preserved for backward compatibility. + Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + */ + VMA_MEMORY_USAGE_CPU_COPY = 5, + /** + Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`. + Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation. + + Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`. + + Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + */ + VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6, + /** + Selects best memory type automatically. + This flag is recommended for most common use cases. + + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. + + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO = 7, + /** + Selects best memory type automatically with preference for GPU (device) memory. + + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. + + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8, + /** + Selects best memory type automatically with preference for CPU (host) memory. + + When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT), + you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT + in VmaAllocationCreateInfo::flags. + + It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g. + vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo() + and not with generic memory allocation functions. + */ + VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9, + + VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF +} VmaMemoryUsage; + +/// Flags to be passed as VmaAllocationCreateInfo::flags. +typedef enum VmaAllocationCreateFlagBits +{ + /** \brief Set this flag if the allocation should have its own memory block. + + Use it for special, big resources, like fullscreen images used as attachments. + + If you use this flag while creating a buffer or an image, `VkMemoryDedicatedAllocateInfo` + structure is applied if possible. + */ + VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001, + + /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block. + + If new allocation cannot be placed in any of the existing blocks, allocation + fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error. + + You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and + #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense. + */ + VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002, + /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. + + Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData. + + It is valid to use this flag for allocation made from memory type that is not + `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is + useful if you need an allocation that is efficient to use on GPU + (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that + support it (e.g. Intel GPU). + */ + VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004, + /** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead. + + Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a + null-terminated string. Instead of copying pointer value, a local copy of the + string is made and stored in allocation's `pName`. The string is automatically + freed together with the allocation. It is also used in vmaBuildStatsString(). + */ + VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020, + /** Allocation will be created from upper stack in a double stack pool. + + This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040, + /** Create both buffer/image and allocation, but don't bind them together. + It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. + The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage(). + Otherwise it is ignored. + + If you want to make sure the new buffer/image is not tied to the new memory allocation + through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block, + use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT. + */ + VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080, + /** Create allocation only if additional device memory required for it, if any, won't exceed + memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + */ + VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100, + /** \brief Set this flag if the allocated memory will have aliasing resources. + + Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. + Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors. + */ + VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200, + /** + Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). + + - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + This includes allocations created in \ref custom_memory_pools. + + Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number, + never read or accessed randomly, so a memory type can be selected that is uncached and write-combined. + + \warning Violating this declaration may work correctly, but will likely be very slow. + Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;` + Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400, + /** + Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT). + + - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value, + you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect. + - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`. + This includes allocations created in \ref custom_memory_pools. + + Declares that mapped memory can be read, written, and accessed in random order, + so a `HOST_CACHED` memory type is preferred. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 0x00000800, + /** + Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, + it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected + if it may improve performance. + + By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type + (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and + issue an explicit transfer to write/read your data. + To prepare for this possibility, don't forget to add appropriate flags like + `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image. + */ + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 0x00001000, + /** Allocation strategy that chooses smallest possible free range for the allocation + to minimize memory usage and fragmentation, possibly at the expense of allocation time. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 0x00010000, + /** Allocation strategy that chooses first suitable free range for the allocation - + not necessarily in terms of the smallest offset but the one that is easiest and fastest to find + to minimize allocation time, possibly at the expense of allocation quality. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 0x00020000, + /** Allocation strategy that chooses always the lowest offset in available space. + This is not the most efficient strategy but achieves highly packed data. + Used internally by defragmentation, not recommended in typical usage. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 0x00040000, + /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT. + */ + VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, + /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT. + */ + VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, + /** A bit mask to extract only `STRATEGY` bits from entire set of flags. + */ + VMA_ALLOCATION_CREATE_STRATEGY_MASK = + VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT | + VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT | + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + + VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaAllocationCreateFlagBits; +/// See #VmaAllocationCreateFlagBits. +typedef VkFlags VmaAllocationCreateFlags; + +/// Flags to be passed as VmaPoolCreateInfo::flags. +typedef enum VmaPoolCreateFlagBits +{ + /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. + + This is an optional optimization flag. + + If you always allocate using vmaCreateBuffer(), vmaCreateImage(), + vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator + knows exact type of your allocations so it can handle Buffer-Image Granularity + in the optimal way. + + If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(), + exact type of such allocations is not known, so allocator must be conservative + in handling Buffer-Image Granularity, which can lead to suboptimal allocation + (wasted memory). In that case, if you can make sure you always allocate only + buffers and linear images or only optimal images out of this pool, use this flag + to make allocator disregard Buffer-Image Granularity and so make allocations + faster and more optimal. + */ + VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002, + + /** \brief Enables alternative, linear allocation algorithm in this pool. + + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. + + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + */ + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004, + + /** Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_POOL_CREATE_ALGORITHM_MASK = + VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT, + + VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaPoolCreateFlagBits; +/// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits. +typedef VkFlags VmaPoolCreateFlags; + +/// Flags to be passed as VmaDefragmentationInfo::flags. +typedef enum VmaDefragmentationFlagBits +{ + /* \brief Use simple but fast algorithm for defragmentation. + May not achieve best results but will require least time to compute and least allocations to copy. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 0x1, + /* \brief Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified. + Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 0x2, + /* \brief Perform full defragmentation of memory. + Can result in notably more time to compute and allocations to copy, but will achieve best memory packing. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 0x4, + /** \brief Use the most roboust algorithm at the cost of time to compute and number of copies to make. + Only available when bufferImageGranularity is greater than 1, since it aims to reduce + alignment issues between different types of resources. + Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT. + */ + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8, + + /// A bit mask to extract only `ALGORITHM` bits from entire set of flags. + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK = + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT | + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT | + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT | + VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT, + + VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaDefragmentationFlagBits; +/// See #VmaDefragmentationFlagBits. +typedef VkFlags VmaDefragmentationFlags; + +/// Operation performed on single defragmentation move. See structure #VmaDefragmentationMove. +typedef enum VmaDefragmentationMoveOperation +{ + /// Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass(). + VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0, + /// Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged. + VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1, + /// Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed. + VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2, +} VmaDefragmentationMoveOperation; + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. +typedef enum VmaVirtualBlockCreateFlagBits +{ + /** \brief Enables alternative, linear allocation algorithm in this virtual block. + + Specify this flag to enable linear allocation algorithm, which always creates + new allocations after last one and doesn't reuse space from allocations freed in + between. It trades memory consumption for simplified algorithm and data + structure, which has better performance and uses less memory for metadata. + + By using this flag, you can achieve behavior of free-at-once, stack, + ring buffer, and double stack. + For details, see documentation chapter \ref linear_algorithm. + */ + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001, + + /** \brief Bit mask to extract only `ALGORITHM` bits from entire set of flags. + */ + VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK = + VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT, + + VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaVirtualBlockCreateFlagBits; +/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits. +typedef VkFlags VmaVirtualBlockCreateFlags; + +/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. +typedef enum VmaVirtualAllocationCreateFlagBits +{ + /** \brief Allocation will be created from upper stack in a double stack pool. + + This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT, + /** \brief Allocation strategy that tries to minimize memory usage. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT, + /** \brief Allocation strategy that tries to minimize allocation time. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT, + /** Allocation strategy that chooses always the lowest offset in available space. + This is not the most efficient strategy but achieves highly packed data. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags. + + These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits. + */ + VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK, + + VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VmaVirtualAllocationCreateFlagBits; +/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits. +typedef VkFlags VmaVirtualAllocationCreateFlags; + +/** @} */ + +#endif // _VMA_ENUM_DECLARATIONS + +#ifndef _VMA_DATA_TYPES_DECLARATIONS + +/** +\addtogroup group_init +@{ */ + +/** \struct VmaAllocator +\brief Represents main object of this library initialized. + +Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it. +Call function vmaDestroyAllocator() to destroy it. + +It is recommended to create just one object of this type per `VkDevice` object, +right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed. +*/ +VK_DEFINE_HANDLE(VmaAllocator) + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** \struct VmaPool +\brief Represents custom memory pool + +Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it. +Call function vmaDestroyPool() to destroy it. + +For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools). +*/ +VK_DEFINE_HANDLE(VmaPool) + +/** \struct VmaAllocation +\brief Represents single memory allocation. + +It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type +plus unique offset. + +There are multiple ways to create such object. +You need to fill structure VmaAllocationCreateInfo. +For more information see [Choosing memory type](@ref choosing_memory_type). + +Although the library provides convenience functions that create Vulkan buffer or image, +allocate memory for it and bind them together, +binding of the allocation to a buffer or an image is out of scope of the allocation itself. +Allocation object can exist without buffer/image bound, +binding can be done manually by the user, and destruction of it can be done +independently of destruction of the allocation. + +The object also remembers its size and some other information. +To retrieve this information, use function vmaGetAllocationInfo() and inspect +returned structure VmaAllocationInfo. +*/ +VK_DEFINE_HANDLE(VmaAllocation) + +/** \struct VmaDefragmentationContext +\brief An opaque object that represents started defragmentation process. + +Fill structure #VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it. +Call function vmaEndDefragmentation() to destroy it. +*/ +VK_DEFINE_HANDLE(VmaDefragmentationContext) + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \struct VmaVirtualAllocation +\brief Represents single memory allocation done inside VmaVirtualBlock. + +Use it as a unique identifier to virtual allocation within the single block. + +Use value `VK_NULL_HANDLE` to represent a null/invalid allocation. +*/ +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation) + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \struct VmaVirtualBlock +\brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory. + +Fill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it. +For more information, see documentation chapter \ref virtual_allocator. + +This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally. +*/ +VK_DEFINE_HANDLE(VmaVirtualBlock) + +/** @} */ + +/** +\addtogroup group_init +@{ +*/ + +/// Callback function called after successful vkAllocateMemory. +typedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); + +/// Callback function called before vkFreeMemory. +typedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryType, + VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory, + VkDeviceSize size, + void* VMA_NULLABLE pUserData); + +/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`. + +Provided for informative purpose, e.g. to gather statistics about number of +allocations or total amount of memory allocated in Vulkan. + +Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. +*/ +typedef struct VmaDeviceMemoryCallbacks +{ + /// Optional, can be null. + PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate; + /// Optional, can be null. + PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree; + /// Optional, can be null. + void* VMA_NULLABLE pUserData; +} VmaDeviceMemoryCallbacks; + +/** \brief Pointers to some Vulkan functions - a subset used by the library. + +Used in VmaAllocatorCreateInfo::pVulkanFunctions. +*/ +typedef struct VmaVulkanFunctions +{ + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr; + /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS. + PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr; + PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties; + PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties; + PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory; + PFN_vkFreeMemory VMA_NULLABLE vkFreeMemory; + PFN_vkMapMemory VMA_NULLABLE vkMapMemory; + PFN_vkUnmapMemory VMA_NULLABLE vkUnmapMemory; + PFN_vkFlushMappedMemoryRanges VMA_NULLABLE vkFlushMappedMemoryRanges; + PFN_vkInvalidateMappedMemoryRanges VMA_NULLABLE vkInvalidateMappedMemoryRanges; + PFN_vkBindBufferMemory VMA_NULLABLE vkBindBufferMemory; + PFN_vkBindImageMemory VMA_NULLABLE vkBindImageMemory; + PFN_vkGetBufferMemoryRequirements VMA_NULLABLE vkGetBufferMemoryRequirements; + PFN_vkGetImageMemoryRequirements VMA_NULLABLE vkGetImageMemoryRequirements; + PFN_vkCreateBuffer VMA_NULLABLE vkCreateBuffer; + PFN_vkDestroyBuffer VMA_NULLABLE vkDestroyBuffer; + PFN_vkCreateImage VMA_NULLABLE vkCreateImage; + PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage; + PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer; +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + /// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR; + /// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension. + PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR; +#endif +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + /// Fetch "vkBindBufferMemory2" on Vulkan >= 1.1, fetch "vkBindBufferMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR; + /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension. + PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR; +#endif +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + /// Fetch from "vkGetPhysicalDeviceMemoryProperties2" on Vulkan >= 1.1, but you can also fetch it from "vkGetPhysicalDeviceMemoryProperties2KHR" if you enabled extension VK_KHR_get_physical_device_properties2. + PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR; +#endif +#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + /// Fetch from "vkGetDeviceBufferMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceBufferMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. + PFN_vkGetDeviceBufferMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceBufferMemoryRequirements; + /// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4. + PFN_vkGetDeviceImageMemoryRequirementsKHR VMA_NULLABLE vkGetDeviceImageMemoryRequirements; +#endif +#if VMA_EXTERNAL_MEMORY_WIN32 + PFN_vkGetMemoryWin32HandleKHR VMA_NULLABLE vkGetMemoryWin32HandleKHR; +#else + void* VMA_NULLABLE vkGetMemoryWin32HandleKHR; +#endif +} VmaVulkanFunctions; + +/// Description of a Allocator to be created. +typedef struct VmaAllocatorCreateInfo +{ + /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum. + VmaAllocatorCreateFlags flags; + /// Vulkan physical device. + /** It must be valid throughout whole lifetime of created allocator. */ + VkPhysicalDevice VMA_NOT_NULL physicalDevice; + /// Vulkan device. + /** It must be valid throughout whole lifetime of created allocator. */ + VkDevice VMA_NOT_NULL device; + /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional. + /** Set to 0 to use default, which is currently 256 MiB. */ + VkDeviceSize preferredLargeHeapBlockSize; + /// Custom CPU memory allocation callbacks. Optional. + /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */ + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; + /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional. + /** Optional, can be null. */ + const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks; + /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. + + If not NULL, it must be a pointer to an array of + `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on + maximum number of bytes that can be allocated out of particular Vulkan memory + heap. + + Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that + heap. This is also the default in case of `pHeapSizeLimit` = NULL. + + If there is a limit defined for a heap: + + - If user tries to allocate more memory from that heap using this allocator, + the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the + value of this limit will be reported instead when using vmaGetMemoryProperties(). + + Warning! Using this feature may not be equivalent to installing a GPU with + smaller amount of memory, because graphics driver doesn't necessary fail new + allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is + exceeded. It may return success and just silently migrate some device memory + blocks to system RAM. This driver behavior can also be controlled using + VK_AMD_memory_overallocation_behavior extension. + */ + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pHeapSizeLimit; + + /** \brief Pointers to Vulkan functions. Can be null. + + For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions). + */ + const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions; + /** \brief Handle to Vulkan instance object. + + Starting from version 3.0.0 this member is no longer optional, it must be set! + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Optional. Vulkan version that the application uses. + + It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`. + The patch version number specified is ignored. Only the major and minor versions are considered. + Only versions 1.0...1.4 are supported by the current implementation. + Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`. + It must match the Vulkan version used by the application and supported on the selected physical device, + so it must be no higher than `VkApplicationInfo::apiVersion` passed to `vkCreateInstance` + and no higher than `VkPhysicalDeviceProperties::apiVersion` found on the physical device used. + */ + uint32_t vulkanApiVersion; +#if VMA_EXTERNAL_MEMORY + /** \brief Either null or a pointer to an array of external memory handle types for each Vulkan memory type. + + If not NULL, it must be a pointer to an array of `VkPhysicalDeviceMemoryProperties::memoryTypeCount` + elements, defining external memory handle types of particular Vulkan memory type, + to be passed using `VkExportMemoryAllocateInfoKHR`. + + Any of the elements may be equal to 0, which means not to use `VkExportMemoryAllocateInfoKHR` on this memory type. + This is also the default in case of `pTypeExternalMemoryHandleTypes` = NULL. + */ + const VkExternalMemoryHandleTypeFlagsKHR* VMA_NULLABLE VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryTypeCount") pTypeExternalMemoryHandleTypes; +#endif // #if VMA_EXTERNAL_MEMORY +} VmaAllocatorCreateInfo; + +/// Information about existing #VmaAllocator object. +typedef struct VmaAllocatorInfo +{ + /** \brief Handle to Vulkan instance object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::instance. + */ + VkInstance VMA_NOT_NULL instance; + /** \brief Handle to Vulkan physical device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice. + */ + VkPhysicalDevice VMA_NOT_NULL physicalDevice; + /** \brief Handle to Vulkan device object. + + This is the same value as has been passed through VmaAllocatorCreateInfo::device. + */ + VkDevice VMA_NOT_NULL device; +} VmaAllocatorInfo; + +/** @} */ + +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total. + +These are fast to calculate. +See functions: vmaGetHeapBudgets(), vmaGetPoolStatistics(). +*/ +typedef struct VmaStatistics +{ + /** \brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated. + */ + uint32_t blockCount; + /** \brief Number of #VmaAllocation objects allocated. + + Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`. + */ + uint32_t allocationCount; + /** \brief Number of bytes allocated in `VkDeviceMemory` blocks. + + \note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object + (e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls + "allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image. + */ + VkDeviceSize blockBytes; + /** \brief Total number of bytes occupied by all #VmaAllocation objects. + + Always less or equal than `blockBytes`. + Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan + but unused by any #VmaAllocation. + */ + VkDeviceSize allocationBytes; +} VmaStatistics; + +/** \brief More detailed statistics than #VmaStatistics. + +These are slower to calculate. Use for debugging purposes. +See functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics(). + +Previous version of the statistics API provided averages, but they have been removed +because they can be easily calculated as: + +\code +VkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount; +VkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes; +VkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount; +\endcode +*/ +typedef struct VmaDetailedStatistics +{ + /// Basic statistics. + VmaStatistics statistics; + /// Number of free ranges of memory between allocations. + uint32_t unusedRangeCount; + /// Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations. + VkDeviceSize allocationSizeMin; + /// Largest allocation size. 0 if there are 0 allocations. + VkDeviceSize allocationSizeMax; + /// Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges. + VkDeviceSize unusedRangeSizeMin; + /// Largest empty range size. 0 if there are 0 empty ranges. + VkDeviceSize unusedRangeSizeMax; +} VmaDetailedStatistics; + +/** \brief General statistics from current state of the Allocator - +total memory usage across all memory heaps and types. + +These are slower to calculate. Use for debugging purposes. +See function vmaCalculateStatistics(). +*/ +typedef struct VmaTotalStatistics +{ + VmaDetailedStatistics memoryType[VK_MAX_MEMORY_TYPES]; + VmaDetailedStatistics memoryHeap[VK_MAX_MEMORY_HEAPS]; + VmaDetailedStatistics total; +} VmaTotalStatistics; + +/** \brief Statistics of current memory usage and available budget for a specific memory heap. + +These are fast to calculate. +See function vmaGetHeapBudgets(). +*/ +typedef struct VmaBudget +{ + /** \brief Statistics fetched from the library. + */ + VmaStatistics statistics; + /** \brief Estimated current memory usage of the program, in bytes. + + Fetched from system using VK_EXT_memory_budget extension if enabled. + + It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects + also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or + `VkDeviceMemory` blocks allocated outside of this library, if any. + */ + VkDeviceSize usage; + /** \brief Estimated amount of memory available to the program, in bytes. + + Fetched from system using VK_EXT_memory_budget extension if enabled. + + It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors + external to the program, decided by the operating system. + Difference `budget - usage` is the amount of additional memory that can probably + be allocated without problems. Exceeding the budget may result in various problems. + */ + VkDeviceSize budget; +} VmaBudget; + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** \brief Parameters of new #VmaAllocation. + +To be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others. +*/ +typedef struct VmaAllocationCreateInfo +{ + /// Use #VmaAllocationCreateFlagBits enum. + VmaAllocationCreateFlags flags; + /** \brief Intended usage of memory. + + You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n + If `pool` is not null, this member is ignored. + */ + VmaMemoryUsage usage; + /** \brief Flags that must be set in a Memory Type chosen for an allocation. + + Leave 0 if you specify memory requirements in other way. \n + If `pool` is not null, this member is ignored.*/ + VkMemoryPropertyFlags requiredFlags; + /** \brief Flags that preferably should be set in a memory type chosen for an allocation. + + Set to 0 if no additional flags are preferred. \n + If `pool` is not null, this member is ignored. */ + VkMemoryPropertyFlags preferredFlags; + /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation. + + Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if + it meets other requirements specified by this structure, with no further + restrictions on memory type index. \n + If `pool` is not null, this member is ignored. + */ + uint32_t memoryTypeBits; + /** \brief Pool that this allocation should be created in. + + Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members: + `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored. + */ + VmaPool VMA_NULLABLE pool; + /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData(). + + If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either + null or pointer to a null-terminated string. The string will be then copied to + internal buffer, so it doesn't need to be valid after allocation call. + */ + void* VMA_NULLABLE pUserData; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations. + + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object + and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + Otherwise, it has the priority of a memory block where it is placed and this variable is ignored. + */ + float priority; +} VmaAllocationCreateInfo; + +/// Describes parameter of created #VmaPool. +typedef struct VmaPoolCreateInfo +{ + /** \brief Vulkan memory type index to allocate this pool from. + */ + uint32_t memoryTypeIndex; + /** \brief Use combination of #VmaPoolCreateFlagBits. + */ + VmaPoolCreateFlags flags; + /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional. + + Specify nonzero to set explicit, constant size of memory blocks used by this + pool. + + Leave 0 to use default and let the library manage block sizes automatically. + Sizes of particular blocks may vary. + In this case, the pool will also support dedicated allocations. + */ + VkDeviceSize blockSize; + /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty. + + Set to 0 to have no preallocated blocks and allow the pool be completely empty. + */ + size_t minBlockCount; + /** \brief Maximum number of blocks that can be allocated in this pool. Optional. + + Set to 0 to use default, which is `SIZE_MAX`, which means no limit. + + Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated + throughout whole lifetime of this pool. + */ + size_t maxBlockCount; + /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations. + + It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object. + Otherwise, this variable is ignored. + */ + float priority; + /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0. + + Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two. + It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough, + e.g. when doing interop with OpenGL. + */ + VkDeviceSize minAllocationAlignment; + /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional. + + Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`. + It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`. + Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool. + + Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`, + can be attached automatically by this library when using other, more convenient of its features. + */ + void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkMemoryAllocateInfo) pMemoryAllocateNext; +} VmaPoolCreateInfo; + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** +Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo(). + +There is also an extended version of this structure that carries additional parameters: #VmaAllocationInfo2. +*/ +typedef struct VmaAllocationInfo +{ + /** \brief Memory type index that this allocation was allocated from. + + It never changes. + */ + uint32_t memoryType; + /** \brief Handle to Vulkan memory object. + + Same memory object can be shared by multiple allocations. + + It can change after the allocation is moved during \ref defragmentation. + */ + VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory; + /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation. + + You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function + vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image, + not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation + and apply this offset automatically. + + It can change after the allocation is moved during \ref defragmentation. + */ + VkDeviceSize offset; + /** \brief Size of this allocation, in bytes. + + It never changes. + + \note Allocation size returned in this variable may be greater than the size + requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the + allocation is accessible for operations on memory e.g. using a pointer after + mapping with vmaMapMemory(), but operations on the resource e.g. using + `vkCmdCopyBuffer` must be limited to the size of the resource. + */ + VkDeviceSize size; + /** \brief Pointer to the beginning of this allocation as mapped data. + + If the allocation hasn't been mapped using vmaMapMemory() and hasn't been + created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null. + + It can change after call to vmaMapMemory(), vmaUnmapMemory(). + It can also change after the allocation is moved during \ref defragmentation. + */ + void* VMA_NULLABLE pMappedData; + /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData(). + + It can change after call to vmaSetAllocationUserData() for this allocation. + */ + void* VMA_NULLABLE pUserData; + /** \brief Custom allocation name that was set with vmaSetAllocationName(). + + It can change after call to vmaSetAllocationName() for this allocation. + + Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with + additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED]. + */ + const char* VMA_NULLABLE pName; +} VmaAllocationInfo; + +/// Extended parameters of a #VmaAllocation object that can be retrieved using function vmaGetAllocationInfo2(). +typedef struct VmaAllocationInfo2 +{ + /** \brief Basic parameters of the allocation. + + If you need only these, you can use function vmaGetAllocationInfo() and structure #VmaAllocationInfo instead. + */ + VmaAllocationInfo allocationInfo; + /** \brief Size of the `VkDeviceMemory` block that the allocation belongs to. + + In case of an allocation with dedicated memory, it will be equal to `allocationInfo.size`. + */ + VkDeviceSize blockSize; + /** \brief `VK_TRUE` if the allocation has dedicated memory, `VK_FALSE` if it was placed as part of a larger memory block. + + When `VK_TRUE`, it also means `VkMemoryDedicatedAllocateInfo` was used when creating the allocation + (if VK_KHR_dedicated_allocation extension or Vulkan version >= 1.1 is enabled). + */ + VkBool32 dedicatedMemory; +} VmaAllocationInfo2; + +/** Callback function called during vmaBeginDefragmentation() to check custom criterion about ending current defragmentation pass. + +Should return true if the defragmentation needs to stop current pass. +*/ +typedef VkBool32 (VKAPI_PTR* PFN_vmaCheckDefragmentationBreakFunction)(void* VMA_NULLABLE pUserData); + +/** \brief Parameters for defragmentation. + +To be used with function vmaBeginDefragmentation(). +*/ +typedef struct VmaDefragmentationInfo +{ + /// \brief Use combination of #VmaDefragmentationFlagBits. + VmaDefragmentationFlags flags; + /** \brief Custom pool to be defragmented. + + If null then default pools will undergo defragmentation process. + */ + VmaPool VMA_NULLABLE pool; + /** \brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places. + + `0` means no limit. + */ + VkDeviceSize maxBytesPerPass; + /** \brief Maximum number of allocations that can be moved during single pass to a different place. + + `0` means no limit. + */ + uint32_t maxAllocationsPerPass; + /** \brief Optional custom callback for stopping vmaBeginDefragmentation(). + + Have to return true for breaking current defragmentation pass. + */ + PFN_vmaCheckDefragmentationBreakFunction VMA_NULLABLE pfnBreakCallback; + /// \brief Optional data to pass to custom callback for stopping pass of defragmentation. + void* VMA_NULLABLE pBreakCallbackUserData; +} VmaDefragmentationInfo; + +/// Single move of an allocation to be done for defragmentation. +typedef struct VmaDefragmentationMove +{ + /// Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it. + VmaDefragmentationMoveOperation operation; + /// Allocation that should be moved. + VmaAllocation VMA_NOT_NULL srcAllocation; + /** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`. + + \warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass, + to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory(). + vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory. + */ + VmaAllocation VMA_NOT_NULL dstTmpAllocation; +} VmaDefragmentationMove; + +/** \brief Parameters for incremental defragmentation steps. + +To be used with function vmaBeginDefragmentationPass(). +*/ +typedef struct VmaDefragmentationPassMoveInfo +{ + /// Number of elements in the `pMoves` array. + uint32_t moveCount; + /** \brief Array of moves to be performed by the user in the current defragmentation pass. + + Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass(). + + For each element, you should: + + 1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset. + 2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`. + 3. Make sure these commands finished executing on the GPU. + 4. Destroy the old buffer/image. + + Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass(). + After this call, the allocation will point to the new place in memory. + + Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. + + Alternatively, if you decide you want to completely remove the allocation: + + 1. Destroy its buffer/image. + 2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. + + Then, after vmaEndDefragmentationPass() the allocation will be freed. + */ + VmaDefragmentationMove* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(moveCount) pMoves; +} VmaDefragmentationPassMoveInfo; + +/// Statistics returned for defragmentation process in function vmaEndDefragmentation(). +typedef struct VmaDefragmentationStats +{ + /// Total number of bytes that have been copied while moving allocations to different places. + VkDeviceSize bytesMoved; + /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects. + VkDeviceSize bytesFreed; + /// Number of allocations that have been moved to different places. + uint32_t allocationsMoved; + /// Number of empty `VkDeviceMemory` objects that have been released to the system. + uint32_t deviceMemoryBlocksFreed; +} VmaDefragmentationStats; + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock(). +typedef struct VmaVirtualBlockCreateInfo +{ + /** \brief Total size of the virtual block. + + Sizes can be expressed in bytes or any units you want as long as you are consistent in using them. + For example, if you allocate from some array of structures, 1 can mean single instance of entire structure. + */ + VkDeviceSize size; + + /** \brief Use combination of #VmaVirtualBlockCreateFlagBits. + */ + VmaVirtualBlockCreateFlags flags; + + /** \brief Custom CPU memory allocation callbacks. Optional. + + Optional, can be null. When specified, they will be used for all CPU-side memory allocations. + */ + const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks; +} VmaVirtualBlockCreateInfo; + +/// Parameters of created virtual allocation to be passed to vmaVirtualAllocate(). +typedef struct VmaVirtualAllocationCreateInfo +{ + /** \brief Size of the allocation. + + Cannot be zero. + */ + VkDeviceSize size; + /** \brief Required alignment of the allocation. Optional. + + Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset. + */ + VkDeviceSize alignment; + /** \brief Use combination of #VmaVirtualAllocationCreateFlagBits. + */ + VmaVirtualAllocationCreateFlags flags; + /** \brief Custom pointer to be associated with the allocation. Optional. + + It can be any value and can be used for user-defined purposes. It can be fetched or changed later. + */ + void* VMA_NULLABLE pUserData; +} VmaVirtualAllocationCreateInfo; + +/// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo(). +typedef struct VmaVirtualAllocationInfo +{ + /** \brief Offset of the allocation. + + Offset at which the allocation was made. + */ + VkDeviceSize offset; + /** \brief Size of the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::size. + */ + VkDeviceSize size; + /** \brief Custom pointer associated with the allocation. + + Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData(). + */ + void* VMA_NULLABLE pUserData; +} VmaVirtualAllocationInfo; + +/** @} */ + +#endif // _VMA_DATA_TYPES_DECLARATIONS + +#ifndef _VMA_FUNCTION_HEADERS + +/** +\addtogroup group_init +@{ +*/ + +#ifdef VOLK_HEADER_VERSION +/** \brief Fully initializes `pDstVulkanFunctions` structure with Vulkan functions needed by VMA +using [volk library](https://github.com/zeux/volk). + +This function is defined in VMA header only if "volk.h" was included before it. + +To use this function properly: + +-# Initialize volk and Vulkan: + -# Call `volkInitialize()` + -# Create `VkInstance` object + -# Call `volkLoadInstance()` + -# Create `VkDevice` object + -# Call `volkLoadDevice()` +-# Fill in structure #VmaAllocatorCreateInfo, especially members: + - VmaAllocatorCreateInfo::device + - VmaAllocatorCreateInfo::vulkanApiVersion + - VmaAllocatorCreateInfo::flags - set appropriate flags for the Vulkan extensions you enabled +-# Create an instance of the #VmaVulkanFunctions structure. +-# Call vmaImportVulkanFunctionsFromVolk(). + Parameter `pAllocatorCreateInfo` is read to find out which functions should be fetched for + appropriate Vulkan version and extensions. + Parameter `pDstVulkanFunctions` is filled with those function pointers, or null if not applicable. +-# Attach the #VmaVulkanFunctions structure to VmaAllocatorCreateInfo::pVulkanFunctions. +-# Call vmaCreateAllocator() to create the #VmaAllocator object. + +Example: + +\code +VmaAllocatorCreateInfo allocatorCreateInfo = {}; +allocatorCreateInfo.physicalDevice = myPhysicalDevice; +allocatorCreateInfo.device = myDevice; +allocatorCreateInfo.instance = myInstance; +allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_3; +allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT | + VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT | + VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT; + +VmaVulkanFunctions vulkanFunctions; +VkResult res = vmaImportVulkanFunctionsFromVolk(&allocatorCreateInfo, &vulkanFunctions); +// Check res... +allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; + +VmaAllocator allocator; +res = vmaCreateAllocator(&allocatorCreateInfo, &allocator); +// Check res... +\endcode + +Internally in this function, pointers to functions related to the entire Vulkan instance are fetched using global function definitions, +while pointers to functions related to the Vulkan device are fetched using `volkLoadDeviceTable()` for given `pAllocatorCreateInfo->device`. + */ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk( + const VmaAllocatorCreateInfo* VMA_NOT_NULL pAllocatorCreateInfo, + VmaVulkanFunctions* VMA_NOT_NULL pDstVulkanFunctions); +#endif + +/// Creates #VmaAllocator object. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( + const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator); + +/// Destroys allocator object. +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( + VmaAllocator VMA_NULLABLE allocator); + +/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc. + +It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to +`VkPhysicalDevice`, `VkDevice` etc. every time using this function. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo); + +/** +PhysicalDeviceProperties are fetched from physicalDevice by the allocator. +You can access it here, without fetching it again on your own. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties); + +/** +PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. +You can access it here, without fetching it again on your own. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties); + +/** +\brief Given Memory Type Index, returns Property Flags of this memory type. + +This is just a convenience function. Same information can be obtained using +vmaGetMemoryProperties(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeIndex, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); + +/** \brief Sets index of the current frame. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t frameIndex); + +/** @} */ + +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Retrieves statistics from current state of the Allocator. + +This function is called "calculate" not "get" because it has to traverse all +internal data structures, so it may be quite slow. Use it for debugging purposes. +For faster but more brief statistics suitable to be called every frame or every allocation, +use vmaGetHeapBudgets(). + +Note that when using allocator from multiple threads, returned information may immediately +become outdated. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaTotalStatistics* VMA_NOT_NULL pStats); + +/** \brief Retrieves information about current memory usage and budget for all memory heaps. + +\param allocator +\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used. + +This function is called "get" not "calculate" because it is very fast, suitable to be called +every frame or every allocation. For more detailed statistics use vmaCalculateStatistics(). + +Note that when using allocator from multiple threads, returned information may immediately +become outdated. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( + VmaAllocator VMA_NOT_NULL allocator, + VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pBudgets); + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** +\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo. + +This algorithm tries to find a memory type that: + +- Is allowed by memoryTypeBits. +- Contains all the flags from pAllocationCreateInfo->requiredFlags. +- Matches intended usage. +- Has as many flags from pAllocationCreateInfo->preferredFlags as possible. + +\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result +from this function or any other allocating function probably means that your +device doesn't support any memory type with requested features for the specific +type of resource you want to use it for. Please check parameters of your +resource, like image layout (OPTIMAL versus LINEAR) or mip level count. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeBits, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + +/** +\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo. + +It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. +It internally creates a temporary, dummy buffer that never has memory bound. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + +/** +\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo. + +It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. +It internally creates a temporary, dummy image that never has memory bound. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + uint32_t* VMA_NOT_NULL pMemoryTypeIndex); + +/** \brief Allocates Vulkan device memory and creates #VmaPool object. + +\param allocator Allocator object. +\param pCreateInfo Parameters of pool to create. +\param[out] pPool Handle to created pool. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( + VmaAllocator VMA_NOT_NULL allocator, + const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool); + +/** \brief Destroys #VmaPool object and frees Vulkan device memory. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NULLABLE pool); + +/** @} */ + +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Retrieves statistics of existing #VmaPool object. + +\param allocator Allocator object. +\param pool Pool object. +\param[out] pPoolStats Statistics of specified pool. + +Note that when using the pool from multiple threads, returned information may immediately +become outdated. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaStatistics* VMA_NOT_NULL pPoolStats); + +/** \brief Retrieves detailed statistics of existing #VmaPool object. + +\param allocator Allocator object. +\param pool Pool object. +\param[out] pPoolStats Statistics of specified pool. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + VmaDetailedStatistics* VMA_NOT_NULL pPoolStats); + +/** @} */ + +/** +\addtogroup group_alloc +@{ +*/ + +/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions. + +Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, +`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is +`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). + +Possible return values: + +- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool. +- `VK_SUCCESS` - corruption detection has been performed and succeeded. +- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. +- Other value: Error returned by Vulkan, e.g. memory mapping failure. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool); + +/** \brief Retrieves name of a custom pool. + +After the call `ppName` is either null or points to an internally-owned null-terminated string +containing name of the pool that was previously set. The pointer becomes invalid when the pool is +destroyed or its name is changed using vmaSetPoolName(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE* VMA_NOT_NULL ppName); + +/** \brief Sets name of a custom pool. + +`pName` can be either null or pointer to a null-terminated string with new name for the pool. +Function makes internal copy of the string, so it can be changed or freed immediately after this call. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( + VmaAllocator VMA_NOT_NULL allocator, + VmaPool VMA_NOT_NULL pool, + const char* VMA_NULLABLE pName); + +/** \brief General purpose memory allocation. + +\param allocator +\param pVkMemoryRequirements +\param pCreateInfo +\param[out] pAllocation Handle to allocated memory. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + +You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). + +It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(), +vmaCreateBuffer(), vmaCreateImage() instead whenever possible. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief General purpose memory allocation for multiple allocation objects at once. + +\param allocator Allocator object. +\param pVkMemoryRequirements Memory requirements for each allocation. +\param pCreateInfo Creation parameters for each allocation. +\param allocationCount Number of allocations to make. +\param[out] pAllocations Pointer to array that will be filled with handles to created allocations. +\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations. + +You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages(). + +Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. +It is just a general purpose allocation function able to make multiple allocations at once. +It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times. + +All allocations are made using same parameters. All of them are created out of the same memory pool and type. +If any allocation fails, all allocations already made within this function call are also freed, so that when +returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements, + const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo, + size_t allocationCount, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations, + VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo); + +/** \brief Allocates memory suitable for given `VkBuffer`. + +\param allocator +\param buffer +\param pCreateInfo +\param[out] pAllocation Handle to allocated memory. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + +It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory(). + +This is a special-purpose function. In most cases you should use vmaCreateBuffer(). + +You must free the allocation using vmaFreeMemory() when no longer needed. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief Allocates memory suitable for given `VkImage`. + +\param allocator +\param image +\param pCreateInfo +\param[out] pAllocation Handle to allocated memory. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + +It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory(). + +This is a special-purpose function. In most cases you should use vmaCreateImage(). + +You must free the allocation using vmaFreeMemory() when no longer needed. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage(). + +Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NULLABLE allocation); + +/** \brief Frees memory and destroys multiple allocations. + +Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding. +It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(), +vmaAllocateMemoryPages() and other functions. +It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times. + +Allocations in `pAllocations` array can come from any memory pools and types. +Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( + VmaAllocator VMA_NOT_NULL allocator, + size_t allocationCount, + const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations); + +/** \brief Returns current information about specified allocation. + +Current parameters of given allocation are returned in `pAllocationInfo`. + +Although this function doesn't lock any mutex, so it should be quite efficient, +you should avoid calling it too often. +You can retrieve same VmaAllocationInfo structure while creating your resource, from function +vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change +(e.g. due to defragmentation). + +There is also a new function vmaGetAllocationInfo2() that offers extended information +about the allocation, returned using new structure #VmaAllocationInfo2. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo); + +/** \brief Returns extended information about specified allocation. + +Current parameters of given allocation are returned in `pAllocationInfo`. +Extended parameters in structure #VmaAllocationInfo2 include memory block size +and a flag telling whether the allocation has dedicated memory. +It can be useful e.g. for interop with OpenGL. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VmaAllocationInfo2* VMA_NOT_NULL pAllocationInfo); + +/** \brief Sets pUserData in given allocation to new value. + +The value of pointer `pUserData` is copied to allocation's `pUserData`. +It is opaque, so you can use it however you want - e.g. +as a pointer, ordinal number or some handle to you own data. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE pUserData); + +/** \brief Sets pName in given allocation to new value. + +`pName` must be either null, or pointer to a null-terminated string. The function +makes local copy of the string and sets it as allocation's `pName`. String +passed as pName doesn't need to be valid for whole lifetime of the allocation - +you can free it after this call. String previously pointed by allocation's +`pName` is freed from memory. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const char* VMA_NULLABLE pName); + +/** +\brief Given an allocation, returns Property Flags of its memory type. + +This is just a convenience function. Same information can be obtained using +vmaGetAllocationInfo() + vmaGetMemoryProperties(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags); + + +#if VMA_EXTERNAL_MEMORY_WIN32 +/** +\brief Given an allocation, returns Win32 handle that may be imported by other processes or APIs. + +\param hTargetProcess Must be a valid handle to target process or null. If it's null, the function returns + handle for the current process. +\param[out] pHandle Output parameter that returns the handle. + +The function fills `pHandle` with handle that can be used in target process. +The handle is fetched using function `vkGetMemoryWin32HandleKHR`. +When no longer needed, you must close it using: + +\code +CloseHandle(handle); +\endcode + +You can close it any time, before or after destroying the allocation object. +It is reference-counted internally by Windows. + +Note the handle is returned for the entire `VkDeviceMemory` block that the allocation belongs to. +If the allocation is sub-allocated from a larger block, you may need to consider the offset of the allocation +(VmaAllocationInfo::offset). + +If the function fails with `VK_ERROR_FEATURE_NOT_PRESENT` error code, please double-check +that VmaVulkanFunctions::vkGetMemoryWin32HandleKHR function pointer is set, e.g. either by using `VMA_DYNAMIC_VULKAN_FUNCTIONS` +or by manually passing it through VmaAllocatorCreateInfo::pVulkanFunctions. + +For more information, see chapter \ref vk_khr_external_memory_win32. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle); +#endif // VMA_EXTERNAL_MEMORY_WIN32 + +/** \brief Maps memory represented by given allocation and returns pointer to it. + +Maps memory represented by given allocation to make it accessible to CPU code. +When succeeded, `*ppData` contains pointer to first byte of this memory. + +\warning +If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is +correctly offsetted to the beginning of region assigned to this particular allocation. +Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block. +You should not add VmaAllocationInfo::offset to it! + +Mapping is internally reference-counted and synchronized, so despite raw Vulkan +function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory` +multiple times simultaneously, it is safe to call this function on allocations +assigned to the same memory block. Actual Vulkan memory will be mapped on first +mapping and unmapped on last unmapping. + +If the function succeeded, you must call vmaUnmapMemory() to unmap the +allocation when mapping is no longer needed or before freeing the allocation, at +the latest. + +It also safe to call this function multiple times on the same allocation. You +must call vmaUnmapMemory() same number of times as you called vmaMapMemory(). + +It is also safe to call this function on allocation created with +#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time. +You must still call vmaUnmapMemory() same number of times as you called +vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the +"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag. + +This function fails when used on allocation made in memory type that is not +`HOST_VISIBLE`. + +This function doesn't automatically flush or invalidate caches. +If the allocation is made from a memory types that is not `HOST_COHERENT`, +you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + void* VMA_NULLABLE* VMA_NOT_NULL ppData); + +/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory(). + +For details, see description of vmaMapMemory(). + +This function doesn't automatically flush or invalidate caches. +If the allocation is made from a memory types that is not `HOST_COHERENT`, +you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation); + +/** \brief Flushes memory of given allocation. + +Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation. +It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`. +Unmap operation doesn't do that automatically. + +- `offset` must be relative to the beginning of allocation. +- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. +- `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. +- If `size` is 0, this call is ignored. +- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. + +Warning! `offset` and `size` are relative to the contents of given `allocation`. +If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. +Do not pass allocation's offset as `offset`!!! + +This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + +/** \brief Invalidates memory of given allocation. + +Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation. +It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`. +Map operation doesn't do that automatically. + +- `offset` must be relative to the beginning of allocation. +- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation. +- `offset` and `size` don't have to be aligned. + They are internally rounded down/up to multiply of `nonCoherentAtomSize`. +- If `size` is 0, this call is ignored. +- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`, + this call is ignored. + +Warning! `offset` and `size` are relative to the contents of given `allocation`. +If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively. +Do not pass allocation's offset as `offset`!!! + +This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if +it is called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize offset, + VkDeviceSize size); + +/** \brief Flushes memory of given set of allocations. + +Calls `vkFlushMappedMemoryRanges()` for memory associated with given ranges of given allocations. +For more information, see documentation of vmaFlushAllocation(). + +\param allocator +\param allocationCount +\param allocations +\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. +\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + +This function returns the `VkResult` from `vkFlushMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + +/** \brief Invalidates memory of given set of allocations. + +Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given ranges of given allocations. +For more information, see documentation of vmaInvalidateAllocation(). + +\param allocator +\param allocationCount +\param allocations +\param offsets If not null, it must point to an array of offsets of regions to flush, relative to the beginning of respective allocations. Null means all offsets are zero. +\param sizes If not null, it must point to an array of sizes of regions to flush in respective allocations. Null means `VK_WHOLE_SIZE` for all allocations. + +This function returns the `VkResult` from `vkInvalidateMappedMemoryRanges` if it is +called, otherwise `VK_SUCCESS`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t allocationCount, + const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets, + const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes); + +/** \brief Maps the allocation temporarily if needed, copies data from specified host pointer to it, and flushes the memory from the host caches if needed. + +\param allocator +\param pSrcHostPointer Pointer to the host data that become source of the copy. +\param dstAllocation Handle to the allocation that becomes destination of the copy. +\param dstAllocationLocalOffset Offset within `dstAllocation` where to write copied data, in bytes. +\param size Number of bytes to copy. + +This is a convenience function that allows to copy data from a host pointer to an allocation easily. +Same behavior can be achieved by calling vmaMapMemory(), `memcpy()`, vmaUnmapMemory(), vmaFlushAllocation(). + +This function can be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. +It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or +#VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. +Otherwise, the function will fail and generate a Validation Layers error. + +`dstAllocationLocalOffset` is relative to the contents of given `dstAllocation`. +If you mean whole allocation, you should pass 0. +Do not pass allocation's offset within device memory block this parameter! +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( + VmaAllocator VMA_NOT_NULL allocator, + const void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pSrcHostPointer, + VmaAllocation VMA_NOT_NULL dstAllocation, + VkDeviceSize dstAllocationLocalOffset, + VkDeviceSize size); + +/** \brief Invalidates memory in the host caches if needed, maps the allocation temporarily if needed, and copies data from it to a specified host pointer. + +\param allocator +\param srcAllocation Handle to the allocation that becomes source of the copy. +\param srcAllocationLocalOffset Offset within `srcAllocation` where to read copied data, in bytes. +\param pDstHostPointer Pointer to the host memory that become destination of the copy. +\param size Number of bytes to copy. + +This is a convenience function that allows to copy data from an allocation to a host pointer easily. +Same behavior can be achieved by calling vmaInvalidateAllocation(), vmaMapMemory(), `memcpy()`, vmaUnmapMemory(). + +This function should be called only for allocations created in a memory type that has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` +and `VK_MEMORY_PROPERTY_HOST_CACHED_BIT` flag. +It can be ensured e.g. by using #VMA_MEMORY_USAGE_AUTO and #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. +Otherwise, the function may fail and generate a Validation Layers error. +It may also work very slowly when reading from an uncached memory. + +`srcAllocationLocalOffset` is relative to the contents of given `srcAllocation`. +If you mean whole allocation, you should pass 0. +Do not pass allocation's offset within device memory block as this parameter! +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL srcAllocation, + VkDeviceSize srcAllocationLocalOffset, + void* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(size) pDstHostPointer, + VkDeviceSize size); + +/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. + +\param allocator +\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked. + +Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero, +`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are +`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection). + +Possible return values: + +- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types. +- `VK_SUCCESS` - corruption detection has been performed and succeeded. +- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations. + `VMA_ASSERT` is also fired in that case. +- Other value: Error returned by Vulkan, e.g. memory mapping failure. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( + VmaAllocator VMA_NOT_NULL allocator, + uint32_t memoryTypeBits); + +/** \brief Begins defragmentation process. + +\param allocator Allocator object. +\param pInfo Structure filled with parameters of defragmentation. +\param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation. +\returns +- `VK_SUCCESS` if defragmentation can begin. +- `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported. + +For more information about defragmentation, see documentation chapter: +[Defragmentation](@ref defragmentation). +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( + VmaAllocator VMA_NOT_NULL allocator, + const VmaDefragmentationInfo* VMA_NOT_NULL pInfo, + VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext); + +/** \brief Ends defragmentation process. + +\param allocator Allocator object. +\param context Context object that has been created by vmaBeginDefragmentation(). +\param[out] pStats Optional stats for the defragmentation. Can be null. + +Use this function to finish defragmentation started by vmaBeginDefragmentation(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationStats* VMA_NULLABLE pStats); + +/** \brief Starts single defragmentation pass. + +\param allocator Allocator object. +\param context Context object that has been created by vmaBeginDefragmentation(). +\param[out] pPassInfo Computed information for current pass. +\returns +- `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation. +- `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(), + and then preferably try another pass with vmaBeginDefragmentationPass(). +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); + +/** \brief Ends single defragmentation pass. + +\param allocator Allocator object. +\param context Context object that has been created by vmaBeginDefragmentation(). +\param pPassInfo Computed information for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you. + +Returns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible. + +Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`. +After this call: + +- Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY + (which is the default) will be pointing to the new destination place. +- Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY + will be freed. + +If no more moves are possible you can end whole defragmentation. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo); + +/** \brief Binds buffer to allocation. + +Binds specified buffer to region of memory represented by specified allocation. +Gets `VkDeviceMemory` handle and offset from the allocation. +If you want to create a buffer, allocate memory for it and bind them together separately, +you should use this function for binding instead of standard `vkBindBufferMemory()`, +because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple +allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously +(which is illegal in Vulkan). + +It is recommended to use function vmaCreateBuffer() instead of this one. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer); + +/** \brief Binds buffer to allocation with additional parameters. + +\param allocator +\param allocation +\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. +\param buffer +\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null. + +This function is similar to vmaBindBufferMemory(), but it provides additional parameters. + +If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag +or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer, + const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindBufferMemoryInfoKHR) pNext); + +/** \brief Binds image to allocation. + +Binds specified image to region of memory represented by specified allocation. +Gets `VkDeviceMemory` handle and offset from the allocation. +If you want to create an image, allocate memory for it and bind them together separately, +you should use this function for binding instead of standard `vkBindImageMemory()`, +because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple +allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously +(which is illegal in Vulkan). + +It is recommended to use function vmaCreateImage() instead of this one. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image); + +/** \brief Binds image to allocation with additional parameters. + +\param allocator +\param allocation +\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0. +\param image +\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null. + +This function is similar to vmaBindImageMemory(), but it provides additional parameters. + +If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag +or with VmaAllocatorCreateInfo::vulkanApiVersion `>= VK_API_VERSION_1_1`. Otherwise the call fails. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + VkImage VMA_NOT_NULL_NON_DISPATCHABLE image, + const void* VMA_NULLABLE VMA_EXTENDS_VK_STRUCT(VkBindImageMemoryInfoKHR) pNext); + +/** \brief Creates a new `VkBuffer`, allocates and binds memory for it. + +\param allocator +\param pBufferCreateInfo +\param pAllocationCreateInfo +\param[out] pBuffer Buffer that was created. +\param[out] pAllocation Allocation that was created. +\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo(). + +This function automatically: + +-# Creates buffer. +-# Allocates appropriate memory for it. +-# Binds the buffer with the memory. + +If any of these operations fail, buffer and allocation are not created, +returned value is negative error code, `*pBuffer` and `*pAllocation` are null. + +If the function succeeded, you must destroy both buffer and allocation when you +no longer need them using either convenience function vmaDestroyBuffer() or +separately, using `vkDestroyBuffer()` and vmaFreeMemory(). + +If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, +VK_KHR_dedicated_allocation extension is used internally to query driver whether +it requires or prefers the new buffer to have dedicated allocation. If yes, +and if dedicated allocation is possible +(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated +allocation for this buffer, just like when using +#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + +\note This function creates a new `VkBuffer`. Sub-allocation of parts of one large buffer, +although recommended as a good practice, is out of scope of this library and could be implemented +by the user as a higher-level logic on top of VMA. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief Creates a buffer with additional minimum alignment. + +Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom, +minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g. +for interop with OpenGL. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( + VmaAllocator VMA_NOT_NULL allocator, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkDeviceSize minAlignment, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/** \brief Creates a new `VkBuffer`, binds already created memory for it. + +\param allocator +\param allocation Allocation that provides memory to be used for binding new buffer to it. +\param pBufferCreateInfo +\param[out] pBuffer Buffer that was created. + +This function automatically: + +-# Creates buffer. +-# Binds the buffer with the supplied memory. + +If any of these operations fail, buffer is not created, +returned value is negative error code and `*pBuffer` is null. + +If the function succeeded, you must destroy the buffer when you +no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding +allocation you can use convenience function vmaDestroyBuffer(). + +\note There is a new version of this function augmented with parameter `allocationLocalOffset` - see vmaCreateAliasingBuffer2(). +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); + +/** \brief Creates a new `VkBuffer`, binds already created memory for it. + +\param allocator +\param allocation Allocation that provides memory to be used for binding new buffer to it. +\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the allocation. Normally it should be 0. +\param pBufferCreateInfo +\param[out] pBuffer Buffer that was created. + +This function automatically: + +-# Creates buffer. +-# Binds the buffer with the supplied memory. + +If any of these operations fail, buffer is not created, +returned value is negative error code and `*pBuffer` is null. + +If the function succeeded, you must destroy the buffer when you +no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding +allocation you can use convenience function vmaDestroyBuffer(). + +\note This is a new version of the function augmented with parameter `allocationLocalOffset`. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer); + +/** \brief Destroys Vulkan buffer and frees allocated memory. + +This is just a convenience function equivalent to: + +\code +vkDestroyBuffer(device, buffer, allocationCallbacks); +vmaFreeMemory(allocator, allocation); +\endcode + +It is safe to pass null as buffer and/or allocation. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE buffer, + VmaAllocation VMA_NULLABLE allocation); + +/// Function similar to vmaCreateBuffer(). +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( + VmaAllocator VMA_NOT_NULL allocator, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage, + VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation, + VmaAllocationInfo* VMA_NULLABLE pAllocationInfo); + +/// Function similar to vmaCreateAliasingBuffer() but for images. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); + +/// Function similar to vmaCreateAliasingBuffer2() but for images. +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage); + +/** \brief Destroys Vulkan image and frees allocated memory. + +This is just a convenience function equivalent to: + +\code +vkDestroyImage(device, image, allocationCallbacks); +vmaFreeMemory(allocator, allocation); +\endcode + +It is safe to pass null as image and/or allocation. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NULLABLE_NON_DISPATCHABLE image, + VmaAllocation VMA_NULLABLE allocation); + +/** @} */ + +/** +\addtogroup group_virtual +@{ +*/ + +/** \brief Creates new #VmaVirtualBlock object. + +\param pCreateInfo Parameters for creation. +\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( + const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock); + +/** \brief Destroys #VmaVirtualBlock object. + +Please note that you should consciously handle virtual allocations that could remain unfreed in the block. +You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock() +if you are sure this is what you want. If you do neither, an assert is called. + +If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`, +don't forget to free them. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock( + VmaVirtualBlock VMA_NULLABLE virtualBlock); + +/** \brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations. +*/ +VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + +/** \brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo); + +/** \brief Allocates new virtual allocation inside given #VmaVirtualBlock. + +If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned +(despite the function doesn't ever allocate actual GPU memory). +`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`. + +\param virtualBlock Virtual block +\param pCreateInfo Parameters for the allocation +\param[out] pAllocation Returned handle of the new allocation +\param[out] pOffset Returned offset of the new allocation. Optional, can be null. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation, + VkDeviceSize* VMA_NULLABLE pOffset); + +/** \brief Frees virtual allocation inside given #VmaVirtualBlock. + +It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation); + +/** \brief Frees all virtual allocations inside given #VmaVirtualBlock. + +You must either call this function or free each virtual allocation individually with vmaVirtualFree() +before destroying a virtual block. Otherwise, an assert is called. + +If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`, +don't forget to free it as well. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock( + VmaVirtualBlock VMA_NOT_NULL virtualBlock); + +/** \brief Changes custom pointer associated with given virtual allocation. +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, + void* VMA_NULLABLE pUserData); + +/** \brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock. + +This function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaStatistics* VMA_NOT_NULL pStats); + +/** \brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock. + +This function is slow to call. Use for debugging purposes. +For less detailed statistics, see vmaGetVirtualBlockStatistics(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaDetailedStatistics* VMA_NOT_NULL pStats); + +/** @} */ + +#if VMA_STATS_STRING_ENABLED +/** +\addtogroup group_stats +@{ +*/ + +/** \brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock. +\param virtualBlock Virtual block. +\param[out] ppStatsString Returned string. +\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStatistics(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces. + +Returned string must be freed using vmaFreeVirtualBlockStatsString(). +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); + +/// Frees a string returned by vmaBuildVirtualBlockStatsString(). +VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString( + VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE pStatsString); + +/** \brief Builds and returns statistics as a null-terminated string in JSON format. +\param allocator +\param[out] ppStatsString Must be freed using vmaFreeStatsString() function. +\param detailedMap +*/ +VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString, + VkBool32 detailedMap); + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( + VmaAllocator VMA_NOT_NULL allocator, + char* VMA_NULLABLE pStatsString); + +/** @} */ + +#endif // VMA_STATS_STRING_ENABLED + +#endif // _VMA_FUNCTION_HEADERS + +#ifdef __cplusplus +} +#endif + +#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION +// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// For Visual Studio IntelliSense. +#if defined(__cplusplus) && defined(__INTELLISENSE__) +#define VMA_IMPLEMENTATION +#endif + +#ifdef VMA_IMPLEMENTATION +#undef VMA_IMPLEMENTATION + +#include +#include +#include +#include +#include +#include + +#if !defined(VMA_CPP20) + #if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20 + #define VMA_CPP20 1 + #else + #define VMA_CPP20 0 + #endif +#endif + +#ifdef _MSC_VER + #include // For functions like __popcnt, _BitScanForward etc. +#endif +#if VMA_CPP20 + #include +#endif + +#if VMA_STATS_STRING_ENABLED + #include // For snprintf +#endif + +/******************************************************************************* +CONFIGURATION SECTION + +Define some of these macros before each #include of this header or change them +here if you need other then default behavior depending on your environment. +*/ +#ifndef _VMA_CONFIGURATION + +/* +Define this macro to 1 to make the library fetch pointers to Vulkan functions +internally, like: + + vulkanFunctions.vkAllocateMemory = &vkAllocateMemory; +*/ +#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES) + #define VMA_STATIC_VULKAN_FUNCTIONS 1 +#endif + +/* +Define this macro to 1 to make the library fetch pointers to Vulkan functions +internally, like: + + vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(device, "vkAllocateMemory"); + +To use this feature in new versions of VMA you now have to pass +VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as +VmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null. +*/ +#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS) + #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 +#endif + +#ifndef VMA_USE_STL_SHARED_MUTEX + #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 + #define VMA_USE_STL_SHARED_MUTEX 1 + // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus + // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2. + #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L + #define VMA_USE_STL_SHARED_MUTEX 1 + #else + #define VMA_USE_STL_SHARED_MUTEX 0 + #endif +#endif + +/* +Define this macro to include custom header files without having to edit this file directly, e.g.: + + // Inside of "my_vma_configuration_user_includes.h": + + #include "my_custom_assert.h" // for MY_CUSTOM_ASSERT + #include "my_custom_min.h" // for my_custom_min + #include + #include + + // Inside a different file, which includes "vk_mem_alloc.h": + + #define VMA_CONFIGURATION_USER_INCLUDES_H "my_vma_configuration_user_includes.h" + #define VMA_ASSERT(expr) MY_CUSTOM_ASSERT(expr) + #define VMA_MIN(v1, v2) (my_custom_min(v1, v2)) + #include "vk_mem_alloc.h" + ... + +The following headers are used in this CONFIGURATION section only, so feel free to +remove them if not needed. +*/ +#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H) + #include // for assert + #include // for min, max, swap + #include +#else + #include VMA_CONFIGURATION_USER_INCLUDES_H +#endif + +#ifndef VMA_NULL + // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0. + #define VMA_NULL nullptr +#endif + +#ifndef VMA_FALLTHROUGH + #if __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 + #define VMA_FALLTHROUGH [[fallthrough]] + #else + #define VMA_FALLTHROUGH + #endif +#endif + +// Normal assert to check for programmer's errors, especially in Debug configuration. +#ifndef VMA_ASSERT + #ifdef NDEBUG + #define VMA_ASSERT(expr) + #else + #define VMA_ASSERT(expr) assert(expr) + #endif +#endif + +// Assert that will be called very often, like inside data structures e.g. operator[]. +// Making it non-empty can make program slow. +#ifndef VMA_HEAVY_ASSERT + #ifdef NDEBUG + #define VMA_HEAVY_ASSERT(expr) + #else + #define VMA_HEAVY_ASSERT(expr) //VMA_ASSERT(expr) + #endif +#endif + +// Assert used for reporting memory leaks - unfreed allocations. +#ifndef VMA_ASSERT_LEAK + #define VMA_ASSERT_LEAK(expr) VMA_ASSERT(expr) +#endif + +// If your compiler is not compatible with C++17 and definition of +// aligned_alloc() function is missing, uncommenting following line may help: + +//#include + +#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16) +#include +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + // alignment must be >= sizeof(void*) + if(alignment < sizeof(void*)) + { + alignment = sizeof(void*); + } + + return memalign(alignment, size); +} +#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) && defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)) +#include + +#if defined(__APPLE__) +#include +#endif + +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + // Unfortunately, aligned_alloc causes VMA to crash due to it returning null pointers. (At least under 11.4) + // Therefore, for now disable this specific exception until a proper solution is found. + //#if defined(__APPLE__) && (defined(MAC_OS_X_VERSION_10_16) || defined(__IPHONE_14_0)) + //#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_16 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + // // For C++14, usr/include/malloc/_malloc.h declares aligned_alloc()) only + // // with the MacOSX11.0 SDK in Xcode 12 (which is what adds + // // MAC_OS_X_VERSION_10_16), even though the function is marked + // // available for 10.15. That is why the preprocessor checks for 10.16 but + // // the __builtin_available checks for 10.15. + // // People who use C++17 could call aligned_alloc with the 10.15 SDK already. + // if (__builtin_available(macOS 10.15, iOS 13, *)) + // return aligned_alloc(alignment, size); + //#endif + //#endif + + // alignment must be >= sizeof(void*) + if(alignment < sizeof(void*)) + { + alignment = sizeof(void*); + } + + void *pointer; + if(posix_memalign(&pointer, alignment, size) == 0) + return pointer; + return VMA_NULL; +} +#elif defined(_WIN32) +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + return _aligned_malloc(size, alignment); +} +#elif __cplusplus >= 201703L || _MSVC_LANG >= 201703L // C++17 +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + return aligned_alloc(alignment, size); +} +#else +static void* vma_aligned_alloc(size_t alignment, size_t size) +{ + VMA_ASSERT(0 && "Could not implement aligned_alloc automatically. Please enable C++17 or later in your compiler or provide custom implementation of macro VMA_SYSTEM_ALIGNED_MALLOC (and VMA_SYSTEM_ALIGNED_FREE if needed) using the API of your system."); + return VMA_NULL; +} +#endif + +#if defined(_WIN32) +static void vma_aligned_free(void* ptr) +{ + _aligned_free(ptr); +} +#else +static void vma_aligned_free(void* VMA_NULLABLE ptr) +{ + free(ptr); +} +#endif + +#ifndef VMA_ALIGN_OF + #define VMA_ALIGN_OF(type) (alignof(type)) +#endif + +#ifndef VMA_SYSTEM_ALIGNED_MALLOC + #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment) vma_aligned_alloc((alignment), (size)) +#endif + +#ifndef VMA_SYSTEM_ALIGNED_FREE + // VMA_SYSTEM_FREE is the old name, but might have been defined by the user + #if defined(VMA_SYSTEM_FREE) + #define VMA_SYSTEM_ALIGNED_FREE(ptr) VMA_SYSTEM_FREE(ptr) + #else + #define VMA_SYSTEM_ALIGNED_FREE(ptr) vma_aligned_free(ptr) + #endif +#endif + +#ifndef VMA_COUNT_BITS_SET + // Returns number of bits set to 1 in (v) + #define VMA_COUNT_BITS_SET(v) VmaCountBitsSet(v) +#endif + +#ifndef VMA_BITSCAN_LSB + // Scans integer for index of first nonzero value from the Least Significant Bit (LSB). If mask is 0 then returns UINT8_MAX + #define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask) +#endif + +#ifndef VMA_BITSCAN_MSB + // Scans integer for index of first nonzero value from the Most Significant Bit (MSB). If mask is 0 then returns UINT8_MAX + #define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask) +#endif + +#ifndef VMA_MIN + #define VMA_MIN(v1, v2) ((std::min)((v1), (v2))) +#endif + +#ifndef VMA_MAX + #define VMA_MAX(v1, v2) ((std::max)((v1), (v2))) +#endif + +#ifndef VMA_SORT + #define VMA_SORT(beg, end, cmp) std::sort(beg, end, cmp) +#endif + +#ifndef VMA_DEBUG_LOG_FORMAT + #define VMA_DEBUG_LOG_FORMAT(format, ...) + /* + #define VMA_DEBUG_LOG_FORMAT(format, ...) do { \ + printf((format), __VA_ARGS__); \ + printf("\n"); \ + } while(false) + */ +#endif + +#ifndef VMA_DEBUG_LOG + #define VMA_DEBUG_LOG(str) VMA_DEBUG_LOG_FORMAT("%s", (str)) +#endif + +#ifndef VMA_LEAK_LOG_FORMAT + #define VMA_LEAK_LOG_FORMAT(format, ...) VMA_DEBUG_LOG_FORMAT(format, __VA_ARGS__) +#endif + +#ifndef VMA_CLASS_NO_COPY + #define VMA_CLASS_NO_COPY(className) \ + private: \ + className(const className&) = delete; \ + className& operator=(const className&) = delete; +#endif +#ifndef VMA_CLASS_NO_COPY_NO_MOVE + #define VMA_CLASS_NO_COPY_NO_MOVE(className) \ + private: \ + className(const className&) = delete; \ + className(className&&) = delete; \ + className& operator=(const className&) = delete; \ + className& operator=(className&&) = delete; +#endif + +// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString. +#if VMA_STATS_STRING_ENABLED + static inline void VmaUint32ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint32_t num) + { + snprintf(outStr, strLen, "%" PRIu32, num); + } + static inline void VmaUint64ToStr(char* VMA_NOT_NULL outStr, size_t strLen, uint64_t num) + { + snprintf(outStr, strLen, "%" PRIu64, num); + } + static inline void VmaPtrToStr(char* VMA_NOT_NULL outStr, size_t strLen, const void* ptr) + { + snprintf(outStr, strLen, "%p", ptr); + } +#endif + +#ifndef VMA_MUTEX + class VmaMutex + { + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutex) + public: + VmaMutex() = default; + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } + bool TryLock() { return m_Mutex.try_lock(); } + private: + std::mutex m_Mutex; + }; + #define VMA_MUTEX VmaMutex +#endif + +// Read-write mutex, where "read" is shared access, "write" is exclusive access. +#ifndef VMA_RW_MUTEX + #if VMA_USE_STL_SHARED_MUTEX + // Use std::shared_mutex from C++17. + #include + class VmaRWMutex + { + public: + void LockRead() { m_Mutex.lock_shared(); } + void UnlockRead() { m_Mutex.unlock_shared(); } + bool TryLockRead() { return m_Mutex.try_lock_shared(); } + void LockWrite() { m_Mutex.lock(); } + void UnlockWrite() { m_Mutex.unlock(); } + bool TryLockWrite() { return m_Mutex.try_lock(); } + private: + std::shared_mutex m_Mutex; + }; + #define VMA_RW_MUTEX VmaRWMutex + #elif defined(_WIN32) && defined(WINVER) && defined(SRWLOCK_INIT) && WINVER >= 0x0600 + // Use SRWLOCK from WinAPI. + // Minimum supported client = Windows Vista, server = Windows Server 2008. + class VmaRWMutex + { + public: + VmaRWMutex() { InitializeSRWLock(&m_Lock); } + void LockRead() { AcquireSRWLockShared(&m_Lock); } + void UnlockRead() { ReleaseSRWLockShared(&m_Lock); } + bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; } + void LockWrite() { AcquireSRWLockExclusive(&m_Lock); } + void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); } + bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; } + private: + SRWLOCK m_Lock; + }; + #define VMA_RW_MUTEX VmaRWMutex + #else + // Less efficient fallback: Use normal mutex. + class VmaRWMutex + { + public: + void LockRead() { m_Mutex.Lock(); } + void UnlockRead() { m_Mutex.Unlock(); } + bool TryLockRead() { return m_Mutex.TryLock(); } + void LockWrite() { m_Mutex.Lock(); } + void UnlockWrite() { m_Mutex.Unlock(); } + bool TryLockWrite() { return m_Mutex.TryLock(); } + private: + VMA_MUTEX m_Mutex; + }; + #define VMA_RW_MUTEX VmaRWMutex + #endif // #if VMA_USE_STL_SHARED_MUTEX +#endif // #ifndef VMA_RW_MUTEX + +/* +If providing your own implementation, you need to implement a subset of std::atomic. +*/ +#ifndef VMA_ATOMIC_UINT32 + #include + #define VMA_ATOMIC_UINT32 std::atomic +#endif + +#ifndef VMA_ATOMIC_UINT64 + #include + #define VMA_ATOMIC_UINT64 std::atomic +#endif + +#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY + /** + Every allocation will have its own memory block. + Define to 1 for debugging purposes only. + */ + #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0) +#endif + +#ifndef VMA_MIN_ALIGNMENT + /** + Minimum alignment of all allocations, in bytes. + Set to more than 1 for debugging purposes. Must be power of two. + */ + #ifdef VMA_DEBUG_ALIGNMENT // Old name + #define VMA_MIN_ALIGNMENT VMA_DEBUG_ALIGNMENT + #else + #define VMA_MIN_ALIGNMENT (1) + #endif +#endif + +#ifndef VMA_DEBUG_MARGIN + /** + Minimum margin after every allocation, in bytes. + Set nonzero for debugging purposes only. + */ + #define VMA_DEBUG_MARGIN (0) +#endif + +#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS + /** + Define this macro to 1 to automatically fill new allocations and destroyed + allocations with some bit pattern. + */ + #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0) +#endif + +#ifndef VMA_DEBUG_DETECT_CORRUPTION + /** + Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to + enable writing magic value to the margin after every allocation and + validating it, so that memory corruptions (out-of-bounds writes) are detected. + */ + #define VMA_DEBUG_DETECT_CORRUPTION (0) +#endif + +#ifndef VMA_DEBUG_GLOBAL_MUTEX + /** + Set this to 1 for debugging purposes only, to enable single mutex protecting all + entry calls to the library. Can be useful for debugging multithreading issues. + */ + #define VMA_DEBUG_GLOBAL_MUTEX (0) +#endif + +#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY + /** + Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity. + Set to more than 1 for debugging purposes only. Must be power of two. + */ + #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1) +#endif + +#ifndef VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT + /* + Set this to 1 to make VMA never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount + and return error instead of leaving up to Vulkan implementation what to do in such cases. + */ + #define VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT (1) +#endif + +#ifndef VMA_DEBUG_DONT_EXCEED_HEAP_SIZE_WITH_ALLOCATION_SIZE + /* + Set this to 1 to make VMA never exceed VkPhysicalDeviceMemoryProperties::memoryHeaps[i].size + with a single allocation size VkMemoryAllocateInfo::allocationSize + and return error instead of leaving up to Vulkan implementation what to do in such cases. + It protects agaist validation error VUID-vkAllocateMemory-pAllocateInfo-01713. + On the other hand, allowing exceeding this size may result in a successful allocation despite the validation error. + */ + #define VMA_DEBUG_DONT_EXCEED_HEAP_SIZE_WITH_ALLOCATION_SIZE (1) +#endif + +#ifndef VMA_SMALL_HEAP_MAX_SIZE + /// Maximum size of a memory heap in Vulkan to consider it "small". + #define VMA_SMALL_HEAP_MAX_SIZE (1024ULL * 1024 * 1024) +#endif + +#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE + /// Default size of a block allocated as single VkDeviceMemory from a "large" heap. + #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ULL * 1024 * 1024) +#endif + +/* +Mapping hysteresis is a logic that launches when vmaMapMemory/vmaUnmapMemory is called +or a persistently mapped allocation is created and destroyed several times in a row. +It keeps additional +1 mapping of a device memory block to prevent calling actual +vkMapMemory/vkUnmapMemory too many times, which may improve performance and help +tools like RenderDoc. +*/ +#ifndef VMA_MAPPING_HYSTERESIS_ENABLED + #define VMA_MAPPING_HYSTERESIS_ENABLED 1 +#endif + +#define VMA_VALIDATE(cond) do { if(!(cond)) { \ + VMA_ASSERT(0 && "Validation failed: " #cond); \ + return false; \ + } } while(false) + +/******************************************************************************* +END OF CONFIGURATION +*/ +#endif // _VMA_CONFIGURATION + + +static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC; +static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF; +// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F. +static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666; + +// Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants. +static const uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040; +static const uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080; +static const uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000; +static const uint32_t VK_IMAGE_CREATE_DISJOINT_BIT_COPY = 0x00000200; +static const int32_t VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY = 1000158000; +static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000U; +static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32; +static const uint32_t VMA_VENDOR_ID_AMD = 4098; + +// This one is tricky. Vulkan specification defines this code as available since +// Vulkan 1.0, but doesn't actually define it in Vulkan SDK earlier than 1.2.131. +// See pull request #207. +#define VK_ERROR_UNKNOWN_COPY ((VkResult)-13) + + +#if VMA_STATS_STRING_ENABLED +// Correspond to values of enum VmaSuballocationType. +static const char* const VMA_SUBALLOCATION_TYPE_NAMES[] = +{ + "FREE", + "UNKNOWN", + "BUFFER", + "IMAGE_UNKNOWN", + "IMAGE_LINEAR", + "IMAGE_OPTIMAL", +}; +#endif + +static const VkAllocationCallbacks VmaEmptyAllocationCallbacks = + { VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL }; + + +#ifndef _VMA_ENUM_DECLARATIONS + +enum VmaSuballocationType +{ + VMA_SUBALLOCATION_TYPE_FREE = 0, + VMA_SUBALLOCATION_TYPE_UNKNOWN = 1, + VMA_SUBALLOCATION_TYPE_BUFFER = 2, + VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3, + VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4, + VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5, + VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF +}; + +enum VMA_CACHE_OPERATION +{ + VMA_CACHE_FLUSH, + VMA_CACHE_INVALIDATE +}; + +enum class VmaAllocationRequestType +{ + Normal, + TLSF, + // Used by "Linear" algorithm. + UpperAddress, + EndOf1st, + EndOf2nd, +}; + +#endif // _VMA_ENUM_DECLARATIONS + +#ifndef _VMA_FORWARD_DECLARATIONS +// Opaque handle used by allocation algorithms to identify single allocation in any conforming way. +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaAllocHandle); + +struct VmaMutexLock; +struct VmaMutexLockRead; +struct VmaMutexLockWrite; + +template +struct AtomicTransactionalIncrement; + +template +struct VmaStlAllocator; + +template +class VmaVector; + +template +class VmaSmallVector; + +template +class VmaPoolAllocator; + +template +struct VmaListItem; + +template +class VmaRawList; + +template +class VmaList; + +template +class VmaIntrusiveLinkedList; + +#if VMA_STATS_STRING_ENABLED +class VmaStringBuilder; +class VmaJsonWriter; +#endif + +class VmaDeviceMemoryBlock; + +struct VmaDedicatedAllocationListItemTraits; +class VmaDedicatedAllocationList; + +struct VmaSuballocation; +struct VmaSuballocationOffsetLess; +struct VmaSuballocationOffsetGreater; +struct VmaSuballocationItemSizeLess; + +typedef VmaList> VmaSuballocationList; + +struct VmaAllocationRequest; + +class VmaBlockMetadata; +class VmaBlockMetadata_Linear; +class VmaBlockMetadata_TLSF; + +class VmaBlockVector; + +struct VmaPoolListItemTraits; + +struct VmaCurrentBudgetData; + +class VmaAllocationObjectAllocator; + +#endif // _VMA_FORWARD_DECLARATIONS + + +#ifndef _VMA_FUNCTIONS + +/* +Returns number of bits set to 1 in (v). + +On specific platforms and compilers you can use intrinsics like: + +Visual Studio: + return __popcnt(v); +GCC, Clang: + return static_cast(__builtin_popcount(v)); + +Define macro VMA_COUNT_BITS_SET to provide your optimized implementation. +But you need to check in runtime whether user's CPU supports these, as some old processors don't. +*/ +static inline uint32_t VmaCountBitsSet(uint32_t v) +{ +#if VMA_CPP20 + return std::popcount(v); +#else + uint32_t c = v - ((v >> 1) & 0x55555555); + c = ((c >> 2) & 0x33333333) + (c & 0x33333333); + c = ((c >> 4) + c) & 0x0F0F0F0F; + c = ((c >> 8) + c) & 0x00FF00FF; + c = ((c >> 16) + c) & 0x0000FFFF; + return c; +#endif +} + +static inline uint8_t VmaBitScanLSB(uint64_t mask) +{ +#if defined(_MSC_VER) && defined(_WIN64) + unsigned long pos; + if (_BitScanForward64(&pos, mask)) + return static_cast(pos); + return UINT8_MAX; +#elif VMA_CPP20 + if(mask != 0) + return static_cast(std::countr_zero(mask)); + return UINT8_MAX; +#elif defined __GNUC__ || defined __clang__ + return static_cast(__builtin_ffsll(mask)) - 1U; +#else + uint8_t pos = 0; + uint64_t bit = 1; + do + { + if (mask & bit) + return pos; + bit <<= 1; + } while (pos++ < 63); + return UINT8_MAX; +#endif +} + +static inline uint8_t VmaBitScanLSB(uint32_t mask) +{ +#ifdef _MSC_VER + unsigned long pos; + if (_BitScanForward(&pos, mask)) + return static_cast(pos); + return UINT8_MAX; +#elif VMA_CPP20 + if(mask != 0) + return static_cast(std::countr_zero(mask)); + return UINT8_MAX; +#elif defined __GNUC__ || defined __clang__ + return static_cast(__builtin_ffs(mask)) - 1U; +#else + uint8_t pos = 0; + uint32_t bit = 1; + do + { + if (mask & bit) + return pos; + bit <<= 1; + } while (pos++ < 31); + return UINT8_MAX; +#endif +} + +static inline uint8_t VmaBitScanMSB(uint64_t mask) +{ +#if defined(_MSC_VER) && defined(_WIN64) + unsigned long pos; + if (_BitScanReverse64(&pos, mask)) + return static_cast(pos); +#elif VMA_CPP20 + if(mask != 0) + return 63 - static_cast(std::countl_zero(mask)); +#elif defined __GNUC__ || defined __clang__ + if (mask != 0) + return 63 - static_cast(__builtin_clzll(mask)); +#else + uint8_t pos = 63; + uint64_t bit = 1ULL << 63; + do + { + if (mask & bit) + return pos; + bit >>= 1; + } while (pos-- > 0); +#endif + return UINT8_MAX; +} + +static inline uint8_t VmaBitScanMSB(uint32_t mask) +{ +#ifdef _MSC_VER + unsigned long pos; + if (_BitScanReverse(&pos, mask)) + return static_cast(pos); +#elif VMA_CPP20 + if(mask != 0) + return 31 - static_cast(std::countl_zero(mask)); +#elif defined __GNUC__ || defined __clang__ + if (mask != 0) + return 31 - static_cast(__builtin_clz(mask)); +#else + uint8_t pos = 31; + uint32_t bit = 1UL << 31; + do + { + if (mask & bit) + return pos; + bit >>= 1; + } while (pos-- > 0); +#endif + return UINT8_MAX; +} + +/* +Returns true if given number is a power of two. +T must be unsigned integer number or signed integer but always nonnegative. +For 0 returns true. +*/ +template +inline bool VmaIsPow2(T x) +{ + return (x & (x - 1)) == 0; +} + +// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16. +// Use types like uint32_t, uint64_t as T. +template +static inline T VmaAlignUp(T val, T alignment) +{ + VMA_HEAVY_ASSERT(VmaIsPow2(alignment)); + return (val + alignment - 1) & ~(alignment - 1); +} + +// Aligns given value down to nearest multiply of align value. For example: VmaAlignDown(11, 8) = 8. +// Use types like uint32_t, uint64_t as T. +template +static inline T VmaAlignDown(T val, T alignment) +{ + VMA_HEAVY_ASSERT(VmaIsPow2(alignment)); + return val & ~(alignment - 1); +} + +// Division with mathematical rounding to nearest number. +template +static inline T VmaRoundDiv(T x, T y) +{ + return (x + (y / (T)2)) / y; +} + +// Divide by 'y' and round up to nearest integer. +template +static inline T VmaDivideRoundingUp(T x, T y) +{ + return (x + y - (T)1) / y; +} + +// Returns smallest power of 2 greater or equal to v. +static inline uint32_t VmaNextPow2(uint32_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +static inline uint64_t VmaNextPow2(uint64_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v++; + return v; +} + +// Returns largest power of 2 less or equal to v. +static inline uint32_t VmaPrevPow2(uint32_t v) +{ + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v = v ^ (v >> 1); + return v; +} + +static inline uint64_t VmaPrevPow2(uint64_t v) +{ + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v = v ^ (v >> 1); + return v; +} + +static inline bool VmaStrIsEmpty(const char* pStr) +{ + return pStr == VMA_NULL || *pStr == '\0'; +} + +/* +Returns true if two memory blocks occupy overlapping pages. +ResourceA must be in less memory offset than ResourceB. + +Algorithm is based on "Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)" +chapter 11.6 "Resource Memory Association", paragraph "Buffer-Image Granularity". +*/ +static inline bool VmaBlocksOnSamePage( + VkDeviceSize resourceAOffset, + VkDeviceSize resourceASize, + VkDeviceSize resourceBOffset, + VkDeviceSize pageSize) +{ + VMA_ASSERT(resourceAOffset + resourceASize <= resourceBOffset && resourceASize > 0 && pageSize > 0); + VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1; + VkDeviceSize resourceAEndPage = resourceAEnd & ~(pageSize - 1); + VkDeviceSize resourceBStart = resourceBOffset; + VkDeviceSize resourceBStartPage = resourceBStart & ~(pageSize - 1); + return resourceAEndPage == resourceBStartPage; +} + +/* +Returns true if given suballocation types could conflict and must respect +VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer +or linear image and another one is optimal image. If type is unknown, behave +conservatively. +*/ +static inline bool VmaIsBufferImageGranularityConflict( + VmaSuballocationType suballocType1, + VmaSuballocationType suballocType2) +{ + if (suballocType1 > suballocType2) + { + std::swap(suballocType1, suballocType2); + } + + switch (suballocType1) + { + case VMA_SUBALLOCATION_TYPE_FREE: + return false; + case VMA_SUBALLOCATION_TYPE_UNKNOWN: + return true; + case VMA_SUBALLOCATION_TYPE_BUFFER: + return + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN || + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL; + case VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN: + return + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN || + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR || + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL; + case VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR: + return + suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL; + case VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL: + return false; + default: + VMA_ASSERT(0); + return true; + } +} + +static void VmaWriteMagicValue(void* pData, VkDeviceSize offset) +{ +#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION + uint32_t* pDst = (uint32_t*)((char*)pData + offset); + const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t); + for (size_t i = 0; i < numberCount; ++i, ++pDst) + { + *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE; + } +#else + // no-op +#endif +} + +static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset) +{ +#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION + const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset); + const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t); + for (size_t i = 0; i < numberCount; ++i, ++pSrc) + { + if (*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE) + { + return false; + } + } +#endif + return true; +} + +/* +Fills structure with parameters of an example buffer to be used for transfers +during GPU memory defragmentation. +*/ +static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo) +{ + memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo)); + outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size. +} + + +/* +Performs binary search and returns iterator to first element that is greater or +equal to (key), according to comparison (cmp). + +Cmp should return true if first argument is less than second argument. + +Returned value is the found element, if present in the collection or place where +new element with value (key) should be inserted. +*/ +template +static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp) +{ + size_t down = 0; + size_t up = size_t(end - beg); + while (down < up) + { + const size_t mid = down + (up - down) / 2; // Overflow-safe midpoint calculation + if (cmp(*(beg + mid), key)) + { + down = mid + 1; + } + else + { + up = mid; + } + } + return beg + down; +} + +template +IterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value, const CmpLess& cmp) +{ + IterT it = VmaBinaryFindFirstNotLess( + beg, end, value, cmp); + if (it == end || + (!cmp(*it, value) && !cmp(value, *it))) + { + return it; + } + return end; +} + +/* +Returns true if all pointers in the array are not-null and unique. +Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT. +T must be pointer type, e.g. VmaAllocation, VmaPool. +*/ +template +static bool VmaValidatePointerArray(uint32_t count, const T* arr) +{ + for (uint32_t i = 0; i < count; ++i) + { + const T iPtr = arr[i]; + if (iPtr == VMA_NULL) + { + return false; + } + for (uint32_t j = i + 1; j < count; ++j) + { + if (iPtr == arr[j]) + { + return false; + } + } + } + return true; +} + +template +static inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct) +{ + newStruct->pNext = mainStruct->pNext; + mainStruct->pNext = newStruct; +} +// Finds structure with s->sType == sType in mainStruct->pNext chain. +// Returns pointer to it. If not found, returns null. +template +static inline const FindT* VmaPnextChainFind(const MainT* mainStruct, VkStructureType sType) +{ + for(const VkBaseInStructure* s = (const VkBaseInStructure*)mainStruct->pNext; + s != VMA_NULL; s = s->pNext) + { + if(s->sType == sType) + { + return (const FindT*)s; + } + } + return VMA_NULL; +} + +// An abstraction over buffer or image `usage` flags, depending on available extensions. +struct VmaBufferImageUsage +{ +#if VMA_KHR_MAINTENANCE5 + typedef uint64_t BaseType; // VkFlags64 +#else + typedef uint32_t BaseType; // VkFlags32 +#endif + + static const VmaBufferImageUsage UNKNOWN; + + BaseType Value; + + VmaBufferImageUsage() { *this = UNKNOWN; } + explicit VmaBufferImageUsage(BaseType usage) : Value(usage) { } + VmaBufferImageUsage(const VkBufferCreateInfo &createInfo, bool useKhrMaintenance5); + explicit VmaBufferImageUsage(const VkImageCreateInfo &createInfo); + + bool operator==(const VmaBufferImageUsage& rhs) const { return Value == rhs.Value; } + bool operator!=(const VmaBufferImageUsage& rhs) const { return Value != rhs.Value; } + + bool Contains(BaseType flag) const { return (Value & flag) != 0; } + bool ContainsDeviceAccess() const + { + // This relies on values of VK_IMAGE_USAGE_TRANSFER* being the same as VK_BUFFER_IMAGE_TRANSFER*. + return (Value & ~BaseType(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) != 0; + } +}; + +const VmaBufferImageUsage VmaBufferImageUsage::UNKNOWN = VmaBufferImageUsage(0); + +VmaBufferImageUsage::VmaBufferImageUsage(const VkBufferCreateInfo &createInfo, + bool useKhrMaintenance5) +{ +#if VMA_KHR_MAINTENANCE5 + if(useKhrMaintenance5) + { + // If VkBufferCreateInfo::pNext chain contains VkBufferUsageFlags2CreateInfoKHR, + // take usage from it and ignore VkBufferCreateInfo::usage, per specification + // of the VK_KHR_maintenance5 extension. + const VkBufferUsageFlags2CreateInfoKHR* const usageFlags2 = + VmaPnextChainFind(&createInfo, VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR); + if(usageFlags2 != VMA_NULL) + { + this->Value = usageFlags2->usage; + return; + } + } +#endif + + this->Value = (BaseType)createInfo.usage; +} + +VmaBufferImageUsage::VmaBufferImageUsage(const VkImageCreateInfo &createInfo) + : Value((BaseType)createInfo.usage) +{ + // Maybe in the future there will be VK_KHR_maintenanceN extension with structure + // VkImageUsageFlags2CreateInfoKHR, like the one for buffers... +} + +// This is the main algorithm that guides the selection of a memory type best for an allocation - +// converts usage to required/preferred/not preferred flags. +static bool FindMemoryPreferences( + bool isIntegratedGPU, + const VmaAllocationCreateInfo& allocCreateInfo, + VmaBufferImageUsage bufImgUsage, + VkMemoryPropertyFlags& outRequiredFlags, + VkMemoryPropertyFlags& outPreferredFlags, + VkMemoryPropertyFlags& outNotPreferredFlags) +{ + outRequiredFlags = allocCreateInfo.requiredFlags; + outPreferredFlags = allocCreateInfo.preferredFlags; + outNotPreferredFlags = 0; + + switch(allocCreateInfo.usage) + { + case VMA_MEMORY_USAGE_UNKNOWN: + break; + case VMA_MEMORY_USAGE_GPU_ONLY: + if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + break; + case VMA_MEMORY_USAGE_CPU_ONLY: + outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + break; + case VMA_MEMORY_USAGE_CPU_TO_GPU: + outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + break; + case VMA_MEMORY_USAGE_GPU_TO_CPU: + outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + outPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + break; + case VMA_MEMORY_USAGE_CPU_COPY: + outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED: + outRequiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; + break; + case VMA_MEMORY_USAGE_AUTO: + case VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE: + case VMA_MEMORY_USAGE_AUTO_PREFER_HOST: + { + if(bufImgUsage == VmaBufferImageUsage::UNKNOWN) + { + VMA_ASSERT(0 && "VMA_MEMORY_USAGE_AUTO* values can only be used with functions like vmaCreateBuffer, vmaCreateImage so that the details of the created resource are known." + " Maybe you use VkBufferUsageFlags2CreateInfoKHR but forgot to use VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT?" ); + return false; + } + + const bool deviceAccess = bufImgUsage.ContainsDeviceAccess(); + const bool hostAccessSequentialWrite = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT) != 0; + const bool hostAccessRandom = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) != 0; + const bool hostAccessAllowTransferInstead = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) != 0; + const bool preferDevice = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + const bool preferHost = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST; + + // CPU random access - e.g. a buffer written to or transferred from GPU to read back on CPU. + if(hostAccessRandom) + { + // Prefer cached. Cannot require it, because some platforms don't have it (e.g. Raspberry Pi - see #362)! + outPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + if (!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost) + { + // Nice if it will end up in HOST_VISIBLE, but more importantly prefer DEVICE_LOCAL. + // Omitting HOST_VISIBLE here is intentional. + // In case there is DEVICE_LOCAL | HOST_VISIBLE | HOST_CACHED, it will pick that one. + // Otherwise, this will give same weight to DEVICE_LOCAL as HOST_VISIBLE | HOST_CACHED and select the former if occurs first on the list. + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + else + { + // Always CPU memory. + outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + } + } + // CPU sequential write - may be CPU or host-visible GPU memory, uncached and write-combined. + else if(hostAccessSequentialWrite) + { + // Want uncached and write-combined. + outNotPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + + if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost) + { + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + } + else + { + outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + // Direct GPU access, CPU sequential write (e.g. a dynamic uniform buffer updated every frame) + if(deviceAccess) + { + // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose GPU memory. + if(preferHost) + outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + else + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + // GPU no direct access, CPU sequential write (e.g. an upload buffer to be transferred to the GPU) + else + { + // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose CPU memory. + if(preferDevice) + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + else + outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + } + } + // No CPU access + else + { + // if(deviceAccess) + // + // GPU access, no CPU access (e.g. a color attachment image) - prefer GPU memory, + // unless there is a clear preference from the user not to do so. + // + // else: + // + // No direct GPU access, no CPU access, just transfers. + // It may be staging copy intended for e.g. preserving image for next frame (then better GPU memory) or + // a "swap file" copy to free some GPU memory (then better CPU memory). + // Up to the user to decide. If no preferece, assume the former and choose GPU memory. + + if(preferHost) + outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + else + outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + } + break; + } + default: + VMA_ASSERT(0); + } + + // Avoid DEVICE_COHERENT unless explicitly requested. + if(((allocCreateInfo.requiredFlags | allocCreateInfo.preferredFlags) & + (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0) + { + outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// Memory allocation + +static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment) +{ + void* result = VMA_NULL; + if ((pAllocationCallbacks != VMA_NULL) && + (pAllocationCallbacks->pfnAllocation != VMA_NULL)) + { + result = (*pAllocationCallbacks->pfnAllocation)( + pAllocationCallbacks->pUserData, + size, + alignment, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + } + else + { + result = VMA_SYSTEM_ALIGNED_MALLOC(size, alignment); + } + VMA_ASSERT(result != VMA_NULL && "CPU memory allocation failed."); + return result; +} + +static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr) +{ + if ((pAllocationCallbacks != VMA_NULL) && + (pAllocationCallbacks->pfnFree != VMA_NULL)) + { + (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr); + } + else + { + VMA_SYSTEM_ALIGNED_FREE(ptr); + } +} + +template +static T* VmaAllocate(const VkAllocationCallbacks* pAllocationCallbacks) +{ + return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T), VMA_ALIGN_OF(T)); +} + +template +static T* VmaAllocateArray(const VkAllocationCallbacks* pAllocationCallbacks, size_t count) +{ + return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T) * count, VMA_ALIGN_OF(T)); +} + +#define vma_new(allocator, type) new(VmaAllocate(allocator))(type) + +#define vma_new_array(allocator, type, count) new(VmaAllocateArray((allocator), (count)))(type) + +template +static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr) +{ + ptr->~T(); + VmaFree(pAllocationCallbacks, ptr); +} + +template +static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count) +{ + if (ptr != VMA_NULL) + { + for (size_t i = count; i--; ) + { + ptr[i].~T(); + } + VmaFree(pAllocationCallbacks, ptr); + } +} + +static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr) +{ + if (srcStr != VMA_NULL) + { + const size_t len = strlen(srcStr); + char* const result = vma_new_array(allocs, char, len + 1); + memcpy(result, srcStr, len + 1); + return result; + } + return VMA_NULL; +} + +#if VMA_STATS_STRING_ENABLED +static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr, size_t strLen) +{ + if (srcStr != VMA_NULL) + { + char* const result = vma_new_array(allocs, char, strLen + 1); + memcpy(result, srcStr, strLen); + result[strLen] = '\0'; + return result; + } + return VMA_NULL; +} +#endif // VMA_STATS_STRING_ENABLED + +static void VmaFreeString(const VkAllocationCallbacks* allocs, char* str) +{ + if (str != VMA_NULL) + { + const size_t len = strlen(str); + vma_delete_array(allocs, str, len + 1); + } +} + +template +size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value) +{ + const size_t indexToInsert = VmaBinaryFindFirstNotLess( + vector.data(), + vector.data() + vector.size(), + value, + CmpLess()) - vector.data(); + VmaVectorInsert(vector, indexToInsert, value); + return indexToInsert; +} + +template +bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value) +{ + CmpLess comparator; + typename VectorT::iterator it = VmaBinaryFindFirstNotLess( + vector.begin(), + vector.end(), + value, + comparator); + if ((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it)) + { + size_t indexToRemove = it - vector.begin(); + VmaVectorRemove(vector, indexToRemove); + return true; + } + return false; +} +#endif // _VMA_FUNCTIONS + +#ifndef _VMA_STATISTICS_FUNCTIONS + +static void VmaClearStatistics(VmaStatistics& outStats) +{ + outStats.blockCount = 0; + outStats.allocationCount = 0; + outStats.blockBytes = 0; + outStats.allocationBytes = 0; +} + +static void VmaAddStatistics(VmaStatistics& inoutStats, const VmaStatistics& src) +{ + inoutStats.blockCount += src.blockCount; + inoutStats.allocationCount += src.allocationCount; + inoutStats.blockBytes += src.blockBytes; + inoutStats.allocationBytes += src.allocationBytes; +} + +static void VmaClearDetailedStatistics(VmaDetailedStatistics& outStats) +{ + VmaClearStatistics(outStats.statistics); + outStats.unusedRangeCount = 0; + outStats.allocationSizeMin = VK_WHOLE_SIZE; + outStats.allocationSizeMax = 0; + outStats.unusedRangeSizeMin = VK_WHOLE_SIZE; + outStats.unusedRangeSizeMax = 0; +} + +static void VmaAddDetailedStatisticsAllocation(VmaDetailedStatistics& inoutStats, VkDeviceSize size) +{ + inoutStats.statistics.allocationCount++; + inoutStats.statistics.allocationBytes += size; + inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, size); + inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, size); +} + +static void VmaAddDetailedStatisticsUnusedRange(VmaDetailedStatistics& inoutStats, VkDeviceSize size) +{ + inoutStats.unusedRangeCount++; + inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, size); + inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, size); +} + +static void VmaAddDetailedStatistics(VmaDetailedStatistics& inoutStats, const VmaDetailedStatistics& src) +{ + VmaAddStatistics(inoutStats.statistics, src.statistics); + inoutStats.unusedRangeCount += src.unusedRangeCount; + inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, src.allocationSizeMin); + inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, src.allocationSizeMax); + inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, src.unusedRangeSizeMin); + inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, src.unusedRangeSizeMax); +} + +#endif // _VMA_STATISTICS_FUNCTIONS + +#ifndef _VMA_MUTEX_LOCK +// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope). +struct VmaMutexLock +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLock) +public: + explicit VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) : + m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->Lock(); } + } + ~VmaMutexLock() { if (m_pMutex) { m_pMutex->Unlock(); } } + +private: + VMA_MUTEX* m_pMutex; +}; + +// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading. +struct VmaMutexLockRead +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockRead) +public: + VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) : + m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->LockRead(); } + } + ~VmaMutexLockRead() { if (m_pMutex) { m_pMutex->UnlockRead(); } } + +private: + VMA_RW_MUTEX* m_pMutex; +}; + +// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing. +struct VmaMutexLockWrite +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaMutexLockWrite) +public: + VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) + : m_pMutex(useMutex ? &mutex : VMA_NULL) + { + if (m_pMutex) { m_pMutex->LockWrite(); } + } + ~VmaMutexLockWrite() { if (m_pMutex) { m_pMutex->UnlockWrite(); } } + +private: + VMA_RW_MUTEX* m_pMutex; +}; + +#if VMA_DEBUG_GLOBAL_MUTEX + static VMA_MUTEX gDebugGlobalMutex; + #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true); +#else + #define VMA_DEBUG_GLOBAL_MUTEX_LOCK +#endif +#endif // _VMA_MUTEX_LOCK + +#ifndef _VMA_ATOMIC_TRANSACTIONAL_INCREMENT +// An object that increments given atomic but decrements it back in the destructor unless Commit() is called. +template +struct AtomicTransactionalIncrement +{ +public: + using T = decltype(AtomicT().load()); + + ~AtomicTransactionalIncrement() + { + if(m_Atomic) + --(*m_Atomic); + } + + void Commit() { m_Atomic = VMA_NULL; } + T Increment(AtomicT* atomic) + { + m_Atomic = atomic; + return m_Atomic->fetch_add(1); + } + +private: + AtomicT* m_Atomic = VMA_NULL; +}; +#endif // _VMA_ATOMIC_TRANSACTIONAL_INCREMENT + +#ifndef _VMA_STL_ALLOCATOR +// STL-compatible allocator. +template +struct VmaStlAllocator +{ + const VkAllocationCallbacks* const m_pCallbacks; + typedef T value_type; + + explicit VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) {} + template + explicit VmaStlAllocator(const VmaStlAllocator& src) : m_pCallbacks(src.m_pCallbacks) {} + VmaStlAllocator(const VmaStlAllocator&) = default; + VmaStlAllocator& operator=(const VmaStlAllocator&) = delete; + + T* allocate(size_t n) { return VmaAllocateArray(m_pCallbacks, n); } + void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); } + + template + bool operator==(const VmaStlAllocator& rhs) const + { + return m_pCallbacks == rhs.m_pCallbacks; + } + template + bool operator!=(const VmaStlAllocator& rhs) const + { + return m_pCallbacks != rhs.m_pCallbacks; + } +}; +#endif // _VMA_STL_ALLOCATOR + +#ifndef _VMA_VECTOR +/* Class with interface compatible with subset of std::vector. +T must be POD because constructors and destructors are not called and memcpy is +used for these objects. */ +template +class VmaVector +{ +public: + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + explicit VmaVector(const AllocatorT& allocator); + VmaVector(size_t count, const AllocatorT& allocator); + // This version of the constructor is here for compatibility with pre-C++14 std::vector. + // value is unused. + VmaVector(size_t count, const T& value, const AllocatorT& allocator) : VmaVector(count, allocator) {} + VmaVector(const VmaVector& src); + VmaVector& operator=(const VmaVector& rhs); + ~VmaVector() { VmaFree(m_Allocator.m_pCallbacks, m_pArray); } + + bool empty() const { return m_Count == 0; } + size_t size() const { return m_Count; } + T* data() { return m_pArray; } + T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; } + T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; } + const T* data() const { return m_pArray; } + const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; } + const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; } + + iterator begin() { return m_pArray; } + iterator end() { return m_pArray + m_Count; } + const_iterator cbegin() const { return m_pArray; } + const_iterator cend() const { return m_pArray + m_Count; } + const_iterator begin() const { return cbegin(); } + const_iterator end() const { return cend(); } + + void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); } + void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); } + void push_front(const T& src) { insert(0, src); } + + void push_back(const T& src); + void reserve(size_t newCapacity, bool freeMemory = false); + void resize(size_t newCount); + void clear() { resize(0); } + void shrink_to_fit(); + void insert(size_t index, const T& src); + void remove(size_t index); + + T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; } + const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; } + +private: + AllocatorT m_Allocator; + T* m_pArray; + size_t m_Count; + size_t m_Capacity; +}; + +#ifndef _VMA_VECTOR_FUNCTIONS +template +VmaVector::VmaVector(const AllocatorT& allocator) + : m_Allocator(allocator), + m_pArray(VMA_NULL), + m_Count(0), + m_Capacity(0) {} + +template +VmaVector::VmaVector(size_t count, const AllocatorT& allocator) + : m_Allocator(allocator), + m_pArray(count ? (T*)VmaAllocateArray(allocator.m_pCallbacks, count) : VMA_NULL), + m_Count(count), + m_Capacity(count) {} + +template +VmaVector::VmaVector(const VmaVector& src) + : m_Allocator(src.m_Allocator), + m_pArray(src.m_Count ? (T*)VmaAllocateArray(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL), + m_Count(src.m_Count), + m_Capacity(src.m_Count) +{ + if (m_Count != 0) + { + memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T)); + } +} + +template +VmaVector& VmaVector::operator=(const VmaVector& rhs) +{ + if (&rhs != this) + { + resize(rhs.m_Count); + if (m_Count != 0) + { + memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T)); + } + } + return *this; +} + +template +void VmaVector::push_back(const T& src) +{ + const size_t newIndex = size(); + resize(newIndex + 1); + m_pArray[newIndex] = src; +} + +template +void VmaVector::reserve(size_t newCapacity, bool freeMemory) +{ + newCapacity = VMA_MAX(newCapacity, m_Count); + + if ((newCapacity < m_Capacity) && !freeMemory) + { + newCapacity = m_Capacity; + } + + if (newCapacity != m_Capacity) + { + T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator, newCapacity) : VMA_NULL; + if (m_Count != 0) + { + memcpy(newArray, m_pArray, m_Count * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = newCapacity; + m_pArray = newArray; + } +} + +template +void VmaVector::resize(size_t newCount) +{ + size_t newCapacity = m_Capacity; + if (newCount > m_Capacity) + { + newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8)); + } + + if (newCapacity != m_Capacity) + { + T* const newArray = newCapacity ? VmaAllocateArray(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL; + const size_t elementsToCopy = VMA_MIN(m_Count, newCount); + if (elementsToCopy != 0) + { + memcpy(newArray, m_pArray, elementsToCopy * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = newCapacity; + m_pArray = newArray; + } + + m_Count = newCount; +} + +template +void VmaVector::shrink_to_fit() +{ + if (m_Capacity > m_Count) + { + T* newArray = VMA_NULL; + if (m_Count > 0) + { + newArray = VmaAllocateArray(m_Allocator.m_pCallbacks, m_Count); + memcpy(newArray, m_pArray, m_Count * sizeof(T)); + } + VmaFree(m_Allocator.m_pCallbacks, m_pArray); + m_Capacity = m_Count; + m_pArray = newArray; + } +} + +template +void VmaVector::insert(size_t index, const T& src) +{ + VMA_HEAVY_ASSERT(index <= m_Count); + const size_t oldCount = size(); + resize(oldCount + 1); + if (index < oldCount) + { + memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T)); + } + m_pArray[index] = src; +} + +template +void VmaVector::remove(size_t index) +{ + VMA_HEAVY_ASSERT(index < m_Count); + const size_t oldCount = size(); + if (index < oldCount - 1) + { + memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T)); + } + resize(oldCount - 1); +} +#endif // _VMA_VECTOR_FUNCTIONS + +template +static void VmaVectorInsert(VmaVector& vec, size_t index, const T& item) +{ + vec.insert(index, item); +} + +template +static void VmaVectorRemove(VmaVector& vec, size_t index) +{ + vec.remove(index); +} +#endif // _VMA_VECTOR + +#ifndef _VMA_SMALL_VECTOR +/* +This is a vector (a variable-sized array), optimized for the case when the array is small. + +It contains some number of elements in-place, which allows it to avoid heap allocation +when the actual number of elements is below that threshold. This allows normal "small" +cases to be fast without losing generality for large inputs. +*/ +template +class VmaSmallVector +{ +public: + typedef T value_type; + typedef T* iterator; + + explicit VmaSmallVector(const AllocatorT& allocator); + VmaSmallVector(size_t count, const AllocatorT& allocator); + template + explicit VmaSmallVector(const VmaSmallVector&) = delete; + template + VmaSmallVector& operator=(const VmaSmallVector&) = delete; + ~VmaSmallVector() = default; + + bool empty() const { return m_Count == 0; } + size_t size() const { return m_Count; } + T* data() { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; } + T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; } + T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; } + const T* data() const { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; } + const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; } + const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; } + + iterator begin() { return data(); } + iterator end() { return data() + m_Count; } + + void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); } + void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); } + void push_front(const T& src) { insert(0, src); } + + void push_back(const T& src); + void resize(size_t newCount, bool freeMemory = false); + void clear(bool freeMemory = false); + void insert(size_t index, const T& src); + void remove(size_t index); + + T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; } + const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; } + +private: + size_t m_Count; + T m_StaticArray[N]; // Used when m_Size <= N + VmaVector m_DynamicArray; // Used when m_Size > N +}; + +#ifndef _VMA_SMALL_VECTOR_FUNCTIONS +template +VmaSmallVector::VmaSmallVector(const AllocatorT& allocator) + : m_Count(0), + m_DynamicArray(allocator) {} + +template +VmaSmallVector::VmaSmallVector(size_t count, const AllocatorT& allocator) + : m_Count(count), + m_DynamicArray(count > N ? count : 0, allocator) {} + +template +void VmaSmallVector::push_back(const T& src) +{ + const size_t newIndex = size(); + resize(newIndex + 1); + data()[newIndex] = src; +} + +template +void VmaSmallVector::resize(size_t newCount, bool freeMemory) +{ + if (newCount > N && m_Count > N) + { + // Any direction, staying in m_DynamicArray + m_DynamicArray.resize(newCount); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + } + else if (newCount > N && m_Count <= N) + { + // Growing, moving from m_StaticArray to m_DynamicArray + m_DynamicArray.resize(newCount); + if (m_Count > 0) + { + memcpy(m_DynamicArray.data(), m_StaticArray, m_Count * sizeof(T)); + } + } + else if (newCount <= N && m_Count > N) + { + // Shrinking, moving from m_DynamicArray to m_StaticArray + if (newCount > 0) + { + memcpy(m_StaticArray, m_DynamicArray.data(), newCount * sizeof(T)); + } + m_DynamicArray.resize(0); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + } + else + { + // Any direction, staying in m_StaticArray - nothing to do here + } + m_Count = newCount; +} + +template +void VmaSmallVector::clear(bool freeMemory) +{ + m_DynamicArray.clear(); + if (freeMemory) + { + m_DynamicArray.shrink_to_fit(); + } + m_Count = 0; +} + +template +void VmaSmallVector::insert(size_t index, const T& src) +{ + VMA_HEAVY_ASSERT(index <= m_Count); + const size_t oldCount = size(); + resize(oldCount + 1); + T* const dataPtr = data(); + if (index < oldCount) + { + // I know, this could be more optimal for case where memmove can be memcpy directly from m_StaticArray to m_DynamicArray. + memmove(dataPtr + (index + 1), dataPtr + index, (oldCount - index) * sizeof(T)); + } + dataPtr[index] = src; +} + +template +void VmaSmallVector::remove(size_t index) +{ + VMA_HEAVY_ASSERT(index < m_Count); + const size_t oldCount = size(); + if (index < oldCount - 1) + { + // I know, this could be more optimal for case where memmove can be memcpy directly from m_DynamicArray to m_StaticArray. + T* const dataPtr = data(); + memmove(dataPtr + index, dataPtr + (index + 1), (oldCount - index - 1) * sizeof(T)); + } + resize(oldCount - 1); +} +#endif // _VMA_SMALL_VECTOR_FUNCTIONS +#endif // _VMA_SMALL_VECTOR + +#ifndef _VMA_POOL_ALLOCATOR +/* +Allocator for objects of type T using a list of arrays (pools) to speed up +allocation. Number of elements that can be allocated is not bounded because +allocator can create multiple blocks. +*/ +template +class VmaPoolAllocator +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaPoolAllocator) +public: + VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity); + ~VmaPoolAllocator(); + template T* Alloc(Types&&... args); + void Free(T* ptr); + +private: + union Item + { + uint32_t NextFreeIndex; + alignas(T) char Value[sizeof(T)]; + }; + struct ItemBlock + { + Item* pItems; + uint32_t Capacity; + uint32_t FirstFreeIndex; + }; + + const VkAllocationCallbacks* m_pAllocationCallbacks; + const uint32_t m_FirstBlockCapacity; + VmaVector> m_ItemBlocks; + + ItemBlock& CreateNewBlock(); +}; + +#ifndef _VMA_POOL_ALLOCATOR_FUNCTIONS +template +VmaPoolAllocator::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) + : m_pAllocationCallbacks(pAllocationCallbacks), + m_FirstBlockCapacity(firstBlockCapacity), + m_ItemBlocks(VmaStlAllocator(pAllocationCallbacks)) +{ + VMA_ASSERT(m_FirstBlockCapacity > 1); +} + +template +VmaPoolAllocator::~VmaPoolAllocator() +{ + for (size_t i = m_ItemBlocks.size(); i--;) + vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity); + m_ItemBlocks.clear(); +} + +template +template T* VmaPoolAllocator::Alloc(Types&&... args) +{ + for (size_t i = m_ItemBlocks.size(); i--; ) + { + ItemBlock& block = m_ItemBlocks[i]; + // This block has some free items: Use first one. + if (block.FirstFreeIndex != UINT32_MAX) + { + Item* const pItem = &block.pItems[block.FirstFreeIndex]; + block.FirstFreeIndex = pItem->NextFreeIndex; + T* result = (T*)&pItem->Value; + new(result)T(std::forward(args)...); // Explicit constructor call. + return result; + } + } + + // No block has free item: Create new one and use it. + ItemBlock& newBlock = CreateNewBlock(); + Item* const pItem = &newBlock.pItems[0]; + newBlock.FirstFreeIndex = pItem->NextFreeIndex; + T* result = (T*)&pItem->Value; + new(result) T(std::forward(args)...); // Explicit constructor call. + return result; +} + +template +void VmaPoolAllocator::Free(T* ptr) +{ + // Search all memory blocks to find ptr. + for (size_t i = m_ItemBlocks.size(); i--; ) + { + ItemBlock& block = m_ItemBlocks[i]; + + // Casting to union. + Item* pItemPtr = VMA_NULL; + memcpy(&pItemPtr, &ptr, sizeof(pItemPtr)); + + // Check if pItemPtr is in address range of this block. + if ((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity)) + { + ptr->~T(); // Explicit destructor call. + const uint32_t index = static_cast(pItemPtr - block.pItems); + pItemPtr->NextFreeIndex = block.FirstFreeIndex; + block.FirstFreeIndex = index; + return; + } + } + VMA_ASSERT(0 && "Pointer doesn't belong to this memory pool."); +} + +template +typename VmaPoolAllocator::ItemBlock& VmaPoolAllocator::CreateNewBlock() +{ + const uint32_t newBlockCapacity = m_ItemBlocks.empty() ? + m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2; + + const ItemBlock newBlock = + { + vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity), + newBlockCapacity, + 0 + }; + + m_ItemBlocks.push_back(newBlock); + + // Setup singly-linked list of all free items in this block. + for (uint32_t i = 0; i < newBlockCapacity - 1; ++i) + newBlock.pItems[i].NextFreeIndex = i + 1; + newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX; + return m_ItemBlocks.back(); +} +#endif // _VMA_POOL_ALLOCATOR_FUNCTIONS +#endif // _VMA_POOL_ALLOCATOR + +#ifndef _VMA_RAW_LIST +template +struct VmaListItem +{ + VmaListItem* pPrev; + VmaListItem* pNext; + T Value; +}; + +// Doubly linked list. +template +class VmaRawList +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaRawList) +public: + typedef VmaListItem ItemType; + + explicit VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks); + // Intentionally not calling Clear, because that would be unnecessary + // computations to return all items to m_ItemAllocator as free. + ~VmaRawList() = default; + + size_t GetCount() const { return m_Count; } + bool IsEmpty() const { return m_Count == 0; } + + ItemType* Front() { return m_pFront; } + ItemType* Back() { return m_pBack; } + const ItemType* Front() const { return m_pFront; } + const ItemType* Back() const { return m_pBack; } + + ItemType* PushFront(); + ItemType* PushBack(); + ItemType* PushFront(const T& value); + ItemType* PushBack(const T& value); + void PopFront(); + void PopBack(); + + // Item can be null - it means PushBack. + ItemType* InsertBefore(ItemType* pItem); + // Item can be null - it means PushFront. + ItemType* InsertAfter(ItemType* pItem); + ItemType* InsertBefore(ItemType* pItem, const T& value); + ItemType* InsertAfter(ItemType* pItem, const T& value); + + void Clear(); + void Remove(ItemType* pItem); + +private: + const VkAllocationCallbacks* const m_pAllocationCallbacks; + VmaPoolAllocator m_ItemAllocator; + ItemType* m_pFront; + ItemType* m_pBack; + size_t m_Count; +}; + +#ifndef _VMA_RAW_LIST_FUNCTIONS +template +VmaRawList::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) + : m_pAllocationCallbacks(pAllocationCallbacks), + m_ItemAllocator(pAllocationCallbacks, 128), + m_pFront(VMA_NULL), + m_pBack(VMA_NULL), + m_Count(0) {} + +template +VmaListItem* VmaRawList::PushFront() +{ + ItemType* const pNewItem = m_ItemAllocator.Alloc(); + pNewItem->pPrev = VMA_NULL; + if (IsEmpty()) + { + pNewItem->pNext = VMA_NULL; + m_pFront = pNewItem; + m_pBack = pNewItem; + m_Count = 1; + } + else + { + pNewItem->pNext = m_pFront; + m_pFront->pPrev = pNewItem; + m_pFront = pNewItem; + ++m_Count; + } + return pNewItem; +} + +template +VmaListItem* VmaRawList::PushBack() +{ + ItemType* const pNewItem = m_ItemAllocator.Alloc(); + pNewItem->pNext = VMA_NULL; + if(IsEmpty()) + { + pNewItem->pPrev = VMA_NULL; + m_pFront = pNewItem; + m_pBack = pNewItem; + m_Count = 1; + } + else + { + pNewItem->pPrev = m_pBack; + m_pBack->pNext = pNewItem; + m_pBack = pNewItem; + ++m_Count; + } + return pNewItem; +} + +template +VmaListItem* VmaRawList::PushFront(const T& value) +{ + ItemType* const pNewItem = PushFront(); + pNewItem->Value = value; + return pNewItem; +} + +template +VmaListItem* VmaRawList::PushBack(const T& value) +{ + ItemType* const pNewItem = PushBack(); + pNewItem->Value = value; + return pNewItem; +} + +template +void VmaRawList::PopFront() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const pFrontItem = m_pFront; + ItemType* const pNextItem = pFrontItem->pNext; + if (pNextItem != VMA_NULL) + { + pNextItem->pPrev = VMA_NULL; + } + m_pFront = pNextItem; + m_ItemAllocator.Free(pFrontItem); + --m_Count; +} + +template +void VmaRawList::PopBack() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const pBackItem = m_pBack; + ItemType* const pPrevItem = pBackItem->pPrev; + if(pPrevItem != VMA_NULL) + { + pPrevItem->pNext = VMA_NULL; + } + m_pBack = pPrevItem; + m_ItemAllocator.Free(pBackItem); + --m_Count; +} + +template +void VmaRawList::Clear() +{ + if (!IsEmpty()) + { + ItemType* pItem = m_pBack; + while (pItem != VMA_NULL) + { + ItemType* const pPrevItem = pItem->pPrev; + m_ItemAllocator.Free(pItem); + pItem = pPrevItem; + } + m_pFront = VMA_NULL; + m_pBack = VMA_NULL; + m_Count = 0; + } +} + +template +void VmaRawList::Remove(ItemType* pItem) +{ + VMA_HEAVY_ASSERT(pItem != VMA_NULL); + VMA_HEAVY_ASSERT(m_Count > 0); + + if(pItem->pPrev != VMA_NULL) + { + pItem->pPrev->pNext = pItem->pNext; + } + else + { + VMA_HEAVY_ASSERT(m_pFront == pItem); + m_pFront = pItem->pNext; + } + + if(pItem->pNext != VMA_NULL) + { + pItem->pNext->pPrev = pItem->pPrev; + } + else + { + VMA_HEAVY_ASSERT(m_pBack == pItem); + m_pBack = pItem->pPrev; + } + + m_ItemAllocator.Free(pItem); + --m_Count; +} + +template +VmaListItem* VmaRawList::InsertBefore(ItemType* pItem) +{ + if(pItem != VMA_NULL) + { + ItemType* const prevItem = pItem->pPrev; + ItemType* const newItem = m_ItemAllocator.Alloc(); + newItem->pPrev = prevItem; + newItem->pNext = pItem; + pItem->pPrev = newItem; + if(prevItem != VMA_NULL) + { + prevItem->pNext = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_pFront == pItem); + m_pFront = newItem; + } + ++m_Count; + return newItem; + } + return PushBack(); +} + +template +VmaListItem* VmaRawList::InsertAfter(ItemType* pItem) +{ + if(pItem != VMA_NULL) + { + ItemType* const nextItem = pItem->pNext; + ItemType* const newItem = m_ItemAllocator.Alloc(); + newItem->pNext = nextItem; + newItem->pPrev = pItem; + pItem->pNext = newItem; + if(nextItem != VMA_NULL) + { + nextItem->pPrev = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_pBack == pItem); + m_pBack = newItem; + } + ++m_Count; + return newItem; + } + return PushFront(); +} + +template +VmaListItem* VmaRawList::InsertBefore(ItemType* pItem, const T& value) +{ + ItemType* const newItem = InsertBefore(pItem); + newItem->Value = value; + return newItem; +} + +template +VmaListItem* VmaRawList::InsertAfter(ItemType* pItem, const T& value) +{ + ItemType* const newItem = InsertAfter(pItem); + newItem->Value = value; + return newItem; +} +#endif // _VMA_RAW_LIST_FUNCTIONS +#endif // _VMA_RAW_LIST + +#ifndef _VMA_LIST +template +class VmaList +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaList) +public: + class reverse_iterator; + class const_iterator; + class const_reverse_iterator; + + class iterator + { + friend class const_iterator; + friend class VmaList; + public: + iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + explicit iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + + T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + const iterator operator++(int) { iterator result = *this; ++*this; return result; } + const iterator operator--(int) { iterator result = *this; --*this; return result; } + + iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; } + iterator& operator--(); + + private: + VmaRawList* m_pList; + VmaListItem* m_pItem; + + iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; + class reverse_iterator + { + friend class const_reverse_iterator; + friend class VmaList; + public: + reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + explicit reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + + T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + const reverse_iterator operator++(int) { reverse_iterator result = *this; ++* this; return result; } + const reverse_iterator operator--(int) { reverse_iterator result = *this; --* this; return result; } + + reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } + reverse_iterator& operator--(); + + private: + VmaRawList* m_pList; + VmaListItem* m_pItem; + + reverse_iterator(VmaRawList* pList, VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; + class const_iterator + { + friend class VmaList; + public: + const_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + explicit const_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + explicit const_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + + iterator drop_const() { return { const_cast*>(m_pList), const_cast*>(m_pItem) }; } + + const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + const const_iterator operator++(int) { const_iterator result = *this; ++* this; return result; } + const const_iterator operator--(int) { const_iterator result = *this; --* this; return result; } + + const_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; } + const_iterator& operator--(); + + private: + const VmaRawList* m_pList; + const VmaListItem* m_pItem; + + const_iterator(const VmaRawList* pList, const VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; + class const_reverse_iterator + { + friend class VmaList; + public: + const_reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {} + explicit const_reverse_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + explicit const_reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {} + + reverse_iterator drop_const() { return { const_cast*>(m_pList), const_cast*>(m_pItem) }; } + + const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; } + const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; } + + bool operator==(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; } + bool operator!=(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; } + + const const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++* this; return result; } + const const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --* this; return result; } + + const_reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; } + const_reverse_iterator& operator--(); + + private: + const VmaRawList* m_pList; + const VmaListItem* m_pItem; + + const_reverse_iterator(const VmaRawList* pList, const VmaListItem* pItem) : m_pList(pList), m_pItem(pItem) {} + }; + + explicit VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) {} + + bool empty() const { return m_RawList.IsEmpty(); } + size_t size() const { return m_RawList.GetCount(); } + + iterator begin() { return iterator(&m_RawList, m_RawList.Front()); } + iterator end() { return iterator(&m_RawList, VMA_NULL); } + + const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); } + const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); } + + const_iterator begin() const { return cbegin(); } + const_iterator end() const { return cend(); } + + reverse_iterator rbegin() { return reverse_iterator(&m_RawList, m_RawList.Back()); } + reverse_iterator rend() { return reverse_iterator(&m_RawList, VMA_NULL); } + + const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_RawList, m_RawList.Back()); } + const_reverse_iterator crend() const { return const_reverse_iterator(&m_RawList, VMA_NULL); } + + const_reverse_iterator rbegin() const { return crbegin(); } + const_reverse_iterator rend() const { return crend(); } + + void push_back(const T& value) { m_RawList.PushBack(value); } + iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); } + + void clear() { m_RawList.Clear(); } + void erase(iterator it) { m_RawList.Remove(it.m_pItem); } + +private: + VmaRawList m_RawList; +}; + +#ifndef _VMA_LIST_FUNCTIONS +template +typename VmaList::iterator& VmaList::iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pPrev; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} + +template +typename VmaList::reverse_iterator& VmaList::reverse_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pNext; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Front(); + } + return *this; +} + +template +typename VmaList::const_iterator& VmaList::const_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pPrev; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} + +template +typename VmaList::const_reverse_iterator& VmaList::const_reverse_iterator::operator--() +{ + if (m_pItem != VMA_NULL) + { + m_pItem = m_pItem->pNext; + } + else + { + VMA_HEAVY_ASSERT(!m_pList->IsEmpty()); + m_pItem = m_pList->Back(); + } + return *this; +} +#endif // _VMA_LIST_FUNCTIONS +#endif // _VMA_LIST + +#ifndef _VMA_INTRUSIVE_LINKED_LIST +/* +Expected interface of ItemTypeTraits: +struct MyItemTypeTraits +{ + typedef MyItem ItemType; + static ItemType* GetPrev(const ItemType* item) { return item->myPrevPtr; } + static ItemType* GetNext(const ItemType* item) { return item->myNextPtr; } + static ItemType*& AccessPrev(ItemType* item) { return item->myPrevPtr; } + static ItemType*& AccessNext(ItemType* item) { return item->myNextPtr; } +}; +*/ +template +class VmaIntrusiveLinkedList +{ +public: + typedef typename ItemTypeTraits::ItemType ItemType; + static ItemType* GetPrev(const ItemType* item) { return ItemTypeTraits::GetPrev(item); } + static ItemType* GetNext(const ItemType* item) { return ItemTypeTraits::GetNext(item); } + + // Movable, not copyable. + VmaIntrusiveLinkedList() = default; + VmaIntrusiveLinkedList(VmaIntrusiveLinkedList && src) noexcept; + VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList&) = delete; + VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src) noexcept; + VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete; + ~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); } + + size_t GetCount() const { return m_Count; } + bool IsEmpty() const { return m_Count == 0; } + ItemType* Front() { return m_Front; } + ItemType* Back() { return m_Back; } + const ItemType* Front() const { return m_Front; } + const ItemType* Back() const { return m_Back; } + + void PushBack(ItemType* item); + void PushFront(ItemType* item); + ItemType* PopBack(); + ItemType* PopFront(); + + // MyItem can be null - it means PushBack. + void InsertBefore(ItemType* existingItem, ItemType* newItem); + // MyItem can be null - it means PushFront. + void InsertAfter(ItemType* existingItem, ItemType* newItem); + void Remove(ItemType* item); + void RemoveAll(); + +private: + ItemType* m_Front = VMA_NULL; + ItemType* m_Back = VMA_NULL; + size_t m_Count = 0; +}; + +#ifndef _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS +template +VmaIntrusiveLinkedList::VmaIntrusiveLinkedList(VmaIntrusiveLinkedList&& src) noexcept + : m_Front(src.m_Front), m_Back(src.m_Back), m_Count(src.m_Count) +{ + src.m_Front = src.m_Back = VMA_NULL; + src.m_Count = 0; +} + +template +VmaIntrusiveLinkedList& VmaIntrusiveLinkedList::operator=(VmaIntrusiveLinkedList&& src) noexcept +{ + if (&src != this) + { + VMA_HEAVY_ASSERT(IsEmpty()); + m_Front = src.m_Front; + m_Back = src.m_Back; + m_Count = src.m_Count; + src.m_Front = src.m_Back = VMA_NULL; + src.m_Count = 0; + } + return *this; +} + +template +void VmaIntrusiveLinkedList::PushBack(ItemType* item) +{ + VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL); + if (IsEmpty()) + { + m_Front = item; + m_Back = item; + m_Count = 1; + } + else + { + ItemTypeTraits::AccessPrev(item) = m_Back; + ItemTypeTraits::AccessNext(m_Back) = item; + m_Back = item; + ++m_Count; + } +} + +template +void VmaIntrusiveLinkedList::PushFront(ItemType* item) +{ + VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL); + if (IsEmpty()) + { + m_Front = item; + m_Back = item; + m_Count = 1; + } + else + { + ItemTypeTraits::AccessNext(item) = m_Front; + ItemTypeTraits::AccessPrev(m_Front) = item; + m_Front = item; + ++m_Count; + } +} + +template +typename VmaIntrusiveLinkedList::ItemType* VmaIntrusiveLinkedList::PopBack() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const backItem = m_Back; + ItemType* const prevItem = ItemTypeTraits::GetPrev(backItem); + if (prevItem != VMA_NULL) + { + ItemTypeTraits::AccessNext(prevItem) = VMA_NULL; + } + m_Back = prevItem; + --m_Count; + ItemTypeTraits::AccessPrev(backItem) = VMA_NULL; + ItemTypeTraits::AccessNext(backItem) = VMA_NULL; + return backItem; +} + +template +typename VmaIntrusiveLinkedList::ItemType* VmaIntrusiveLinkedList::PopFront() +{ + VMA_HEAVY_ASSERT(m_Count > 0); + ItemType* const frontItem = m_Front; + ItemType* const nextItem = ItemTypeTraits::GetNext(frontItem); + if (nextItem != VMA_NULL) + { + ItemTypeTraits::AccessPrev(nextItem) = VMA_NULL; + } + m_Front = nextItem; + --m_Count; + ItemTypeTraits::AccessPrev(frontItem) = VMA_NULL; + ItemTypeTraits::AccessNext(frontItem) = VMA_NULL; + return frontItem; +} + +template +void VmaIntrusiveLinkedList::InsertBefore(ItemType* existingItem, ItemType* newItem) +{ + VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL); + if (existingItem != VMA_NULL) + { + ItemType* const prevItem = ItemTypeTraits::GetPrev(existingItem); + ItemTypeTraits::AccessPrev(newItem) = prevItem; + ItemTypeTraits::AccessNext(newItem) = existingItem; + ItemTypeTraits::AccessPrev(existingItem) = newItem; + if (prevItem != VMA_NULL) + { + ItemTypeTraits::AccessNext(prevItem) = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_Front == existingItem); + m_Front = newItem; + } + ++m_Count; + } + else + PushBack(newItem); +} + +template +void VmaIntrusiveLinkedList::InsertAfter(ItemType* existingItem, ItemType* newItem) +{ + VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL); + if (existingItem != VMA_NULL) + { + ItemType* const nextItem = ItemTypeTraits::GetNext(existingItem); + ItemTypeTraits::AccessNext(newItem) = nextItem; + ItemTypeTraits::AccessPrev(newItem) = existingItem; + ItemTypeTraits::AccessNext(existingItem) = newItem; + if (nextItem != VMA_NULL) + { + ItemTypeTraits::AccessPrev(nextItem) = newItem; + } + else + { + VMA_HEAVY_ASSERT(m_Back == existingItem); + m_Back = newItem; + } + ++m_Count; + } + else + return PushFront(newItem); +} + +template +void VmaIntrusiveLinkedList::Remove(ItemType* item) +{ + VMA_HEAVY_ASSERT(item != VMA_NULL && m_Count > 0); + if (ItemTypeTraits::GetPrev(item) != VMA_NULL) + { + ItemTypeTraits::AccessNext(ItemTypeTraits::AccessPrev(item)) = ItemTypeTraits::GetNext(item); + } + else + { + VMA_HEAVY_ASSERT(m_Front == item); + m_Front = ItemTypeTraits::GetNext(item); + } + + if (ItemTypeTraits::GetNext(item) != VMA_NULL) + { + ItemTypeTraits::AccessPrev(ItemTypeTraits::AccessNext(item)) = ItemTypeTraits::GetPrev(item); + } + else + { + VMA_HEAVY_ASSERT(m_Back == item); + m_Back = ItemTypeTraits::GetPrev(item); + } + ItemTypeTraits::AccessPrev(item) = VMA_NULL; + ItemTypeTraits::AccessNext(item) = VMA_NULL; + --m_Count; +} + +template +void VmaIntrusiveLinkedList::RemoveAll() +{ + if (!IsEmpty()) + { + ItemType* item = m_Back; + while (item != VMA_NULL) + { + ItemType* const prevItem = ItemTypeTraits::AccessPrev(item); + ItemTypeTraits::AccessPrev(item) = VMA_NULL; + ItemTypeTraits::AccessNext(item) = VMA_NULL; + item = prevItem; + } + m_Front = VMA_NULL; + m_Back = VMA_NULL; + m_Count = 0; + } +} +#endif // _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS +#endif // _VMA_INTRUSIVE_LINKED_LIST + +#if !defined(_VMA_STRING_BUILDER) && VMA_STATS_STRING_ENABLED +class VmaStringBuilder +{ +public: + explicit VmaStringBuilder(const VkAllocationCallbacks* allocationCallbacks) : m_Data(VmaStlAllocator(allocationCallbacks)) {} + ~VmaStringBuilder() = default; + + size_t GetLength() const { return m_Data.size(); } + // Returned string is not null-terminated! + const char* GetData() const { return m_Data.data(); } + void AddNewLine() { Add('\n'); } + void Add(char ch) { m_Data.push_back(ch); } + + void Add(const char* pStr); + void AddNumber(uint32_t num); + void AddNumber(uint64_t num); + void AddPointer(const void* ptr); + +private: + VmaVector> m_Data; +}; + +#ifndef _VMA_STRING_BUILDER_FUNCTIONS +void VmaStringBuilder::Add(const char* pStr) +{ + const size_t strLen = strlen(pStr); + if (strLen > 0) + { + const size_t oldCount = m_Data.size(); + m_Data.resize(oldCount + strLen); + memcpy(m_Data.data() + oldCount, pStr, strLen); + } +} + +void VmaStringBuilder::AddNumber(uint32_t num) +{ + char buf[11]; + buf[10] = '\0'; + char* p = &buf[10]; + do + { + *--p = '0' + (char)(num % 10); + num /= 10; + } while (num); + Add(p); +} + +void VmaStringBuilder::AddNumber(uint64_t num) +{ + char buf[21]; + buf[20] = '\0'; + char* p = &buf[20]; + do + { + *--p = '0' + (char)(num % 10); + num /= 10; + } while (num); + Add(p); +} + +void VmaStringBuilder::AddPointer(const void* ptr) +{ + char buf[21]; + VmaPtrToStr(buf, sizeof(buf), ptr); + Add(buf); +} +#endif //_VMA_STRING_BUILDER_FUNCTIONS +#endif // _VMA_STRING_BUILDER + +#if !defined(_VMA_JSON_WRITER) && VMA_STATS_STRING_ENABLED +/* +Allows to conveniently build a correct JSON document to be written to the +VmaStringBuilder passed to the constructor. +*/ +class VmaJsonWriter +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaJsonWriter) +public: + // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object. + VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb); + ~VmaJsonWriter(); + + // Begins object by writing "{". + // Inside an object, you must call pairs of WriteString and a value, e.g.: + // j.BeginObject(true); j.WriteString("A"); j.WriteNumber(1); j.WriteString("B"); j.WriteNumber(2); j.EndObject(); + // Will write: { "A": 1, "B": 2 } + void BeginObject(bool singleLine = false); + // Ends object by writing "}". + void EndObject(); + + // Begins array by writing "[". + // Inside an array, you can write a sequence of any values. + void BeginArray(bool singleLine = false); + // Ends array by writing "[". + void EndArray(); + + // Writes a string value inside "". + // pStr can contain any ANSI characters, including '"', new line etc. - they will be properly escaped. + void WriteString(const char* pStr); + + // Begins writing a string value. + // Call BeginString, ContinueString, ContinueString, ..., EndString instead of + // WriteString to conveniently build the string content incrementally, made of + // parts including numbers. + void BeginString(const char* pStr = VMA_NULL); + // Posts next part of an open string. + void ContinueString(const char* pStr); + // Posts next part of an open string. The number is converted to decimal characters. + void ContinueString(uint32_t n); + void ContinueString(uint64_t n); + // Posts next part of an open string. Pointer value is converted to characters + // using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00 + void ContinueString_Pointer(const void* ptr); + // Ends writing a string value by writing '"'. + void EndString(const char* pStr = VMA_NULL); + + // Writes a number value. + void WriteNumber(uint32_t n); + void WriteNumber(uint64_t n); + // Writes a boolean value - false or true. + void WriteBool(bool b); + // Writes a null value. + void WriteNull(); + +private: + enum COLLECTION_TYPE + { + COLLECTION_TYPE_OBJECT, + COLLECTION_TYPE_ARRAY, + }; + struct StackItem + { + COLLECTION_TYPE type; + uint32_t valueCount; + bool singleLineMode; + }; + + static const char* const INDENT; + + VmaStringBuilder& m_SB; + VmaVector< StackItem, VmaStlAllocator > m_Stack; + bool m_InsideString; + + void BeginValue(bool isString); + void WriteIndent(bool oneLess = false); +}; +const char* const VmaJsonWriter::INDENT = " "; + +#ifndef _VMA_JSON_WRITER_FUNCTIONS +VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) + : m_SB(sb), + m_Stack(VmaStlAllocator(pAllocationCallbacks)), + m_InsideString(false) {} + +VmaJsonWriter::~VmaJsonWriter() +{ + VMA_ASSERT(!m_InsideString); + VMA_ASSERT(m_Stack.empty()); +} + +void VmaJsonWriter::BeginObject(bool singleLine) +{ + VMA_ASSERT(!m_InsideString); + + BeginValue(false); + m_SB.Add('{'); + + StackItem item; + item.type = COLLECTION_TYPE_OBJECT; + item.valueCount = 0; + item.singleLineMode = singleLine; + m_Stack.push_back(item); +} + +void VmaJsonWriter::EndObject() +{ + VMA_ASSERT(!m_InsideString); + + WriteIndent(true); + m_SB.Add('}'); + + VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_OBJECT); + m_Stack.pop_back(); +} + +void VmaJsonWriter::BeginArray(bool singleLine) +{ + VMA_ASSERT(!m_InsideString); + + BeginValue(false); + m_SB.Add('['); + + StackItem item; + item.type = COLLECTION_TYPE_ARRAY; + item.valueCount = 0; + item.singleLineMode = singleLine; + m_Stack.push_back(item); +} + +void VmaJsonWriter::EndArray() +{ + VMA_ASSERT(!m_InsideString); + + WriteIndent(true); + m_SB.Add(']'); + + VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_ARRAY); + m_Stack.pop_back(); +} + +void VmaJsonWriter::WriteString(const char* pStr) +{ + BeginString(pStr); + EndString(); +} + +void VmaJsonWriter::BeginString(const char* pStr) +{ + VMA_ASSERT(!m_InsideString); + + BeginValue(true); + m_SB.Add('"'); + m_InsideString = true; + if (pStr != VMA_NULL && pStr[0] != '\0') + { + ContinueString(pStr); + } +} + +void VmaJsonWriter::ContinueString(const char* pStr) +{ + VMA_ASSERT(m_InsideString); + + const size_t strLen = strlen(pStr); + for (size_t i = 0; i < strLen; ++i) + { + char ch = pStr[i]; + if (ch == '\\') + { + m_SB.Add("\\\\"); + } + else if (ch == '"') + { + m_SB.Add("\\\""); + } + else if ((uint8_t)ch >= 32) + { + m_SB.Add(ch); + } + else switch (ch) + { + case '\b': + m_SB.Add("\\b"); + break; + case '\f': + m_SB.Add("\\f"); + break; + case '\n': + m_SB.Add("\\n"); + break; + case '\r': + m_SB.Add("\\r"); + break; + case '\t': + m_SB.Add("\\t"); + break; + default: + VMA_ASSERT(0 && "Character not currently supported."); + } + } +} + +void VmaJsonWriter::ContinueString(uint32_t n) +{ + VMA_ASSERT(m_InsideString); + m_SB.AddNumber(n); +} + +void VmaJsonWriter::ContinueString(uint64_t n) +{ + VMA_ASSERT(m_InsideString); + m_SB.AddNumber(n); +} + +void VmaJsonWriter::ContinueString_Pointer(const void* ptr) +{ + VMA_ASSERT(m_InsideString); + m_SB.AddPointer(ptr); +} + +void VmaJsonWriter::EndString(const char* pStr) +{ + VMA_ASSERT(m_InsideString); + if (pStr != VMA_NULL && pStr[0] != '\0') + { + ContinueString(pStr); + } + m_SB.Add('"'); + m_InsideString = false; +} + +void VmaJsonWriter::WriteNumber(uint32_t n) +{ + VMA_ASSERT(!m_InsideString); + BeginValue(false); + m_SB.AddNumber(n); +} + +void VmaJsonWriter::WriteNumber(uint64_t n) +{ + VMA_ASSERT(!m_InsideString); + BeginValue(false); + m_SB.AddNumber(n); +} + +void VmaJsonWriter::WriteBool(bool b) +{ + VMA_ASSERT(!m_InsideString); + BeginValue(false); + m_SB.Add(b ? "true" : "false"); +} + +void VmaJsonWriter::WriteNull() +{ + VMA_ASSERT(!m_InsideString); + BeginValue(false); + m_SB.Add("null"); +} + +void VmaJsonWriter::BeginValue(bool isString) +{ + if (!m_Stack.empty()) + { + StackItem& currItem = m_Stack.back(); + if (currItem.type == COLLECTION_TYPE_OBJECT && + currItem.valueCount % 2 == 0) + { + VMA_ASSERT(isString); + } + + if (currItem.type == COLLECTION_TYPE_OBJECT && + currItem.valueCount % 2 != 0) + { + m_SB.Add(": "); + } + else if (currItem.valueCount > 0) + { + m_SB.Add(", "); + WriteIndent(); + } + else + { + WriteIndent(); + } + ++currItem.valueCount; + } +} + +void VmaJsonWriter::WriteIndent(bool oneLess) +{ + if (!m_Stack.empty() && !m_Stack.back().singleLineMode) + { + m_SB.AddNewLine(); + + size_t count = m_Stack.size(); + if (count > 0 && oneLess) + { + --count; + } + for (size_t i = 0; i < count; ++i) + { + m_SB.Add(INDENT); + } + } +} +#endif // _VMA_JSON_WRITER_FUNCTIONS + +static void VmaPrintDetailedStatistics(VmaJsonWriter& json, const VmaDetailedStatistics& stat) +{ + json.BeginObject(); + + json.WriteString("BlockCount"); + json.WriteNumber(stat.statistics.blockCount); + json.WriteString("BlockBytes"); + json.WriteNumber(stat.statistics.blockBytes); + json.WriteString("AllocationCount"); + json.WriteNumber(stat.statistics.allocationCount); + json.WriteString("AllocationBytes"); + json.WriteNumber(stat.statistics.allocationBytes); + json.WriteString("UnusedRangeCount"); + json.WriteNumber(stat.unusedRangeCount); + + if (stat.statistics.allocationCount > 1) + { + json.WriteString("AllocationSizeMin"); + json.WriteNumber(stat.allocationSizeMin); + json.WriteString("AllocationSizeMax"); + json.WriteNumber(stat.allocationSizeMax); + } + if (stat.unusedRangeCount > 1) + { + json.WriteString("UnusedRangeSizeMin"); + json.WriteNumber(stat.unusedRangeSizeMin); + json.WriteString("UnusedRangeSizeMax"); + json.WriteNumber(stat.unusedRangeSizeMax); + } + json.EndObject(); +} +#endif // _VMA_JSON_WRITER + +#ifndef _VMA_MAPPING_HYSTERESIS + +class VmaMappingHysteresis +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaMappingHysteresis) +public: + VmaMappingHysteresis() = default; + + uint32_t GetExtraMapping() const { return m_ExtraMapping; } + + // Call when Map was called. + // Returns true if switched to extra +1 mapping reference count. + bool PostMap() + { +#if VMA_MAPPING_HYSTERESIS_ENABLED + if(m_ExtraMapping == 0) + { + ++m_MajorCounter; + if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING) + { + m_ExtraMapping = 1; + m_MajorCounter = 0; + m_MinorCounter = 0; + return true; + } + } + else // m_ExtraMapping == 1 + PostMinorCounter(); +#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED + return false; + } + + // Call when Unmap was called. + void PostUnmap() + { +#if VMA_MAPPING_HYSTERESIS_ENABLED + if(m_ExtraMapping == 0) + ++m_MajorCounter; + else // m_ExtraMapping == 1 + PostMinorCounter(); +#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED + } + + // Call when allocation was made from the memory block. + void PostAlloc() + { +#if VMA_MAPPING_HYSTERESIS_ENABLED + if(m_ExtraMapping == 1) + ++m_MajorCounter; + else // m_ExtraMapping == 0 + PostMinorCounter(); +#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED + } + + // Call when allocation was freed from the memory block. + // Returns true if switched to extra -1 mapping reference count. + bool PostFree() + { +#if VMA_MAPPING_HYSTERESIS_ENABLED + if(m_ExtraMapping == 1) + { + ++m_MajorCounter; + if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING && + m_MajorCounter > m_MinorCounter + 1) + { + m_ExtraMapping = 0; + m_MajorCounter = 0; + m_MinorCounter = 0; + return true; + } + } + else // m_ExtraMapping == 0 + PostMinorCounter(); +#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED + return false; + } + +private: + static const int32_t COUNTER_MIN_EXTRA_MAPPING = 7; + + uint32_t m_MinorCounter = 0; + uint32_t m_MajorCounter = 0; + uint32_t m_ExtraMapping = 0; // 0 or 1. + + void PostMinorCounter() + { + if(m_MinorCounter < m_MajorCounter) + { + ++m_MinorCounter; + } + else if(m_MajorCounter > 0) + { + --m_MajorCounter; + --m_MinorCounter; + } + } +}; + +#endif // _VMA_MAPPING_HYSTERESIS + +#if VMA_EXTERNAL_MEMORY_WIN32 +class VmaWin32Handle +{ +public: + VmaWin32Handle() noexcept : m_hHandle(VMA_NULL) { } + explicit VmaWin32Handle(HANDLE hHandle) noexcept : m_hHandle(hHandle) { } + ~VmaWin32Handle() noexcept { if (m_hHandle != VMA_NULL) { ::CloseHandle(m_hHandle); } } + VMA_CLASS_NO_COPY_NO_MOVE(VmaWin32Handle) + +public: + // Strengthened + VkResult GetHandle(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, bool useMutex, HANDLE* pHandle) noexcept + { + *pHandle = VMA_NULL; + // Try to get handle first. + if (m_hHandle != VMA_NULL) + { + *pHandle = Duplicate(hTargetProcess); + return VK_SUCCESS; + } + + VkResult res = VK_SUCCESS; + // If failed, try to create it. + { + VmaMutexLockWrite lock(m_Mutex, useMutex); + if (m_hHandle == VMA_NULL) + { + res = Create(device, memory, pvkGetMemoryWin32HandleKHR, &m_hHandle); + } + } + + *pHandle = Duplicate(hTargetProcess); + return res; + } + + operator bool() const noexcept { return m_hHandle != VMA_NULL; } +private: + // Not atomic + static VkResult Create(VkDevice device, VkDeviceMemory memory, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE* pHandle) noexcept + { + VkResult res = VK_ERROR_FEATURE_NOT_PRESENT; + if (pvkGetMemoryWin32HandleKHR != VMA_NULL) + { + VkMemoryGetWin32HandleInfoKHR handleInfo{ }; + handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR; + handleInfo.memory = memory; + handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR; + res = pvkGetMemoryWin32HandleKHR(device, &handleInfo, pHandle); + } + return res; + } + HANDLE Duplicate(HANDLE hTargetProcess = VMA_NULL) const noexcept + { + if (!m_hHandle) + return m_hHandle; + + HANDLE hCurrentProcess = ::GetCurrentProcess(); + HANDLE hDupHandle = VMA_NULL; + if (!::DuplicateHandle(hCurrentProcess, m_hHandle, hTargetProcess ? hTargetProcess : hCurrentProcess, &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + VMA_ASSERT(0 && "Failed to duplicate handle."); + } + return hDupHandle; + } +private: + HANDLE m_hHandle; + VMA_RW_MUTEX m_Mutex; // Protects access m_Handle +}; +#else +class VmaWin32Handle +{ + // ABI compatibility + void* placeholder = VMA_NULL; + VMA_RW_MUTEX placeholder2; +}; +#endif // VMA_EXTERNAL_MEMORY_WIN32 + + +#ifndef _VMA_DEVICE_MEMORY_BLOCK +/* +Represents a single block of device memory (`VkDeviceMemory`) with all the +data about its regions (aka suballocations, #VmaAllocation), assigned and free. + +Thread-safety: +- Access to m_pMetadata must be externally synchronized. +- Map, Unmap, Bind* are synchronized internally. +*/ +class VmaDeviceMemoryBlock +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaDeviceMemoryBlock) +public: + VmaBlockMetadata* m_pMetadata; + + explicit VmaDeviceMemoryBlock(VmaAllocator hAllocator); + ~VmaDeviceMemoryBlock(); + + // Always call after construction. + void Init( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t newMemoryTypeIndex, + VkDeviceMemory newMemory, + VkDeviceSize newSize, + uint32_t id, + uint32_t algorithm, + VkDeviceSize bufferImageGranularity); + // Always call before destruction. + void Destroy(VmaAllocator allocator); + + VmaPool GetParentPool() const { return m_hParentPool; } + VkDeviceMemory GetDeviceMemory() const { return m_hMemory; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + uint32_t GetId() const { return m_Id; } + void* GetMappedData() const { return m_pMappedData; } + uint32_t GetMapRefCount() const { return m_MapCount; } + + // Call when allocation/free was made from m_pMetadata. + // Used for m_MappingHysteresis. + void PostAlloc(VmaAllocator hAllocator); + void PostFree(VmaAllocator hAllocator); + + // Validates all data structures inside this object. If not valid, returns false. + bool Validate() const; + VkResult CheckCorruption(VmaAllocator hAllocator); + + // ppData can be null. + VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData); + void Unmap(VmaAllocator hAllocator, uint32_t count); + + VkResult WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize); + VkResult ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize); + + VkResult BindBufferMemory( + VmaAllocator hAllocator, + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext); + VkResult BindImageMemory( + VmaAllocator hAllocator, + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext); +#if VMA_EXTERNAL_MEMORY_WIN32 + VkResult CreateWin32Handle( + const VmaAllocator hAllocator, + PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, + HANDLE hTargetProcess, + HANDLE* pHandle)noexcept; +#endif // VMA_EXTERNAL_MEMORY_WIN32 +private: + VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool. + uint32_t m_MemoryTypeIndex; + uint32_t m_Id; + VkDeviceMemory m_hMemory; + + /* + Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory. + Also protects m_MapCount, m_pMappedData. + Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex. + */ + VMA_MUTEX m_MapAndBindMutex; + VmaMappingHysteresis m_MappingHysteresis; + uint32_t m_MapCount; + void* m_pMappedData; + + VmaWin32Handle m_Handle; +}; +#endif // _VMA_DEVICE_MEMORY_BLOCK + +#ifndef _VMA_ALLOCATION_T +struct VmaAllocationExtraData +{ + void* m_pMappedData = VMA_NULL; // Not null means memory is mapped. + VmaWin32Handle m_Handle; +}; + +struct VmaAllocation_T +{ + friend struct VmaDedicatedAllocationListItemTraits; + + enum FLAGS + { + FLAG_PERSISTENT_MAP = 0x01, + FLAG_MAPPING_ALLOWED = 0x02, + }; + +public: + enum ALLOCATION_TYPE + { + ALLOCATION_TYPE_NONE, + ALLOCATION_TYPE_BLOCK, + ALLOCATION_TYPE_DEDICATED, + }; + + // This struct is allocated using VmaPoolAllocator. + explicit VmaAllocation_T(bool mappingAllowed); + ~VmaAllocation_T(); + + void InitBlockAllocation( + VmaDeviceMemoryBlock* block, + VmaAllocHandle allocHandle, + VkDeviceSize alignment, + VkDeviceSize size, + uint32_t memoryTypeIndex, + VmaSuballocationType suballocationType, + bool mapped); + // pMappedData not null means allocation is created with MAPPED flag. + void InitDedicatedAllocation( + VmaAllocator allocator, + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceMemory hMemory, + VmaSuballocationType suballocationType, + void* pMappedData, + VkDeviceSize size); + void Destroy(VmaAllocator allocator); + + ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; } + VkDeviceSize GetAlignment() const { return m_Alignment; } + VkDeviceSize GetSize() const { return m_Size; } + void* GetUserData() const { return m_pUserData; } + const char* GetName() const { return m_pName; } + VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; } + + VmaDeviceMemoryBlock* GetBlock() const { VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); return m_BlockAllocation.m_Block; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + bool IsPersistentMap() const { return (m_Flags & FLAG_PERSISTENT_MAP) != 0; } + bool IsMappingAllowed() const { return (m_Flags & FLAG_MAPPING_ALLOWED) != 0; } + + void SetUserData(VmaAllocator hAllocator, void* pUserData) { m_pUserData = pUserData; } + void SetName(VmaAllocator hAllocator, const char* pName); + void FreeName(VmaAllocator hAllocator); + uint8_t SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation); + VmaAllocHandle GetAllocHandle() const; + VkDeviceSize GetOffset() const; + VmaPool GetParentPool() const; + VkDeviceMemory GetMemory() const; + void* GetMappedData() const; + + void BlockAllocMap(); + void BlockAllocUnmap(); + VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData); + void DedicatedAllocUnmap(VmaAllocator hAllocator); + +#if VMA_STATS_STRING_ENABLED + VmaBufferImageUsage GetBufferImageUsage() const { return m_BufferImageUsage; } + void InitBufferUsage(const VkBufferCreateInfo &createInfo, bool useKhrMaintenance5) + { + VMA_ASSERT(m_BufferImageUsage == VmaBufferImageUsage::UNKNOWN); + m_BufferImageUsage = VmaBufferImageUsage(createInfo, useKhrMaintenance5); + } + void InitImageUsage(const VkImageCreateInfo &createInfo) + { + VMA_ASSERT(m_BufferImageUsage == VmaBufferImageUsage::UNKNOWN); + m_BufferImageUsage = VmaBufferImageUsage(createInfo); + } + void PrintParameters(class VmaJsonWriter& json) const; +#endif + +#if VMA_EXTERNAL_MEMORY_WIN32 + VkResult GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* hHandle) noexcept; +#endif // VMA_EXTERNAL_MEMORY_WIN32 + +private: + // Allocation out of VmaDeviceMemoryBlock. + struct BlockAllocation + { + VmaDeviceMemoryBlock* m_Block; + VmaAllocHandle m_AllocHandle; + }; + // Allocation for an object that has its own private VkDeviceMemory. + struct DedicatedAllocation + { + VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool. + VkDeviceMemory m_hMemory; + VmaAllocationExtraData* m_ExtraData; + VmaAllocation_T* m_Prev; + VmaAllocation_T* m_Next; + }; + union + { + // Allocation out of VmaDeviceMemoryBlock. + BlockAllocation m_BlockAllocation; + // Allocation for an object that has its own private VkDeviceMemory. + DedicatedAllocation m_DedicatedAllocation; + }; + + VkDeviceSize m_Alignment; + VkDeviceSize m_Size; + void* m_pUserData; + char* m_pName; + uint32_t m_MemoryTypeIndex; + uint8_t m_Type; // ALLOCATION_TYPE + uint8_t m_SuballocationType; // VmaSuballocationType + // Reference counter for vmaMapMemory()/vmaUnmapMemory(). + uint8_t m_MapCount; + uint8_t m_Flags; // enum FLAGS +#if VMA_STATS_STRING_ENABLED + VmaBufferImageUsage m_BufferImageUsage; // 0 if unknown. +#endif + + void EnsureExtraData(VmaAllocator hAllocator); +}; +#endif // _VMA_ALLOCATION_T + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS +struct VmaDedicatedAllocationListItemTraits +{ + typedef VmaAllocation_T ItemType; + + static ItemType* GetPrev(const ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Prev; + } + static ItemType* GetNext(const ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Next; + } + static ItemType*& AccessPrev(ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Prev; + } + static ItemType*& AccessNext(ItemType* item) + { + VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + return item->m_DedicatedAllocation.m_Next; + } +}; +#endif // _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST +/* +Stores linked list of VmaAllocation_T objects. +Thread-safe, synchronized internally. +*/ +class VmaDedicatedAllocationList +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaDedicatedAllocationList) +public: + VmaDedicatedAllocationList() = default; + ~VmaDedicatedAllocationList(); + + void Init(bool useMutex) { m_UseMutex = useMutex; } + bool Validate(); + + void AddDetailedStatistics(VmaDetailedStatistics& inoutStats); + void AddStatistics(VmaStatistics& inoutStats); +#if VMA_STATS_STRING_ENABLED + // Writes JSON array with the list of allocations. + void BuildStatsString(VmaJsonWriter& json); +#endif + + bool IsEmpty(); + void Register(VmaAllocation alloc); + void Unregister(VmaAllocation alloc); + +private: + typedef VmaIntrusiveLinkedList DedicatedAllocationLinkedList; + + bool m_UseMutex = true; + VMA_RW_MUTEX m_Mutex; + DedicatedAllocationLinkedList m_AllocationList; +}; + +#ifndef _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS + +VmaDedicatedAllocationList::~VmaDedicatedAllocationList() +{ + VMA_HEAVY_ASSERT(Validate()); + + if (!m_AllocationList.IsEmpty()) + { + VMA_ASSERT_LEAK(false && "Unfreed dedicated allocations found!"); + } +} + +bool VmaDedicatedAllocationList::Validate() +{ + const size_t declaredCount = m_AllocationList.GetCount(); + size_t actualCount = 0; + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + for (VmaAllocation alloc = m_AllocationList.Front(); + alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc)) + { + ++actualCount; + } + VMA_VALIDATE(actualCount == declaredCount); + + return true; +} + +void VmaDedicatedAllocationList::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) +{ + for(auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) + { + const VkDeviceSize size = item->GetSize(); + inoutStats.statistics.blockCount++; + inoutStats.statistics.blockBytes += size; + VmaAddDetailedStatisticsAllocation(inoutStats, item->GetSize()); + } +} + +void VmaDedicatedAllocationList::AddStatistics(VmaStatistics& inoutStats) +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + + const uint32_t allocCount = (uint32_t)m_AllocationList.GetCount(); + inoutStats.blockCount += allocCount; + inoutStats.allocationCount += allocCount; + + for(auto* item = m_AllocationList.Front(); item != VMA_NULL; item = DedicatedAllocationLinkedList::GetNext(item)) + { + const VkDeviceSize size = item->GetSize(); + inoutStats.blockBytes += size; + inoutStats.allocationBytes += size; + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaDedicatedAllocationList::BuildStatsString(VmaJsonWriter& json) +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + json.BeginArray(); + for (VmaAllocation alloc = m_AllocationList.Front(); + alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc)) + { + json.BeginObject(true); + alloc->PrintParameters(json); + json.EndObject(); + } + json.EndArray(); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaDedicatedAllocationList::IsEmpty() +{ + VmaMutexLockRead lock(m_Mutex, m_UseMutex); + return m_AllocationList.IsEmpty(); +} + +void VmaDedicatedAllocationList::Register(VmaAllocation alloc) +{ + VmaMutexLockWrite lock(m_Mutex, m_UseMutex); + m_AllocationList.PushBack(alloc); +} + +void VmaDedicatedAllocationList::Unregister(VmaAllocation alloc) +{ + VmaMutexLockWrite lock(m_Mutex, m_UseMutex); + m_AllocationList.Remove(alloc); +} +#endif // _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS +#endif // _VMA_DEDICATED_ALLOCATION_LIST + +#ifndef _VMA_SUBALLOCATION +/* +Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as +allocated memory block or free. +*/ +struct VmaSuballocation +{ + VkDeviceSize offset; + VkDeviceSize size; + void* userData; + VmaSuballocationType type; +}; + +// Comparator for offsets. +struct VmaSuballocationOffsetLess +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset < rhs.offset; + } +}; + +struct VmaSuballocationOffsetGreater +{ + bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const + { + return lhs.offset > rhs.offset; + } +}; + +struct VmaSuballocationItemSizeLess +{ + bool operator()(const VmaSuballocationList::iterator lhs, + const VmaSuballocationList::iterator rhs) const + { + return lhs->size < rhs->size; + } + + bool operator()(const VmaSuballocationList::iterator lhs, + VkDeviceSize rhsSize) const + { + return lhs->size < rhsSize; + } +}; +#endif // _VMA_SUBALLOCATION + +#ifndef _VMA_ALLOCATION_REQUEST +/* +Parameters of planned allocation inside a VmaDeviceMemoryBlock. +item points to a FREE suballocation. +*/ +struct VmaAllocationRequest +{ + VmaAllocHandle allocHandle; + VkDeviceSize size; + VmaSuballocationList::iterator item; + void* customData; + uint64_t algorithmData; + VmaAllocationRequestType type; +}; +#endif // _VMA_ALLOCATION_REQUEST + +#ifndef _VMA_BLOCK_METADATA +/* +Data structure used for bookkeeping of allocations and unused ranges of memory +in a single VkDeviceMemory block. +*/ +class VmaBlockMetadata +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata) +public: + // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object. + VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + virtual ~VmaBlockMetadata() = default; + + virtual void Init(VkDeviceSize size) { m_Size = size; } + bool IsVirtual() const { return m_IsVirtual; } + VkDeviceSize GetSize() const { return m_Size; } + + // Validates all data structures inside this object. If not valid, returns false. + virtual bool Validate() const = 0; + virtual size_t GetAllocationCount() const = 0; + virtual size_t GetFreeRegionsCount() const = 0; + virtual VkDeviceSize GetSumFreeSize() const = 0; + // Returns true if this block is empty - contains only single free suballocation. + virtual bool IsEmpty() const = 0; + virtual void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) = 0; + virtual VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const = 0; + virtual void* GetAllocationUserData(VmaAllocHandle allocHandle) const = 0; + + virtual VmaAllocHandle GetAllocationListBegin() const = 0; + virtual VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const = 0; + virtual VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const = 0; + + // Shouldn't modify blockCount. + virtual void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const = 0; + virtual void AddStatistics(VmaStatistics& inoutStats) const = 0; + +#if VMA_STATS_STRING_ENABLED + virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0; +#endif + + // Tries to find a place for suballocation with given parameters inside this block. + // If succeeded, fills pAllocationRequest and returns true. + // If failed, returns false. + virtual bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags. + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) = 0; + + virtual VkResult CheckCorruption(const void* pBlockData) = 0; + + // Makes actual allocation based on request. Request must already be checked and valid. + virtual void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) = 0; + + // Frees suballocation assigned to given memory region. + virtual void Free(VmaAllocHandle allocHandle) = 0; + + // Frees all allocations. + // Careful! Don't call it if there are VmaAllocation objects owned by userData of cleared allocations! + virtual void Clear() = 0; + + virtual void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) = 0; + virtual void DebugLogAllAllocations() const = 0; + +protected: + const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; } + VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } + VkDeviceSize GetDebugMargin() const { return VkDeviceSize(IsVirtual() ? 0 : VMA_DEBUG_MARGIN); } + + void DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const; +#if VMA_STATS_STRING_ENABLED + // mapRefCount == UINT32_MAX means unspecified. + void PrintDetailedMap_Begin(class VmaJsonWriter& json, + VkDeviceSize unusedBytes, + size_t allocationCount, + size_t unusedRangeCount) const; + void PrintDetailedMap_Allocation(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size, void* userData) const; + static void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json, + VkDeviceSize offset, + VkDeviceSize size); + static void PrintDetailedMap_End(class VmaJsonWriter& json); +#endif + +private: + VkDeviceSize m_Size; + const VkAllocationCallbacks* m_pAllocationCallbacks; + const VkDeviceSize m_BufferImageGranularity; + const bool m_IsVirtual; +}; + +#ifndef _VMA_BLOCK_METADATA_FUNCTIONS +VmaBlockMetadata::VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : m_Size(0), + m_pAllocationCallbacks(pAllocationCallbacks), + m_BufferImageGranularity(bufferImageGranularity), + m_IsVirtual(isVirtual) {} + +void VmaBlockMetadata::DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const +{ + if (IsVirtual()) + { + VMA_LEAK_LOG_FORMAT("UNFREED VIRTUAL ALLOCATION; Offset: %" PRIu64 "; Size: %" PRIu64 "; UserData: %p", offset, size, userData); + } + else + { + VMA_ASSERT(userData != VMA_NULL); + VmaAllocation allocation = reinterpret_cast(userData); + + userData = allocation->GetUserData(); + const char* name = allocation->GetName(); + +#if VMA_STATS_STRING_ENABLED + VMA_LEAK_LOG_FORMAT("UNFREED ALLOCATION; Offset: %" PRIu64 "; Size: %" PRIu64 "; UserData: %p; Name: %s; Type: %s; Usage: %" PRIu64, + offset, size, userData, name ? name : "vma_empty", + VMA_SUBALLOCATION_TYPE_NAMES[allocation->GetSuballocationType()], + (uint64_t)allocation->GetBufferImageUsage().Value); +#else + VMA_LEAK_LOG_FORMAT("UNFREED ALLOCATION; Offset: %" PRIu64 "; Size: %" PRIu64 "; UserData: %p; Name: %s; Type: %u", + offset, size, userData, name ? name : "vma_empty", + (unsigned)allocation->GetSuballocationType()); +#endif // VMA_STATS_STRING_ENABLED + } + +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json, + VkDeviceSize unusedBytes, size_t allocationCount, size_t unusedRangeCount) const +{ + json.WriteString("TotalBytes"); + json.WriteNumber(GetSize()); + + json.WriteString("UnusedBytes"); + json.WriteNumber(unusedBytes); + + json.WriteString("Allocations"); + json.WriteNumber((uint64_t)allocationCount); + + json.WriteString("UnusedRanges"); + json.WriteNumber((uint64_t)unusedRangeCount); + + json.WriteString("Suballocations"); + json.BeginArray(); +} + +void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size, void* userData) const +{ + json.BeginObject(true); + + json.WriteString("Offset"); + json.WriteNumber(offset); + + if (IsVirtual()) + { + json.WriteString("Size"); + json.WriteNumber(size); + if (userData) + { + json.WriteString("CustomData"); + json.BeginString(); + json.ContinueString_Pointer(userData); + json.EndString(); + } + } + else + { + ((VmaAllocation)userData)->PrintParameters(json); + } + + json.EndObject(); +} + +void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json, + VkDeviceSize offset, VkDeviceSize size) +{ + json.BeginObject(true); + + json.WriteString("Offset"); + json.WriteNumber(offset); + + json.WriteString("Type"); + json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]); + + json.WriteString("Size"); + json.WriteNumber(size); + + json.EndObject(); +} + +void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) +{ + json.EndArray(); +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_BLOCK_METADATA_FUNCTIONS +#endif // _VMA_BLOCK_METADATA + +#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY +// Before deleting object of this class remember to call 'Destroy()' +class VmaBlockBufferImageGranularity final +{ +public: + struct ValidationContext + { + const VkAllocationCallbacks* allocCallbacks; + uint16_t* pageAllocs; + }; + + explicit VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity); + ~VmaBlockBufferImageGranularity(); + + bool IsEnabled() const { return m_BufferImageGranularity > MAX_LOW_BUFFER_IMAGE_GRANULARITY; } + + void Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size); + // Before destroying object you must call free it's memory + void Destroy(const VkAllocationCallbacks* pAllocationCallbacks); + + void RoundupAllocRequest(VmaSuballocationType allocType, + VkDeviceSize& inOutAllocSize, + VkDeviceSize& inOutAllocAlignment) const; + + bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset, + VkDeviceSize allocSize, + VkDeviceSize blockOffset, + VkDeviceSize blockSize, + VmaSuballocationType allocType) const; + + void AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size); + void FreePages(VkDeviceSize offset, VkDeviceSize size); + void Clear(); + + ValidationContext StartValidation(const VkAllocationCallbacks* pAllocationCallbacks, + bool isVirutal) const; + bool Validate(ValidationContext& ctx, VkDeviceSize offset, VkDeviceSize size) const; + bool FinishValidation(ValidationContext& ctx) const; + +private: + static const uint16_t MAX_LOW_BUFFER_IMAGE_GRANULARITY = 256; + + struct RegionInfo + { + uint8_t allocType; + uint16_t allocCount; + }; + + VkDeviceSize m_BufferImageGranularity; + uint32_t m_RegionCount; + RegionInfo* m_RegionInfo; + + uint32_t GetStartPage(VkDeviceSize offset) const { return OffsetToPageIndex(offset & ~(m_BufferImageGranularity - 1)); } + uint32_t GetEndPage(VkDeviceSize offset, VkDeviceSize size) const { return OffsetToPageIndex((offset + size - 1) & ~(m_BufferImageGranularity - 1)); } + + uint32_t OffsetToPageIndex(VkDeviceSize offset) const; + static void AllocPage(RegionInfo& page, uint8_t allocType); +}; + +#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS +VmaBlockBufferImageGranularity::VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity) + : m_BufferImageGranularity(bufferImageGranularity), + m_RegionCount(0), + m_RegionInfo(VMA_NULL) {} + +VmaBlockBufferImageGranularity::~VmaBlockBufferImageGranularity() +{ + VMA_ASSERT(m_RegionInfo == VMA_NULL && "Free not called before destroying object!"); +} + +void VmaBlockBufferImageGranularity::Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size) +{ + if (IsEnabled()) + { + m_RegionCount = static_cast(VmaDivideRoundingUp(size, m_BufferImageGranularity)); + m_RegionInfo = vma_new_array(pAllocationCallbacks, RegionInfo, m_RegionCount); + memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo)); + } +} + +void VmaBlockBufferImageGranularity::Destroy(const VkAllocationCallbacks* pAllocationCallbacks) +{ + if (m_RegionInfo) + { + vma_delete_array(pAllocationCallbacks, m_RegionInfo, m_RegionCount); + m_RegionInfo = VMA_NULL; + } +} + +void VmaBlockBufferImageGranularity::RoundupAllocRequest(VmaSuballocationType allocType, + VkDeviceSize& inOutAllocSize, + VkDeviceSize& inOutAllocAlignment) const +{ + if (m_BufferImageGranularity > 1 && + m_BufferImageGranularity <= MAX_LOW_BUFFER_IMAGE_GRANULARITY) + { + if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN || + allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL) + { + inOutAllocAlignment = VMA_MAX(inOutAllocAlignment, m_BufferImageGranularity); + inOutAllocSize = VmaAlignUp(inOutAllocSize, m_BufferImageGranularity); + } + } +} + +bool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset, + VkDeviceSize allocSize, + VkDeviceSize blockOffset, + VkDeviceSize blockSize, + VmaSuballocationType allocType) const +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(inOutAllocOffset); + if (m_RegionInfo[startPage].allocCount > 0 && + VmaIsBufferImageGranularityConflict(static_cast(m_RegionInfo[startPage].allocType), allocType)) + { + inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity); + if (blockSize < allocSize + inOutAllocOffset - blockOffset) + return true; + ++startPage; + } + uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize); + if (endPage != startPage && + m_RegionInfo[endPage].allocCount > 0 && + VmaIsBufferImageGranularityConflict(static_cast(m_RegionInfo[endPage].allocType), allocType)) + { + return true; + } + } + return false; +} + +void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size) +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(offset); + AllocPage(m_RegionInfo[startPage], allocType); + + uint32_t endPage = GetEndPage(offset, size); + if (startPage != endPage) + AllocPage(m_RegionInfo[endPage], allocType); + } +} + +void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size) +{ + if (IsEnabled()) + { + uint32_t startPage = GetStartPage(offset); + --m_RegionInfo[startPage].allocCount; + if (m_RegionInfo[startPage].allocCount == 0) + m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE; + uint32_t endPage = GetEndPage(offset, size); + if (startPage != endPage) + { + --m_RegionInfo[endPage].allocCount; + if (m_RegionInfo[endPage].allocCount == 0) + m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE; + } + } +} + +void VmaBlockBufferImageGranularity::Clear() +{ + if (m_RegionInfo) + memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo)); +} + +VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity::StartValidation( + const VkAllocationCallbacks* pAllocationCallbacks, bool isVirutal) const +{ + ValidationContext ctx{ pAllocationCallbacks, VMA_NULL }; + if (!isVirutal && IsEnabled()) + { + ctx.pageAllocs = vma_new_array(pAllocationCallbacks, uint16_t, m_RegionCount); + memset(ctx.pageAllocs, 0, m_RegionCount * sizeof(uint16_t)); + } + return ctx; +} + +bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx, + VkDeviceSize offset, VkDeviceSize size) const +{ + if (IsEnabled()) + { + uint32_t start = GetStartPage(offset); + ++ctx.pageAllocs[start]; + VMA_VALIDATE(m_RegionInfo[start].allocCount > 0); + + uint32_t end = GetEndPage(offset, size); + if (start != end) + { + ++ctx.pageAllocs[end]; + VMA_VALIDATE(m_RegionInfo[end].allocCount > 0); + } + } + return true; +} + +bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const +{ + // Check proper page structure + if (IsEnabled()) + { + VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!"); + + for (uint32_t page = 0; page < m_RegionCount; ++page) + { + VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount); + } + vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount); + ctx.pageAllocs = VMA_NULL; + } + return true; +} + +uint32_t VmaBlockBufferImageGranularity::OffsetToPageIndex(VkDeviceSize offset) const +{ + return static_cast(offset >> VMA_BITSCAN_MSB(m_BufferImageGranularity)); +} + +void VmaBlockBufferImageGranularity::AllocPage(RegionInfo& page, uint8_t allocType) +{ + // When current alloc type is free then it can be overridden by new type + if (page.allocCount == 0 || (page.allocCount > 0 && page.allocType == VMA_SUBALLOCATION_TYPE_FREE)) + page.allocType = allocType; + + ++page.allocCount; +} +#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS +#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY + +#ifndef _VMA_BLOCK_METADATA_LINEAR +/* +Allocations and their references in internal data structure look like this: + +if(m_2ndVectorMode == SECOND_VECTOR_EMPTY): + + 0 +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | + | | + | | +GetSize() +-------+ + +if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER): + + 0 +-------+ + | Alloc | 2nd[0] + +-------+ + | Alloc | 2nd[1] + +-------+ + | ... | + +-------+ + | Alloc | 2nd[2nd.size() - 1] + +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | +GetSize() +-------+ + +if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK): + + 0 +-------+ + | | + | | + | | + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount] + +-------+ + | Alloc | 1st[m_1stNullItemsBeginCount + 1] + +-------+ + | ... | + +-------+ + | Alloc | 1st[1st.size() - 1] + +-------+ + | | + | | + | | + +-------+ + | Alloc | 2nd[2nd.size() - 1] + +-------+ + | ... | + +-------+ + | Alloc | 2nd[1] + +-------+ + | Alloc | 2nd[0] +GetSize() +-------+ + +*/ +class VmaBlockMetadata_Linear : public VmaBlockMetadata +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_Linear) +public: + VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + ~VmaBlockMetadata_Linear() override = default; + + VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; } + bool IsEmpty() const override { return GetAllocationCount() == 0; } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; } + + void Init(VkDeviceSize size) override; + bool Validate() const override; + size_t GetAllocationCount() const override; + size_t GetFreeRegionsCount() const override; + + void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override; + void AddStatistics(VmaStatistics& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + VkResult CheckCorruption(const void* pBlockData) override; + + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void Free(VmaAllocHandle allocHandle) override; + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void* GetAllocationUserData(VmaAllocHandle allocHandle) const override; + VmaAllocHandle GetAllocationListBegin() const override; + VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override; + VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + void DebugLogAllAllocations() const override; + +private: + /* + There are two suballocation vectors, used in ping-pong way. + The one with index m_1stVectorIndex is called 1st. + The one with index (m_1stVectorIndex ^ 1) is called 2nd. + 2nd can be non-empty only when 1st is not empty. + When 2nd is not empty, m_2ndVectorMode indicates its mode of operation. + */ + typedef VmaVector> SuballocationVectorType; + + enum SECOND_VECTOR_MODE + { + SECOND_VECTOR_EMPTY, + /* + Suballocations in 2nd vector are created later than the ones in 1st, but they + all have smaller offset. + */ + SECOND_VECTOR_RING_BUFFER, + /* + Suballocations in 2nd vector are upper side of double stack. + They all have offsets higher than those in 1st vector. + Top of this stack means smaller offsets, but higher indices in this vector. + */ + SECOND_VECTOR_DOUBLE_STACK, + }; + + VkDeviceSize m_SumFreeSize; + SuballocationVectorType m_Suballocations0, m_Suballocations1; + uint32_t m_1stVectorIndex; + SECOND_VECTOR_MODE m_2ndVectorMode; + // Number of items in 1st vector with hAllocation = null at the beginning. + size_t m_1stNullItemsBeginCount; + // Number of other items in 1st vector with hAllocation = null somewhere in the middle. + size_t m_1stNullItemsMiddleCount; + // Number of items in 2nd vector with hAllocation = null. + size_t m_2ndNullItemsCount; + + SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; } + SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; } + const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; } + const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; } + + VmaSuballocation& FindSuballocation(VkDeviceSize offset) const; + bool ShouldCompact1st() const; + void CleanupAfterFree(); + + bool CreateAllocationRequest_LowerAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest); + bool CreateAllocationRequest_UpperAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest); +}; + +#ifndef _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS +VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_SumFreeSize(0), + m_Suballocations0(VmaStlAllocator(pAllocationCallbacks)), + m_Suballocations1(VmaStlAllocator(pAllocationCallbacks)), + m_1stVectorIndex(0), + m_2ndVectorMode(SECOND_VECTOR_EMPTY), + m_1stNullItemsBeginCount(0), + m_1stNullItemsMiddleCount(0), + m_2ndNullItemsCount(0) {} + +void VmaBlockMetadata_Linear::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + m_SumFreeSize = size; +} + +bool VmaBlockMetadata_Linear::Validate() const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY)); + VMA_VALIDATE(!suballocations1st.empty() || + suballocations2nd.empty() || + m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER); + + if (!suballocations1st.empty()) + { + // Null item at the beginning should be accounted into m_1stNullItemsBeginCount. + VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].type != VMA_SUBALLOCATION_TYPE_FREE); + // Null item at the end should be just pop_back(). + VMA_VALIDATE(suballocations1st.back().type != VMA_SUBALLOCATION_TYPE_FREE); + } + if (!suballocations2nd.empty()) + { + // Null item at the end should be just pop_back(). + VMA_VALIDATE(suballocations2nd.back().type != VMA_SUBALLOCATION_TYPE_FREE); + } + + VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size()); + VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size()); + + VkDeviceSize sumUsedSize = 0; + const size_t suballoc1stCount = suballocations1st.size(); + const VkDeviceSize debugMargin = GetDebugMargin(); + VkDeviceSize offset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const size_t suballoc2ndCount = suballocations2nd.size(); + size_t nullItem2ndCount = 0; + for (size_t i = 0; i < suballoc2ndCount; ++i) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem2ndCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + + VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount); + } + + for (size_t i = 0; i < m_1stNullItemsBeginCount; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE && + suballoc.userData == VMA_NULL); + } + + size_t nullItem1stCount = m_1stNullItemsBeginCount; + + for (size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem1stCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount); + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + const size_t suballoc2ndCount = suballocations2nd.size(); + size_t nullItem2ndCount = 0; + for (size_t i = suballoc2ndCount; i--; ) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE); + + VmaAllocation const alloc = (VmaAllocation)suballoc.userData; + if (!IsVirtual()) + { + VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE)); + } + VMA_VALIDATE(suballoc.offset >= offset); + + if (!currFree) + { + if (!IsVirtual()) + { + VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1); + VMA_VALIDATE(alloc->GetSize() == suballoc.size); + } + sumUsedSize += suballoc.size; + } + else + { + ++nullItem2ndCount; + } + + offset = suballoc.offset + suballoc.size + debugMargin; + } + + VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount); + } + + VMA_VALIDATE(offset <= GetSize()); + VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize); + + return true; +} + +size_t VmaBlockMetadata_Linear::GetAllocationCount() const +{ + return AccessSuballocations1st().size() - m_1stNullItemsBeginCount - m_1stNullItemsMiddleCount + + AccessSuballocations2nd().size() - m_2ndNullItemsCount; +} + +size_t VmaBlockMetadata_Linear::GetFreeRegionsCount() const +{ + // Function only used for defragmentation, which is disabled for this algorithm + VMA_ASSERT(0); + return SIZE_MAX; +} + +void VmaBlockMetadata_Linear::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const +{ + const VkDeviceSize size = GetSize(); + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + inoutStats.statistics.blockCount++; + inoutStats.statistics.blockBytes += size; + + VkDeviceSize lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + if (lastOffset < freeSpace2ndTo1stEnd) + { + const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + if (lastOffset < freeSpace1stTo2ndEnd) + { + const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + // There is free space from lastOffset to size. + if (lastOffset < size) + { + const VkDeviceSize unusedRangeSize = size - lastOffset; + VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize); + } + + // End of loop. + lastOffset = size; + } + } + } +} + +void VmaBlockMetadata_Linear::AddStatistics(VmaStatistics& inoutStats) const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const VkDeviceSize size = GetSize(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + inoutStats.blockCount++; + inoutStats.blockBytes += size; + inoutStats.allocationBytes += size - m_SumFreeSize; + + VkDeviceSize lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++inoutStats.allocationCount; + + // Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + // End of loop. + lastOffset = size; + } + } + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const +{ + const VkDeviceSize size = GetSize(); + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + const size_t suballoc1stCount = suballocations1st.size(); + const size_t suballoc2ndCount = suballocations2nd.size(); + + // FIRST PASS + + size_t unusedRangeCount = 0; + VkDeviceSize usedBytes = 0; + + VkDeviceSize lastOffset = 0; + + size_t alloc2ndCount = 0; + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc2ndCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace2ndTo1stEnd) + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + size_t nextAlloc1stIndex = m_1stNullItemsBeginCount; + size_t alloc1stCount = 0; + const VkDeviceSize freeSpace1stTo2ndEnd = + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc1stCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace1stTo2ndEnd) + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + ++unusedRangeCount; + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + ++alloc2ndCount; + usedBytes += suballoc.size; + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to size. + ++unusedRangeCount; + } + + // End of loop. + lastOffset = size; + } + } + } + + const VkDeviceSize unusedBytes = size - usedBytes; + PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount); + + // SECOND PASS + lastOffset = 0; + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset; + size_t nextAlloc2ndIndex = 0; + while (lastOffset < freeSpace2ndTo1stEnd) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex < suballoc2ndCount && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + ++nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex < suballoc2ndCount) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace2ndTo1stEnd) + { + // There is free space from lastOffset to freeSpace2ndTo1stEnd. + const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace2ndTo1stEnd; + } + } + } + + nextAlloc1stIndex = m_1stNullItemsBeginCount; + while (lastOffset < freeSpace1stTo2ndEnd) + { + // Find next non-null allocation or move nextAllocIndex to the end. + while (nextAlloc1stIndex < suballoc1stCount && + suballocations1st[nextAlloc1stIndex].userData == VMA_NULL) + { + ++nextAlloc1stIndex; + } + + // Found non-null allocation. + if (nextAlloc1stIndex < suballoc1stCount) + { + const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + ++nextAlloc1stIndex; + } + // We are at the end. + else + { + if (lastOffset < freeSpace1stTo2ndEnd) + { + // There is free space from lastOffset to freeSpace1stTo2ndEnd. + const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = freeSpace1stTo2ndEnd; + } + } + + if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + size_t nextAlloc2ndIndex = suballocations2nd.size() - 1; + while (lastOffset < size) + { + // Find next non-null allocation or move nextAlloc2ndIndex to the end. + while (nextAlloc2ndIndex != SIZE_MAX && + suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL) + { + --nextAlloc2ndIndex; + } + + // Found non-null allocation. + if (nextAlloc2ndIndex != SIZE_MAX) + { + const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex]; + + // 1. Process free space before this allocation. + if (lastOffset < suballoc.offset) + { + // There is free space from lastOffset to suballoc.offset. + const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // 2. Process this allocation. + // There is allocation with suballoc.offset, suballoc.size. + PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData); + + // 3. Prepare for next iteration. + lastOffset = suballoc.offset + suballoc.size; + --nextAlloc2ndIndex; + } + // We are at the end. + else + { + if (lastOffset < size) + { + // There is free space from lastOffset to size. + const VkDeviceSize unusedRangeSize = size - lastOffset; + PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize); + } + + // End of loop. + lastOffset = size; + } + } + } + + PrintDetailedMap_End(json); +} +#endif // VMA_STATS_STRING_ENABLED + +bool VmaBlockMetadata_Linear::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(allocSize > 0); + VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE); + VMA_ASSERT(pAllocationRequest != VMA_NULL); + VMA_HEAVY_ASSERT(Validate()); + + if(allocSize > GetSize()) + return false; + + pAllocationRequest->size = allocSize; + return upperAddress ? + CreateAllocationRequest_UpperAddress( + allocSize, allocAlignment, allocType, strategy, pAllocationRequest) : + CreateAllocationRequest_LowerAddress( + allocSize, allocAlignment, allocType, strategy, pAllocationRequest); +} + +VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData) +{ + VMA_ASSERT(!IsVirtual()); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + for (size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i) + { + const VmaSuballocation& suballoc = suballocations1st[i]; + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN_COPY; + } + } + } + + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + for (size_t i = 0, count = suballocations2nd.size(); i < count; ++i) + { + const VmaSuballocation& suballoc = suballocations2nd[i]; + if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE) + { + if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN_COPY; + } + } + } + + return VK_SUCCESS; +} + +void VmaBlockMetadata_Linear::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + const VkDeviceSize offset = (VkDeviceSize)request.allocHandle - 1; + const VmaSuballocation newSuballoc = { offset, request.size, userData, type }; + + switch (request.type) + { + case VmaAllocationRequestType::UpperAddress: + { + VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER && + "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer."); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + suballocations2nd.push_back(newSuballoc); + m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK; + } + break; + case VmaAllocationRequestType::EndOf1st: + { + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + + VMA_ASSERT(suballocations1st.empty() || + offset >= suballocations1st.back().offset + suballocations1st.back().size); + // Check if it fits before the end of the block. + VMA_ASSERT(offset + request.size <= GetSize()); + + suballocations1st.push_back(newSuballoc); + } + break; + case VmaAllocationRequestType::EndOf2nd: + { + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector. + VMA_ASSERT(!suballocations1st.empty() && + offset + request.size <= suballocations1st[m_1stNullItemsBeginCount].offset); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + switch (m_2ndVectorMode) + { + case SECOND_VECTOR_EMPTY: + // First allocation from second part ring buffer. + VMA_ASSERT(suballocations2nd.empty()); + m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER; + break; + case SECOND_VECTOR_RING_BUFFER: + // 2-part ring buffer is already started. + VMA_ASSERT(!suballocations2nd.empty()); + break; + case SECOND_VECTOR_DOUBLE_STACK: + VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack."); + break; + default: + VMA_ASSERT(0); + } + + suballocations2nd.push_back(newSuballoc); + } + break; + default: + VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR."); + } + + m_SumFreeSize -= newSuballoc.size; +} + +void VmaBlockMetadata_Linear::Free(VmaAllocHandle allocHandle) +{ + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + VkDeviceSize offset = (VkDeviceSize)allocHandle - 1; + + if (!suballocations1st.empty()) + { + // First allocation: Mark it as next empty at the beginning. + VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount]; + if (firstSuballoc.offset == offset) + { + firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE; + firstSuballoc.userData = VMA_NULL; + m_SumFreeSize += firstSuballoc.size; + ++m_1stNullItemsBeginCount; + CleanupAfterFree(); + return; + } + } + + // Last allocation in 2-part ring buffer or top of upper stack (same logic). + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER || + m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + VmaSuballocation& lastSuballoc = suballocations2nd.back(); + if (lastSuballoc.offset == offset) + { + m_SumFreeSize += lastSuballoc.size; + suballocations2nd.pop_back(); + CleanupAfterFree(); + return; + } + } + // Last allocation in 1st vector. + else if (m_2ndVectorMode == SECOND_VECTOR_EMPTY) + { + VmaSuballocation& lastSuballoc = suballocations1st.back(); + if (lastSuballoc.offset == offset) + { + m_SumFreeSize += lastSuballoc.size; + suballocations1st.pop_back(); + CleanupAfterFree(); + return; + } + } + + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + + // Item from the middle of 1st vector. + { + const SuballocationVectorType::iterator it = VmaBinaryFindSorted( + suballocations1st.begin() + m_1stNullItemsBeginCount, + suballocations1st.end(), + refSuballoc, + VmaSuballocationOffsetLess()); + if (it != suballocations1st.end()) + { + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->userData = VMA_NULL; + ++m_1stNullItemsMiddleCount; + m_SumFreeSize += it->size; + CleanupAfterFree(); + return; + } + } + + if (m_2ndVectorMode != SECOND_VECTOR_EMPTY) + { + // Item from the middle of 2nd vector. + const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ? + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) : + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater()); + if (it != suballocations2nd.end()) + { + it->type = VMA_SUBALLOCATION_TYPE_FREE; + it->userData = VMA_NULL; + ++m_2ndNullItemsCount; + m_SumFreeSize += it->size; + CleanupAfterFree(); + return; + } + } + + VMA_ASSERT(0 && "Allocation to free not found in linear allocator!"); +} + +void VmaBlockMetadata_Linear::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + outInfo.offset = (VkDeviceSize)allocHandle - 1; + VmaSuballocation& suballoc = FindSuballocation(outInfo.offset); + outInfo.size = suballoc.size; + outInfo.pUserData = suballoc.userData; +} + +void* VmaBlockMetadata_Linear::GetAllocationUserData(VmaAllocHandle allocHandle) const +{ + return FindSuballocation((VkDeviceSize)allocHandle - 1).userData; +} + +VmaAllocHandle VmaBlockMetadata_Linear::GetAllocationListBegin() const +{ + // Function only used for defragmentation, which is disabled for this algorithm + VMA_ASSERT(0); + return VK_NULL_HANDLE; +} + +VmaAllocHandle VmaBlockMetadata_Linear::GetNextAllocation(VmaAllocHandle prevAlloc) const +{ + // Function only used for defragmentation, which is disabled for this algorithm + VMA_ASSERT(0); + return VK_NULL_HANDLE; +} + +VkDeviceSize VmaBlockMetadata_Linear::GetNextFreeRegionSize(VmaAllocHandle alloc) const +{ + // Function only used for defragmentation, which is disabled for this algorithm + VMA_ASSERT(0); + return 0; +} + +void VmaBlockMetadata_Linear::Clear() +{ + m_SumFreeSize = GetSize(); + m_Suballocations0.clear(); + m_Suballocations1.clear(); + // Leaving m_1stVectorIndex unchanged - it doesn't matter. + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + m_2ndNullItemsCount = 0; +} + +void VmaBlockMetadata_Linear::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + VmaSuballocation& suballoc = FindSuballocation((VkDeviceSize)allocHandle - 1); + suballoc.userData = userData; +} + +void VmaBlockMetadata_Linear::DebugLogAllAllocations() const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + for (auto it = suballocations1st.begin() + m_1stNullItemsBeginCount; it != suballocations1st.end(); ++it) + if (it->type != VMA_SUBALLOCATION_TYPE_FREE) + DebugLogAllocation(it->offset, it->size, it->userData); + + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + for (auto it = suballocations2nd.begin(); it != suballocations2nd.end(); ++it) + if (it->type != VMA_SUBALLOCATION_TYPE_FREE) + DebugLogAllocation(it->offset, it->size, it->userData); +} + +VmaSuballocation& VmaBlockMetadata_Linear::FindSuballocation(VkDeviceSize offset) const +{ + const SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + VmaSuballocation refSuballoc; + refSuballoc.offset = offset; + // Rest of members stays uninitialized intentionally for better performance. + + // Item from the 1st vector. + { + SuballocationVectorType::const_iterator it = VmaBinaryFindSorted( + suballocations1st.begin() + m_1stNullItemsBeginCount, + suballocations1st.end(), + refSuballoc, + VmaSuballocationOffsetLess()); + if (it != suballocations1st.end()) + { + return const_cast(*it); + } + } + + if (m_2ndVectorMode != SECOND_VECTOR_EMPTY) + { + // Rest of members stays uninitialized intentionally for better performance. + SuballocationVectorType::const_iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ? + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) : + VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater()); + if (it != suballocations2nd.end()) + { + return const_cast(*it); + } + } + + VMA_ASSERT(0 && "Allocation not found in linear allocator!"); + return const_cast(suballocations1st.back()); // Should never occur. +} + +bool VmaBlockMetadata_Linear::ShouldCompact1st() const +{ + const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount; + const size_t suballocCount = AccessSuballocations1st().size(); + return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3; +} + +void VmaBlockMetadata_Linear::CleanupAfterFree() +{ + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (IsEmpty()) + { + suballocations1st.clear(); + suballocations2nd.clear(); + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + m_2ndNullItemsCount = 0; + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + } + else + { + const size_t suballoc1stCount = suballocations1st.size(); + const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount; + VMA_ASSERT(nullItem1stCount <= suballoc1stCount); + + // Find more null items at the beginning of 1st vector. + while (m_1stNullItemsBeginCount < suballoc1stCount && + suballocations1st[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++m_1stNullItemsBeginCount; + --m_1stNullItemsMiddleCount; + } + + // Find more null items at the end of 1st vector. + while (m_1stNullItemsMiddleCount > 0 && + suballocations1st.back().type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_1stNullItemsMiddleCount; + suballocations1st.pop_back(); + } + + // Find more null items at the end of 2nd vector. + while (m_2ndNullItemsCount > 0 && + suballocations2nd.back().type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_2ndNullItemsCount; + suballocations2nd.pop_back(); + } + + // Find more null items at the beginning of 2nd vector. + while (m_2ndNullItemsCount > 0 && + suballocations2nd[0].type == VMA_SUBALLOCATION_TYPE_FREE) + { + --m_2ndNullItemsCount; + VmaVectorRemove(suballocations2nd, 0); + } + + if (ShouldCompact1st()) + { + const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount; + size_t srcIndex = m_1stNullItemsBeginCount; + for (size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex) + { + while (suballocations1st[srcIndex].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++srcIndex; + } + if (dstIndex != srcIndex) + { + suballocations1st[dstIndex] = suballocations1st[srcIndex]; + } + ++srcIndex; + } + suballocations1st.resize(nonNullItemCount); + m_1stNullItemsBeginCount = 0; + m_1stNullItemsMiddleCount = 0; + } + + // 2nd vector became empty. + if (suballocations2nd.empty()) + { + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + } + + // 1st vector became empty. + if (suballocations1st.size() - m_1stNullItemsBeginCount == 0) + { + suballocations1st.clear(); + m_1stNullItemsBeginCount = 0; + + if (!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + // Swap 1st with 2nd. Now 2nd is empty. + m_2ndVectorMode = SECOND_VECTOR_EMPTY; + m_1stNullItemsMiddleCount = m_2ndNullItemsCount; + while (m_1stNullItemsBeginCount < suballocations2nd.size() && + suballocations2nd[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE) + { + ++m_1stNullItemsBeginCount; + --m_1stNullItemsMiddleCount; + } + m_2ndNullItemsCount = 0; + m_1stVectorIndex ^= 1; + } + } + } + + VMA_HEAVY_ASSERT(Validate()); +} + +bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + const VkDeviceSize blockSize = GetSize(); + const VkDeviceSize debugMargin = GetDebugMargin(); + const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity(); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + // Try to allocate at the end of 1st vector. + + VkDeviceSize resultBaseOffset = 0; + if (!suballocations1st.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations1st.back(); + resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin; + } + + // Start from offset equal to beginning of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + // Apply alignment. + resultOffset = VmaAlignUp(resultOffset, allocAlignment); + + // Check previous suballocations for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations1st.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity); + } + } + + const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? + suballocations2nd.back().offset : blockSize; + + // There is enough free space at the end after alignment. + if (resultOffset + allocSize + debugMargin <= freeSpaceEnd) + { + // Check next suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if ((allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK) + { + for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; ) + { + const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) + { + return false; + } + } + else + { + // Already on previous page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1); + // pAllocationRequest->item, customData unused. + pAllocationRequest->type = VmaAllocationRequestType::EndOf1st; + return true; + } + } + + // Wrap-around to end of 2nd vector. Try to allocate there, watching for the + // beginning of 1st vector as the end of free space. + if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + VMA_ASSERT(!suballocations1st.empty()); + + VkDeviceSize resultBaseOffset = 0; + if (!suballocations2nd.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations2nd.back(); + resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin; + } + + // Start from offset equal to beginning of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + // Apply alignment. + resultOffset = VmaAlignUp(resultOffset, allocAlignment); + + // Check previous suballocations for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity); + } + } + + size_t index1st = m_1stNullItemsBeginCount; + + // There is enough free space at the end after alignment. + if ((index1st == suballocations1st.size() && resultOffset + allocSize + debugMargin <= blockSize) || + (index1st < suballocations1st.size() && resultOffset + allocSize + debugMargin <= suballocations1st[index1st].offset)) + { + // Check next suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if (allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) + { + for (size_t nextSuballocIndex = index1st; + nextSuballocIndex < suballocations1st.size(); + nextSuballocIndex++) + { + const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type)) + { + return false; + } + } + else + { + // Already on next page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1); + pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd; + // pAllocationRequest->item, customData unused. + return true; + } + } + + return false; +} + +bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + const VkDeviceSize blockSize = GetSize(); + const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity(); + SuballocationVectorType& suballocations1st = AccessSuballocations1st(); + SuballocationVectorType& suballocations2nd = AccessSuballocations2nd(); + + if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER) + { + VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer."); + return false; + } + + // Try to allocate before 2nd.back(), or end of block if 2nd.empty(). + if (allocSize > blockSize) + { + return false; + } + VkDeviceSize resultBaseOffset = blockSize - allocSize; + if (!suballocations2nd.empty()) + { + const VmaSuballocation& lastSuballoc = suballocations2nd.back(); + resultBaseOffset = lastSuballoc.offset - allocSize; + if (allocSize > lastSuballoc.offset) + { + return false; + } + } + + // Start from offset equal to end of free space. + VkDeviceSize resultOffset = resultBaseOffset; + + const VkDeviceSize debugMargin = GetDebugMargin(); + + // Apply debugMargin at the end. + if (debugMargin > 0) + { + if (resultOffset < debugMargin) + { + return false; + } + resultOffset -= debugMargin; + } + + // Apply alignment. + resultOffset = VmaAlignDown(resultOffset, allocAlignment); + + // Check next suballocations from 2nd for BufferImageGranularity conflicts. + // Make bigger alignment if necessary. + if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty()) + { + bool bufferImageGranularityConflict = false; + for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; ) + { + const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex]; + if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType)) + { + bufferImageGranularityConflict = true; + break; + } + } + else + // Already on previous page. + break; + } + if (bufferImageGranularityConflict) + { + resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity); + } + } + + // There is enough free space. + const VkDeviceSize endOf1st = !suballocations1st.empty() ? + suballocations1st.back().offset + suballocations1st.back().size : + 0; + if (endOf1st + debugMargin <= resultOffset) + { + // Check previous suballocations for BufferImageGranularity conflicts. + // If conflict exists, allocation cannot be made here. + if (bufferImageGranularity > 1) + { + for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; ) + { + const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex]; + if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity)) + { + if (VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type)) + { + return false; + } + } + else + { + // Already on next page. + break; + } + } + } + + // All tests passed: Success. + pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1); + // pAllocationRequest->item unused. + pAllocationRequest->type = VmaAllocationRequestType::UpperAddress; + return true; + } + + return false; +} +#endif // _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_LINEAR + +#ifndef _VMA_BLOCK_METADATA_TLSF +// To not search current larger region if first allocation won't succeed and skip to smaller range +// use with VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as strategy in CreateAllocationRequest(). +// When fragmentation and reusal of previous blocks doesn't matter then use with +// VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT for fastest alloc time possible. +class VmaBlockMetadata_TLSF : public VmaBlockMetadata +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockMetadata_TLSF) +public: + VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual); + ~VmaBlockMetadata_TLSF() override; + + size_t GetAllocationCount() const override { return m_AllocCount; } + size_t GetFreeRegionsCount() const override { return m_BlocksFreeCount + 1; } + VkDeviceSize GetSumFreeSize() const override { return m_BlocksFreeSize + m_NullBlock->size; } + bool IsEmpty() const override { return m_NullBlock->offset == 0; } + VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return ((Block*)allocHandle)->offset; } + + void Init(VkDeviceSize size) override; + bool Validate() const override; + + void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override; + void AddStatistics(VmaStatistics& inoutStats) const override; + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json) const override; +#endif + + bool CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) override; + + VkResult CheckCorruption(const void* pBlockData) override; + void Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) override; + + void Free(VmaAllocHandle allocHandle) override; + void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override; + void* GetAllocationUserData(VmaAllocHandle allocHandle) const override; + VmaAllocHandle GetAllocationListBegin() const override; + VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override; + VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override; + void Clear() override; + void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override; + void DebugLogAllAllocations() const override; + +private: + // According to original paper it should be preferable 4 or 5: + // M. Masmano, I. Ripoll, A. Crespo, and J. Real "TLSF: a New Dynamic Memory Allocator for Real-Time Systems" + // http://www.gii.upv.es/tlsf/files/ecrts04_tlsf.pdf + static const uint8_t SECOND_LEVEL_INDEX = 5; + static const uint16_t SMALL_BUFFER_SIZE = 256; + static const uint32_t INITIAL_BLOCK_ALLOC_COUNT = 16; + static const uint8_t MEMORY_CLASS_SHIFT = 7; + static const uint8_t MAX_MEMORY_CLASSES = 65 - MEMORY_CLASS_SHIFT; + + class Block + { + public: + VkDeviceSize offset; + VkDeviceSize size; + Block* prevPhysical; + Block* nextPhysical; + + void MarkFree() { prevFree = VMA_NULL; } + void MarkTaken() { prevFree = this; } + bool IsFree() const { return prevFree != this; } + void*& UserData() { VMA_HEAVY_ASSERT(!IsFree()); return userData; } + Block*& PrevFree() { return prevFree; } + Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; } + + private: + Block* prevFree; // Address of the same block here indicates that block is taken + union + { + Block* nextFree; + void* userData; + }; + }; + + size_t m_AllocCount; + // Total number of free blocks besides null block + size_t m_BlocksFreeCount; + // Total size of free blocks excluding null block + VkDeviceSize m_BlocksFreeSize; + uint32_t m_IsFreeBitmap; + uint8_t m_MemoryClasses; + uint32_t m_InnerIsFreeBitmap[MAX_MEMORY_CLASSES]; + uint32_t m_ListsCount; + /* + * 0: 0-3 lists for small buffers + * 1+: 0-(2^SLI-1) lists for normal buffers + */ + Block** m_FreeList; + VmaPoolAllocator m_BlockAllocator; + Block* m_NullBlock; + VmaBlockBufferImageGranularity m_GranularityHandler; + + static uint8_t SizeToMemoryClass(VkDeviceSize size); + uint16_t SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const; + uint32_t GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const; + uint32_t GetListIndex(VkDeviceSize size) const; + + void RemoveFreeBlock(Block* block); + void InsertFreeBlock(Block* block); + void MergeBlock(Block* block, Block* prev); + + Block* FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const; + bool CheckBlock( + Block& block, + uint32_t listIndex, + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaAllocationRequest* pAllocationRequest); +}; + +#ifndef _VMA_BLOCK_METADATA_TLSF_FUNCTIONS +VmaBlockMetadata_TLSF::VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks, + VkDeviceSize bufferImageGranularity, bool isVirtual) + : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual), + m_AllocCount(0), + m_BlocksFreeCount(0), + m_BlocksFreeSize(0), + m_IsFreeBitmap(0), + m_MemoryClasses(0), + m_ListsCount(0), + m_FreeList(VMA_NULL), + m_BlockAllocator(pAllocationCallbacks, INITIAL_BLOCK_ALLOC_COUNT), + m_NullBlock(VMA_NULL), + m_GranularityHandler(bufferImageGranularity) {} + +VmaBlockMetadata_TLSF::~VmaBlockMetadata_TLSF() +{ + if (m_FreeList) + vma_delete_array(GetAllocationCallbacks(), m_FreeList, m_ListsCount); + m_GranularityHandler.Destroy(GetAllocationCallbacks()); +} + +void VmaBlockMetadata_TLSF::Init(VkDeviceSize size) +{ + VmaBlockMetadata::Init(size); + + if (!IsVirtual()) + m_GranularityHandler.Init(GetAllocationCallbacks(), size); + + m_NullBlock = m_BlockAllocator.Alloc(); + m_NullBlock->size = size; + m_NullBlock->offset = 0; + m_NullBlock->prevPhysical = VMA_NULL; + m_NullBlock->nextPhysical = VMA_NULL; + m_NullBlock->MarkFree(); + m_NullBlock->NextFree() = VMA_NULL; + m_NullBlock->PrevFree() = VMA_NULL; + uint8_t memoryClass = SizeToMemoryClass(size); + uint16_t sli = SizeToSecondIndex(size, memoryClass); + m_ListsCount = (memoryClass == 0 ? 0 : (memoryClass - 1) * (1UL << SECOND_LEVEL_INDEX) + sli) + 1; + if (IsVirtual()) + m_ListsCount += 1UL << SECOND_LEVEL_INDEX; + else + m_ListsCount += 4; + + m_MemoryClasses = memoryClass + uint8_t(2); + memset(m_InnerIsFreeBitmap, 0, MAX_MEMORY_CLASSES * sizeof(uint32_t)); + + m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount); + memset(m_FreeList, 0, m_ListsCount * sizeof(Block*)); +} + +bool VmaBlockMetadata_TLSF::Validate() const +{ + VMA_VALIDATE(GetSumFreeSize() <= GetSize()); + + VkDeviceSize calculatedSize = m_NullBlock->size; + VkDeviceSize calculatedFreeSize = m_NullBlock->size; + size_t allocCount = 0; + size_t freeCount = 0; + + // Check integrity of free lists + for (uint32_t list = 0; list < m_ListsCount; ++list) + { + Block* block = m_FreeList[list]; + if (block != VMA_NULL) + { + VMA_VALIDATE(block->IsFree()); + VMA_VALIDATE(block->PrevFree() == VMA_NULL); + while (block->NextFree()) + { + VMA_VALIDATE(block->NextFree()->IsFree()); + VMA_VALIDATE(block->NextFree()->PrevFree() == block); + block = block->NextFree(); + } + } + } + + VkDeviceSize nextOffset = m_NullBlock->offset; + auto validateCtx = m_GranularityHandler.StartValidation(GetAllocationCallbacks(), IsVirtual()); + + VMA_VALIDATE(m_NullBlock->nextPhysical == VMA_NULL); + if (m_NullBlock->prevPhysical) + { + VMA_VALIDATE(m_NullBlock->prevPhysical->nextPhysical == m_NullBlock); + } + // Check all blocks + for (Block* prev = m_NullBlock->prevPhysical; prev != VMA_NULL; prev = prev->prevPhysical) + { + VMA_VALIDATE(prev->offset + prev->size == nextOffset); + nextOffset = prev->offset; + calculatedSize += prev->size; + + uint32_t listIndex = GetListIndex(prev->size); + if (prev->IsFree()) + { + ++freeCount; + // Check if free block belongs to free list + Block* freeBlock = m_FreeList[listIndex]; + VMA_VALIDATE(freeBlock != VMA_NULL); + + bool found = false; + do + { + if (freeBlock == prev) + found = true; + + freeBlock = freeBlock->NextFree(); + } while (!found && freeBlock != VMA_NULL); + + VMA_VALIDATE(found); + calculatedFreeSize += prev->size; + } + else + { + ++allocCount; + // Check if taken block is not on a free list + Block* freeBlock = m_FreeList[listIndex]; + while (freeBlock) + { + VMA_VALIDATE(freeBlock != prev); + freeBlock = freeBlock->NextFree(); + } + + if (!IsVirtual()) + { + VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size)); + } + } + + if (prev->prevPhysical) + { + VMA_VALIDATE(prev->prevPhysical->nextPhysical == prev); + } + } + + if (!IsVirtual()) + { + VMA_VALIDATE(m_GranularityHandler.FinishValidation(validateCtx)); + } + + VMA_VALIDATE(nextOffset == 0); + VMA_VALIDATE(calculatedSize == GetSize()); + VMA_VALIDATE(calculatedFreeSize == GetSumFreeSize()); + VMA_VALIDATE(allocCount == m_AllocCount); + VMA_VALIDATE(freeCount == m_BlocksFreeCount); + + return true; +} + +void VmaBlockMetadata_TLSF::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const +{ + inoutStats.statistics.blockCount++; + inoutStats.statistics.blockBytes += GetSize(); + if (m_NullBlock->size > 0) + VmaAddDetailedStatisticsUnusedRange(inoutStats, m_NullBlock->size); + + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + if (block->IsFree()) + VmaAddDetailedStatisticsUnusedRange(inoutStats, block->size); + else + VmaAddDetailedStatisticsAllocation(inoutStats, block->size); + } +} + +void VmaBlockMetadata_TLSF::AddStatistics(VmaStatistics& inoutStats) const +{ + inoutStats.blockCount++; + inoutStats.allocationCount += (uint32_t)m_AllocCount; + inoutStats.blockBytes += GetSize(); + inoutStats.allocationBytes += GetSize() - GetSumFreeSize(); +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockMetadata_TLSF::PrintDetailedMap(class VmaJsonWriter& json) const +{ + size_t blockCount = m_AllocCount + m_BlocksFreeCount; + VmaStlAllocator allocator(GetAllocationCallbacks()); + VmaVector> blockList(blockCount, allocator); + + size_t i = blockCount; + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + blockList[--i] = block; + } + VMA_ASSERT(i == 0); + + VmaDetailedStatistics stats; + VmaClearDetailedStatistics(stats); + AddDetailedStatistics(stats); + + PrintDetailedMap_Begin(json, + stats.statistics.blockBytes - stats.statistics.allocationBytes, + stats.statistics.allocationCount, + stats.unusedRangeCount); + + for (; i < blockCount; ++i) + { + Block* block = blockList[i]; + if (block->IsFree()) + PrintDetailedMap_UnusedRange(json, block->offset, block->size); + else + PrintDetailedMap_Allocation(json, block->offset, block->size, block->UserData()); + } + if (m_NullBlock->size > 0) + PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size); + + PrintDetailedMap_End(json); +} +#endif + +bool VmaBlockMetadata_TLSF::CreateAllocationRequest( + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + bool upperAddress, + VmaSuballocationType allocType, + uint32_t strategy, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(allocSize > 0 && "Cannot allocate empty block!"); + VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm."); + + // For small granularity round up + if (!IsVirtual()) + m_GranularityHandler.RoundupAllocRequest(allocType, allocSize, allocAlignment); + + allocSize += GetDebugMargin(); + // Quick check for too small pool + if (allocSize > GetSumFreeSize()) + return false; + + // If no free blocks in pool then check only null block + if (m_BlocksFreeCount == 0) + return CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest); + + // Round up to the next block + VkDeviceSize sizeForNextList = allocSize; + VkDeviceSize smallSizeStep = VkDeviceSize(SMALL_BUFFER_SIZE / (IsVirtual() ? 1U << SECOND_LEVEL_INDEX : 4U)); + if (allocSize > SMALL_BUFFER_SIZE) + { + sizeForNextList += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX)); + } + else if (allocSize > SMALL_BUFFER_SIZE - smallSizeStep) + sizeForNextList = SMALL_BUFFER_SIZE + 1; + else + sizeForNextList += smallSizeStep; + + uint32_t nextListIndex = m_ListsCount; + uint32_t prevListIndex = m_ListsCount; + Block* nextListBlock = VMA_NULL; + Block* prevListBlock = VMA_NULL; + + // Check blocks according to strategies + if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT) + { + // Quick check for larger block first + nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex); + if (nextListBlock != VMA_NULL && CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + // If not fitted then null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + // Null block failed, search larger bucket + while (nextListBlock) + { + if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + nextListBlock = nextListBlock->NextFree(); + } + + // Failed again, check best fit bucket + prevListBlock = FindFreeBlock(allocSize, prevListIndex); + while (prevListBlock) + { + if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + prevListBlock = prevListBlock->NextFree(); + } + } + else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT) + { + // Check best fit bucket + prevListBlock = FindFreeBlock(allocSize, prevListIndex); + while (prevListBlock) + { + if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + prevListBlock = prevListBlock->NextFree(); + } + + // If failed check null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + // Check larger bucket + nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex); + while (nextListBlock) + { + if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + nextListBlock = nextListBlock->NextFree(); + } + } + else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT ) + { + // Perform search from the start + VmaStlAllocator allocator(GetAllocationCallbacks()); + VmaVector> blockList(m_BlocksFreeCount, allocator); + + size_t i = m_BlocksFreeCount; + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + if (block->IsFree() && block->size >= allocSize) + blockList[--i] = block; + } + + for (; i < m_BlocksFreeCount; ++i) + { + Block& block = *blockList[i]; + if (CheckBlock(block, GetListIndex(block.size), allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + } + + // If failed check null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + // Whole range searched, no more memory + return false; + } + else + { + // Check larger bucket + nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex); + while (nextListBlock) + { + if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + nextListBlock = nextListBlock->NextFree(); + } + + // If failed check null block + if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + + // Check best fit bucket + prevListBlock = FindFreeBlock(allocSize, prevListIndex); + while (prevListBlock) + { + if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + prevListBlock = prevListBlock->NextFree(); + } + } + + // Worst case, full search has to be done + while (++nextListIndex < m_ListsCount) + { + nextListBlock = m_FreeList[nextListIndex]; + while (nextListBlock) + { + if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest)) + return true; + nextListBlock = nextListBlock->NextFree(); + } + } + + // No more memory sadly + return false; +} + +VkResult VmaBlockMetadata_TLSF::CheckCorruption(const void* pBlockData) +{ + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + { + if (!block->IsFree()) + { + if (!VmaValidateMagicValue(pBlockData, block->offset + block->size)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!"); + return VK_ERROR_UNKNOWN_COPY; + } + } + } + + return VK_SUCCESS; +} + +void VmaBlockMetadata_TLSF::Alloc( + const VmaAllocationRequest& request, + VmaSuballocationType type, + void* userData) +{ + VMA_ASSERT(request.type == VmaAllocationRequestType::TLSF); + + // Get block and pop it from the free list + Block* currentBlock = (Block*)request.allocHandle; + VkDeviceSize offset = request.algorithmData; + VMA_ASSERT(currentBlock != VMA_NULL); + VMA_ASSERT(currentBlock->offset <= offset); + + if (currentBlock != m_NullBlock) + RemoveFreeBlock(currentBlock); + + VkDeviceSize debugMargin = GetDebugMargin(); + VkDeviceSize missingAlignment = offset - currentBlock->offset; + + // Append missing alignment to prev block or create new one + if (missingAlignment) + { + Block* prevBlock = currentBlock->prevPhysical; + VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!"); + + if (prevBlock->IsFree() && prevBlock->size != debugMargin) + { + uint32_t oldList = GetListIndex(prevBlock->size); + prevBlock->size += missingAlignment; + // Check if new size crosses list bucket + if (oldList != GetListIndex(prevBlock->size)) + { + prevBlock->size -= missingAlignment; + RemoveFreeBlock(prevBlock); + prevBlock->size += missingAlignment; + InsertFreeBlock(prevBlock); + } + else + m_BlocksFreeSize += missingAlignment; + } + else + { + Block* newBlock = m_BlockAllocator.Alloc(); + currentBlock->prevPhysical = newBlock; + prevBlock->nextPhysical = newBlock; + newBlock->prevPhysical = prevBlock; + newBlock->nextPhysical = currentBlock; + newBlock->size = missingAlignment; + newBlock->offset = currentBlock->offset; + newBlock->MarkTaken(); + + InsertFreeBlock(newBlock); + } + + currentBlock->size -= missingAlignment; + currentBlock->offset += missingAlignment; + } + + VkDeviceSize size = request.size + debugMargin; + if (currentBlock->size == size) + { + if (currentBlock == m_NullBlock) + { + // Setup new null block + m_NullBlock = m_BlockAllocator.Alloc(); + m_NullBlock->size = 0; + m_NullBlock->offset = currentBlock->offset + size; + m_NullBlock->prevPhysical = currentBlock; + m_NullBlock->nextPhysical = VMA_NULL; + m_NullBlock->MarkFree(); + m_NullBlock->PrevFree() = VMA_NULL; + m_NullBlock->NextFree() = VMA_NULL; + currentBlock->nextPhysical = m_NullBlock; + currentBlock->MarkTaken(); + } + } + else + { + VMA_ASSERT(currentBlock->size > size && "Proper block already found, shouldn't find smaller one!"); + + // Create new free block + Block* newBlock = m_BlockAllocator.Alloc(); + newBlock->size = currentBlock->size - size; + newBlock->offset = currentBlock->offset + size; + newBlock->prevPhysical = currentBlock; + newBlock->nextPhysical = currentBlock->nextPhysical; + currentBlock->nextPhysical = newBlock; + currentBlock->size = size; + + if (currentBlock == m_NullBlock) + { + m_NullBlock = newBlock; + m_NullBlock->MarkFree(); + m_NullBlock->NextFree() = VMA_NULL; + m_NullBlock->PrevFree() = VMA_NULL; + currentBlock->MarkTaken(); + } + else + { + newBlock->nextPhysical->prevPhysical = newBlock; + newBlock->MarkTaken(); + InsertFreeBlock(newBlock); + } + } + currentBlock->UserData() = userData; + + if (debugMargin > 0) + { + currentBlock->size -= debugMargin; + Block* newBlock = m_BlockAllocator.Alloc(); + newBlock->size = debugMargin; + newBlock->offset = currentBlock->offset + currentBlock->size; + newBlock->prevPhysical = currentBlock; + newBlock->nextPhysical = currentBlock->nextPhysical; + newBlock->MarkTaken(); + currentBlock->nextPhysical->prevPhysical = newBlock; + currentBlock->nextPhysical = newBlock; + InsertFreeBlock(newBlock); + } + + if (!IsVirtual()) + m_GranularityHandler.AllocPages((uint8_t)(uintptr_t)request.customData, + currentBlock->offset, currentBlock->size); + ++m_AllocCount; +} + +void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle) +{ + Block* block = (Block*)allocHandle; + Block* next = block->nextPhysical; + VMA_ASSERT(!block->IsFree() && "Block is already free!"); + + if (!IsVirtual()) + m_GranularityHandler.FreePages(block->offset, block->size); + --m_AllocCount; + + VkDeviceSize debugMargin = GetDebugMargin(); + if (debugMargin > 0) + { + RemoveFreeBlock(next); + MergeBlock(next, block); + block = next; + next = next->nextPhysical; + } + + // Try merging + Block* prev = block->prevPhysical; + if (prev != VMA_NULL && prev->IsFree() && prev->size != debugMargin) + { + RemoveFreeBlock(prev); + MergeBlock(block, prev); + } + + if (!next->IsFree()) + InsertFreeBlock(block); + else if (next == m_NullBlock) + MergeBlock(m_NullBlock, block); + else + { + RemoveFreeBlock(next); + MergeBlock(next, block); + InsertFreeBlock(next); + } +} + +void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) +{ + Block* block = (Block*)allocHandle; + VMA_ASSERT(!block->IsFree() && "Cannot get allocation info for free block!"); + outInfo.offset = block->offset; + outInfo.size = block->size; + outInfo.pUserData = block->UserData(); +} + +void* VmaBlockMetadata_TLSF::GetAllocationUserData(VmaAllocHandle allocHandle) const +{ + Block* block = (Block*)allocHandle; + VMA_ASSERT(!block->IsFree() && "Cannot get user data for free block!"); + return block->UserData(); +} + +VmaAllocHandle VmaBlockMetadata_TLSF::GetAllocationListBegin() const +{ + if (m_AllocCount == 0) + return VK_NULL_HANDLE; + + for (Block* block = m_NullBlock->prevPhysical; block; block = block->prevPhysical) + { + if (!block->IsFree()) + return (VmaAllocHandle)block; + } + VMA_ASSERT(false && "If m_AllocCount > 0 then should find any allocation!"); + return VK_NULL_HANDLE; +} + +VmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc) const +{ + Block* startBlock = (Block*)prevAlloc; + VMA_ASSERT(!startBlock->IsFree() && "Incorrect block!"); + + for (Block* block = startBlock->prevPhysical; block; block = block->prevPhysical) + { + if (!block->IsFree()) + return (VmaAllocHandle)block; + } + return VK_NULL_HANDLE; +} + +VkDeviceSize VmaBlockMetadata_TLSF::GetNextFreeRegionSize(VmaAllocHandle alloc) const +{ + Block* block = (Block*)alloc; + VMA_ASSERT(!block->IsFree() && "Incorrect block!"); + + if (block->prevPhysical) + return block->prevPhysical->IsFree() ? block->prevPhysical->size : 0; + return 0; +} + +void VmaBlockMetadata_TLSF::Clear() +{ + m_AllocCount = 0; + m_BlocksFreeCount = 0; + m_BlocksFreeSize = 0; + m_IsFreeBitmap = 0; + m_NullBlock->offset = 0; + m_NullBlock->size = GetSize(); + Block* block = m_NullBlock->prevPhysical; + m_NullBlock->prevPhysical = VMA_NULL; + while (block) + { + Block* prev = block->prevPhysical; + m_BlockAllocator.Free(block); + block = prev; + } + memset(m_FreeList, 0, m_ListsCount * sizeof(Block*)); + memset(m_InnerIsFreeBitmap, 0, m_MemoryClasses * sizeof(uint32_t)); + m_GranularityHandler.Clear(); +} + +void VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) +{ + Block* block = (Block*)allocHandle; + VMA_ASSERT(!block->IsFree() && "Trying to set user data for not allocated block!"); + block->UserData() = userData; +} + +void VmaBlockMetadata_TLSF::DebugLogAllAllocations() const +{ + for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical) + if (!block->IsFree()) + DebugLogAllocation(block->offset, block->size, block->UserData()); +} + +uint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) +{ + if (size > SMALL_BUFFER_SIZE) + return uint8_t(VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT); + return 0; +} + +uint16_t VmaBlockMetadata_TLSF::SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const +{ + if (memoryClass == 0) + { + if (IsVirtual()) + return static_cast((size - 1) / 8); + return static_cast((size - 1) / 64); + } + return static_cast((size >> (memoryClass + MEMORY_CLASS_SHIFT - SECOND_LEVEL_INDEX)) ^ (1U << SECOND_LEVEL_INDEX)); +} + +uint32_t VmaBlockMetadata_TLSF::GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const +{ + if (memoryClass == 0) + return secondIndex; + + const uint32_t index = static_cast(memoryClass - 1) * (1 << SECOND_LEVEL_INDEX) + secondIndex; + if (IsVirtual()) + return index + (1 << SECOND_LEVEL_INDEX); + return index + 4; +} + +uint32_t VmaBlockMetadata_TLSF::GetListIndex(VkDeviceSize size) const +{ + uint8_t memoryClass = SizeToMemoryClass(size); + return GetListIndex(memoryClass, SizeToSecondIndex(size, memoryClass)); +} + +void VmaBlockMetadata_TLSF::RemoveFreeBlock(Block* block) +{ + VMA_ASSERT(block != m_NullBlock); + VMA_ASSERT(block->IsFree()); + + if (block->NextFree() != VMA_NULL) + block->NextFree()->PrevFree() = block->PrevFree(); + if (block->PrevFree() != VMA_NULL) + block->PrevFree()->NextFree() = block->NextFree(); + else + { + uint8_t memClass = SizeToMemoryClass(block->size); + uint16_t secondIndex = SizeToSecondIndex(block->size, memClass); + uint32_t index = GetListIndex(memClass, secondIndex); + VMA_ASSERT(m_FreeList[index] == block); + m_FreeList[index] = block->NextFree(); + if (block->NextFree() == VMA_NULL) + { + m_InnerIsFreeBitmap[memClass] &= ~(1U << secondIndex); + if (m_InnerIsFreeBitmap[memClass] == 0) + m_IsFreeBitmap &= ~(1UL << memClass); + } + } + block->MarkTaken(); + block->UserData() = VMA_NULL; + --m_BlocksFreeCount; + m_BlocksFreeSize -= block->size; +} + +void VmaBlockMetadata_TLSF::InsertFreeBlock(Block* block) +{ + VMA_ASSERT(block != m_NullBlock); + VMA_ASSERT(!block->IsFree() && "Cannot insert block twice!"); + + uint8_t memClass = SizeToMemoryClass(block->size); + uint16_t secondIndex = SizeToSecondIndex(block->size, memClass); + uint32_t index = GetListIndex(memClass, secondIndex); + VMA_ASSERT(index < m_ListsCount); + block->PrevFree() = VMA_NULL; + block->NextFree() = m_FreeList[index]; + m_FreeList[index] = block; + if (block->NextFree() != VMA_NULL) + block->NextFree()->PrevFree() = block; + else + { + m_InnerIsFreeBitmap[memClass] |= 1U << secondIndex; + m_IsFreeBitmap |= 1UL << memClass; + } + ++m_BlocksFreeCount; + m_BlocksFreeSize += block->size; +} + +void VmaBlockMetadata_TLSF::MergeBlock(Block* block, Block* prev) +{ + VMA_ASSERT(block->prevPhysical == prev && "Cannot merge separate physical regions!"); + VMA_ASSERT(!prev->IsFree() && "Cannot merge block that belongs to free list!"); + + block->offset = prev->offset; + block->size += prev->size; + block->prevPhysical = prev->prevPhysical; + if (block->prevPhysical) + block->prevPhysical->nextPhysical = block; + m_BlockAllocator.Free(prev); +} + +VmaBlockMetadata_TLSF::Block* VmaBlockMetadata_TLSF::FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const +{ + uint8_t memoryClass = SizeToMemoryClass(size); + uint32_t innerFreeMap = m_InnerIsFreeBitmap[memoryClass] & (~0U << SizeToSecondIndex(size, memoryClass)); + if (!innerFreeMap) + { + // Check higher levels for available blocks + uint32_t freeMap = m_IsFreeBitmap & (~0UL << (memoryClass + 1)); + if (!freeMap) + return VMA_NULL; // No more memory available + + // Find lowest free region + memoryClass = VMA_BITSCAN_LSB(freeMap); + innerFreeMap = m_InnerIsFreeBitmap[memoryClass]; + VMA_ASSERT(innerFreeMap != 0); + } + // Find lowest free subregion + listIndex = GetListIndex(memoryClass, VMA_BITSCAN_LSB(innerFreeMap)); + VMA_ASSERT(m_FreeList[listIndex]); + return m_FreeList[listIndex]; +} + +bool VmaBlockMetadata_TLSF::CheckBlock( + Block& block, + uint32_t listIndex, + VkDeviceSize allocSize, + VkDeviceSize allocAlignment, + VmaSuballocationType allocType, + VmaAllocationRequest* pAllocationRequest) +{ + VMA_ASSERT(block.IsFree() && "Block is already taken!"); + + VkDeviceSize alignedOffset = VmaAlignUp(block.offset, allocAlignment); + if (block.size < allocSize + alignedOffset - block.offset) + return false; + + // Check for granularity conflicts + if (!IsVirtual() && + m_GranularityHandler.CheckConflictAndAlignUp(alignedOffset, allocSize, block.offset, block.size, allocType)) + return false; + + // Alloc successful + pAllocationRequest->type = VmaAllocationRequestType::TLSF; + pAllocationRequest->allocHandle = (VmaAllocHandle)█ + pAllocationRequest->size = allocSize - GetDebugMargin(); + pAllocationRequest->customData = (void*)allocType; + pAllocationRequest->algorithmData = alignedOffset; + + // Place block at the start of list if it's normal block + if (listIndex != m_ListsCount && block.PrevFree()) + { + block.PrevFree()->NextFree() = block.NextFree(); + if (block.NextFree()) + block.NextFree()->PrevFree() = block.PrevFree(); + block.PrevFree() = VMA_NULL; + block.NextFree() = m_FreeList[listIndex]; + m_FreeList[listIndex] = █ + if (block.NextFree()) + block.NextFree()->PrevFree() = █ + } + + return true; +} +#endif // _VMA_BLOCK_METADATA_TLSF_FUNCTIONS +#endif // _VMA_BLOCK_METADATA_TLSF + +#ifndef _VMA_BLOCK_VECTOR +/* +Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific +Vulkan memory type. + +Synchronized internally with a mutex. +*/ +class VmaBlockVector +{ + friend struct VmaDefragmentationContext_T; + VMA_CLASS_NO_COPY_NO_MOVE(VmaBlockVector) +public: + VmaBlockVector( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceSize preferredBlockSize, + size_t minBlockCount, + size_t maxBlockCount, + VkDeviceSize bufferImageGranularity, + bool explicitBlockSize, + uint32_t algorithm, + float priority, + VkDeviceSize minAllocationAlignment, + void* pMemoryAllocateNext); + ~VmaBlockVector(); + + VmaAllocator GetAllocator() const { return m_hAllocator; } + VmaPool GetParentPool() const { return m_hParentPool; } + bool IsCustomPool() const { return m_hParentPool != VMA_NULL; } + uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; } + VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; } + VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; } + uint32_t GetAlgorithm() const { return m_Algorithm; } + bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; } + float GetPriority() const { return m_Priority; } + const void* GetAllocationNextPtr() const { return m_pMemoryAllocateNext; } + // To be used only while the m_Mutex is locked. Used during defragmentation. + size_t GetBlockCount() const { return m_Blocks.size(); } + // To be used only while the m_Mutex is locked. Used during defragmentation. + VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; } + VMA_RW_MUTEX &GetMutex() { return m_Mutex; } + + VkResult CreateMinBlocks(); + void AddStatistics(VmaStatistics& inoutStats); + void AddDetailedStatistics(VmaDetailedStatistics& inoutStats); + bool IsEmpty(); + bool IsCorruptionDetectionEnabled() const; + + VkResult Allocate( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations); + + void Free(VmaAllocation hAllocation); + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json); +#endif + + VkResult CheckCorruption(); + +private: + const VmaAllocator m_hAllocator; + const VmaPool m_hParentPool; + const uint32_t m_MemoryTypeIndex; + const VkDeviceSize m_PreferredBlockSize; + const size_t m_MinBlockCount; + const size_t m_MaxBlockCount; + const VkDeviceSize m_BufferImageGranularity; + const bool m_ExplicitBlockSize; + const uint32_t m_Algorithm; + const float m_Priority; + const VkDeviceSize m_MinAllocationAlignment; + + void* const m_pMemoryAllocateNext; + VMA_RW_MUTEX m_Mutex; + // Incrementally sorted by sumFreeSize, ascending. + VmaVector> m_Blocks; + uint32_t m_NextBlockId; + bool m_IncrementalSort = true; + + void SetIncrementalSort(bool val) { m_IncrementalSort = val; } + + VkDeviceSize CalcMaxBlockSize() const; + // Finds and removes given block from vector. + void Remove(VmaDeviceMemoryBlock* pBlock); + // Performs single step in sorting m_Blocks. They may not be fully sorted + // after this call. + void IncrementallySortBlocks(); + void SortByFreeSize(); + + VkResult AllocatePage( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + VmaAllocation* pAllocation); + + VkResult AllocateFromBlock( + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize size, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + uint32_t strategy, + VmaAllocation* pAllocation); + + VkResult CommitAllocationRequest( + VmaAllocationRequest& allocRequest, + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + VmaAllocation* pAllocation); + + VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex); + bool HasEmptyBlock(); +}; +#endif // _VMA_BLOCK_VECTOR + +#ifndef _VMA_DEFRAGMENTATION_CONTEXT +struct VmaDefragmentationContext_T +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaDefragmentationContext_T) +public: + VmaDefragmentationContext_T( + VmaAllocator hAllocator, + const VmaDefragmentationInfo& info); + ~VmaDefragmentationContext_T(); + + void GetStats(VmaDefragmentationStats& outStats) { outStats = m_GlobalStats; } + + VkResult DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo); + VkResult DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo); + +private: + // Max number of allocations to ignore due to size constraints before ending single pass + static const uint8_t MAX_ALLOCS_TO_IGNORE = 16; + enum class CounterStatus { Pass, Ignore, End }; + + struct FragmentedBlock + { + uint32_t data; + VmaDeviceMemoryBlock* block; + }; + struct StateBalanced + { + VkDeviceSize avgFreeSize = 0; + VkDeviceSize avgAllocSize = UINT64_MAX; + }; + struct StateExtensive + { + enum class Operation : uint8_t + { + FindFreeBlockBuffer, FindFreeBlockTexture, FindFreeBlockAll, + MoveBuffers, MoveTextures, MoveAll, + Cleanup, Done + }; + + Operation operation = Operation::FindFreeBlockTexture; + size_t firstFreeBlock = SIZE_MAX; + }; + struct MoveAllocationData + { + VkDeviceSize size; + VkDeviceSize alignment; + VmaSuballocationType type; + VmaAllocationCreateFlags flags; + VmaDefragmentationMove move = {}; + }; + + const VkDeviceSize m_MaxPassBytes; + const uint32_t m_MaxPassAllocations; + const PFN_vmaCheckDefragmentationBreakFunction m_BreakCallback; + void* m_BreakCallbackUserData; + + VmaStlAllocator m_MoveAllocator; + VmaVector> m_Moves; + + uint8_t m_IgnoredAllocs = 0; + uint32_t m_Algorithm; + uint32_t m_BlockVectorCount; + VmaBlockVector* m_PoolBlockVector; + VmaBlockVector** m_pBlockVectors; + size_t m_ImmovableBlockCount = 0; + VmaDefragmentationStats m_GlobalStats = { 0 }; + VmaDefragmentationStats m_PassStats = { 0 }; + void* m_AlgorithmState = VMA_NULL; + + static MoveAllocationData GetMoveData(VmaAllocHandle handle, VmaBlockMetadata* metadata); + CounterStatus CheckCounters(VkDeviceSize bytes); + bool IncrementCounters(VkDeviceSize bytes); + bool ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block); + bool AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector); + + bool ComputeDefragmentation(VmaBlockVector& vector, size_t index); + bool ComputeDefragmentation_Fast(VmaBlockVector& vector); + bool ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update); + bool ComputeDefragmentation_Full(VmaBlockVector& vector); + bool ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index); + + static void UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state); + bool MoveDataToFreeBlocks(VmaSuballocationType currentType, + VmaBlockVector& vector, size_t firstFreeBlock, + bool& texturePresent, bool& bufferPresent, bool& otherPresent); +}; +#endif // _VMA_DEFRAGMENTATION_CONTEXT + +#ifndef _VMA_POOL_T +struct VmaPool_T +{ + friend struct VmaPoolListItemTraits; + VMA_CLASS_NO_COPY_NO_MOVE(VmaPool_T) +public: + VmaBlockVector m_BlockVector; + VmaDedicatedAllocationList m_DedicatedAllocations; + + VmaPool_T( + VmaAllocator hAllocator, + const VmaPoolCreateInfo& createInfo, + VkDeviceSize preferredBlockSize); + ~VmaPool_T(); + + uint32_t GetId() const { return m_Id; } + void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; } + + const char* GetName() const { return m_Name; } + void SetName(const char* pName); + +#if VMA_STATS_STRING_ENABLED + //void PrintDetailedMap(class VmaStringBuilder& sb); +#endif + +private: + uint32_t m_Id; + char* m_Name; + VmaPool_T* m_PrevPool = VMA_NULL; + VmaPool_T* m_NextPool = VMA_NULL; +}; + +struct VmaPoolListItemTraits +{ + typedef VmaPool_T ItemType; + + static ItemType* GetPrev(const ItemType* item) { return item->m_PrevPool; } + static ItemType* GetNext(const ItemType* item) { return item->m_NextPool; } + static ItemType*& AccessPrev(ItemType* item) { return item->m_PrevPool; } + static ItemType*& AccessNext(ItemType* item) { return item->m_NextPool; } +}; +#endif // _VMA_POOL_T + +#ifndef _VMA_CURRENT_BUDGET_DATA +struct VmaCurrentBudgetData +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaCurrentBudgetData) +public: + + VMA_ATOMIC_UINT32 m_BlockCount[VK_MAX_MEMORY_HEAPS]; + VMA_ATOMIC_UINT32 m_AllocationCount[VK_MAX_MEMORY_HEAPS]; + VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS]; + VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS]; + +#if VMA_MEMORY_BUDGET + VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch; + VMA_RW_MUTEX m_BudgetMutex; + uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS]; + uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS]; + uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS]; +#endif // VMA_MEMORY_BUDGET + + VmaCurrentBudgetData(); + + void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize); + void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize); +}; + +#ifndef _VMA_CURRENT_BUDGET_DATA_FUNCTIONS +VmaCurrentBudgetData::VmaCurrentBudgetData() +{ + for (uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex) + { + m_BlockCount[heapIndex] = 0; + m_AllocationCount[heapIndex] = 0; + m_BlockBytes[heapIndex] = 0; + m_AllocationBytes[heapIndex] = 0; +#if VMA_MEMORY_BUDGET + m_VulkanUsage[heapIndex] = 0; + m_VulkanBudget[heapIndex] = 0; + m_BlockBytesAtBudgetFetch[heapIndex] = 0; +#endif + } + +#if VMA_MEMORY_BUDGET + m_OperationsSinceBudgetFetch = 0; +#endif +} + +void VmaCurrentBudgetData::AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize) +{ + m_AllocationBytes[heapIndex] += allocationSize; + ++m_AllocationCount[heapIndex]; +#if VMA_MEMORY_BUDGET + ++m_OperationsSinceBudgetFetch; +#endif +} + +void VmaCurrentBudgetData::RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize) +{ + VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize); + m_AllocationBytes[heapIndex] -= allocationSize; + VMA_ASSERT(m_AllocationCount[heapIndex] > 0); + --m_AllocationCount[heapIndex]; +#if VMA_MEMORY_BUDGET + ++m_OperationsSinceBudgetFetch; +#endif +} +#endif // _VMA_CURRENT_BUDGET_DATA_FUNCTIONS +#endif // _VMA_CURRENT_BUDGET_DATA + +#ifndef _VMA_ALLOCATION_OBJECT_ALLOCATOR +/* +Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects. +*/ +class VmaAllocationObjectAllocator +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocationObjectAllocator) +public: + explicit VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) + : m_Allocator(pAllocationCallbacks, 1024) {} + + template VmaAllocation Allocate(Types&&... args); + void Free(VmaAllocation hAlloc); + +private: + VMA_MUTEX m_Mutex; + VmaPoolAllocator m_Allocator; +}; + +template +VmaAllocation VmaAllocationObjectAllocator::Allocate(Types&&... args) +{ + VmaMutexLock mutexLock(m_Mutex); + return m_Allocator.Alloc(std::forward(args)...); +} + +void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc) +{ + VmaMutexLock mutexLock(m_Mutex); + m_Allocator.Free(hAlloc); +} +#endif // _VMA_ALLOCATION_OBJECT_ALLOCATOR + +#ifndef _VMA_VIRTUAL_BLOCK_T +struct VmaVirtualBlock_T +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaVirtualBlock_T) +public: + const bool m_AllocationCallbacksSpecified; + const VkAllocationCallbacks m_AllocationCallbacks; + + explicit VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo); + ~VmaVirtualBlock_T(); + + bool IsEmpty() const { return m_Metadata->IsEmpty(); } + void Free(VmaVirtualAllocation allocation) { m_Metadata->Free((VmaAllocHandle)allocation); } + void SetAllocationUserData(VmaVirtualAllocation allocation, void* userData) { m_Metadata->SetAllocationUserData((VmaAllocHandle)allocation, userData); } + void Clear() { m_Metadata->Clear(); } + + const VkAllocationCallbacks* GetAllocationCallbacks() const; + void GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo); + VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation, + VkDeviceSize* outOffset); + void GetStatistics(VmaStatistics& outStats) const; + void CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const; +#if VMA_STATS_STRING_ENABLED + void BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const; +#endif + +private: + VmaBlockMetadata* m_Metadata; +}; + +#ifndef _VMA_VIRTUAL_BLOCK_T_FUNCTIONS +VmaVirtualBlock_T::VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo) + : m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL), + m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks) +{ + const uint32_t algorithm = createInfo.flags & VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK; + switch (algorithm) + { + case 0: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_TLSF)(VK_NULL_HANDLE, 1, true); + break; + case VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT: + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Linear)(VK_NULL_HANDLE, 1, true); + break; + default: + VMA_ASSERT(0); + m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_TLSF)(VK_NULL_HANDLE, 1, true); + } + + m_Metadata->Init(createInfo.size); +} + +VmaVirtualBlock_T::~VmaVirtualBlock_T() +{ + // Define macro VMA_DEBUG_LOG_FORMAT or more specialized VMA_LEAK_LOG_FORMAT + // to receive the list of the unfreed allocations. + if (!m_Metadata->IsEmpty()) + m_Metadata->DebugLogAllAllocations(); + // This is the most important assert in the entire library. + // Hitting it means you have some memory leak - unreleased virtual allocations. + VMA_ASSERT_LEAK(m_Metadata->IsEmpty() && "Some virtual allocations were not freed before destruction of this virtual block!"); + + vma_delete(GetAllocationCallbacks(), m_Metadata); +} + +const VkAllocationCallbacks* VmaVirtualBlock_T::GetAllocationCallbacks() const +{ + return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL; +} + +void VmaVirtualBlock_T::GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo) +{ + m_Metadata->GetAllocationInfo((VmaAllocHandle)allocation, outInfo); +} + +VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation, + VkDeviceSize* outOffset) +{ + VmaAllocationRequest request = {}; + if (m_Metadata->CreateAllocationRequest( + createInfo.size, // allocSize + VMA_MAX(createInfo.alignment, (VkDeviceSize)1), // allocAlignment + (createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0, // upperAddress + VMA_SUBALLOCATION_TYPE_UNKNOWN, // allocType - unimportant + createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK, // strategy + &request)) + { + m_Metadata->Alloc(request, + VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant + createInfo.pUserData); + outAllocation = (VmaVirtualAllocation)request.allocHandle; + if(outOffset) + *outOffset = m_Metadata->GetAllocationOffset(request.allocHandle); + return VK_SUCCESS; + } + outAllocation = (VmaVirtualAllocation)VK_NULL_HANDLE; + if (outOffset) + *outOffset = UINT64_MAX; + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + +void VmaVirtualBlock_T::GetStatistics(VmaStatistics& outStats) const +{ + VmaClearStatistics(outStats); + m_Metadata->AddStatistics(outStats); +} + +void VmaVirtualBlock_T::CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const +{ + VmaClearDetailedStatistics(outStats); + m_Metadata->AddDetailedStatistics(outStats); +} + +#if VMA_STATS_STRING_ENABLED +void VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const +{ + VmaJsonWriter json(GetAllocationCallbacks(), sb); + json.BeginObject(); + + VmaDetailedStatistics stats; + CalculateDetailedStatistics(stats); + + json.WriteString("Stats"); + VmaPrintDetailedStatistics(json, stats); + + if (detailedMap) + { + json.WriteString("Details"); + json.BeginObject(); + m_Metadata->PrintDetailedMap(json); + json.EndObject(); + } + + json.EndObject(); +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS +#endif // _VMA_VIRTUAL_BLOCK_T + + +// Main allocator object. +struct VmaAllocator_T +{ + VMA_CLASS_NO_COPY_NO_MOVE(VmaAllocator_T) +public: + const bool m_UseMutex; + const uint32_t m_VulkanApiVersion; + bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0). + bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0). + bool m_UseExtMemoryBudget; + bool m_UseAmdDeviceCoherentMemory; + bool m_UseKhrBufferDeviceAddress; + bool m_UseExtMemoryPriority; + bool m_UseKhrMaintenance4; + bool m_UseKhrMaintenance5; + bool m_UseKhrExternalMemoryWin32; + const VkDevice m_hDevice; + const VkInstance m_hInstance; + const bool m_AllocationCallbacksSpecified; + const VkAllocationCallbacks m_AllocationCallbacks; + VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks; + VmaAllocationObjectAllocator m_AllocationObjectAllocator; + + // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size. + uint32_t m_HeapSizeLimitMask; + + VkPhysicalDeviceProperties m_PhysicalDeviceProperties; + VkPhysicalDeviceMemoryProperties m_MemProps; + + // Default pools. + VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES]; + VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES]; + + VmaCurrentBudgetData m_Budget; + VMA_ATOMIC_UINT32 m_DeviceMemoryCount; // Total number of VkDeviceMemory objects. + + explicit VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo); + VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo); + ~VmaAllocator_T(); + + const VkAllocationCallbacks* GetAllocationCallbacks() const + { + return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL; + } + const VmaVulkanFunctions& GetVulkanFunctions() const + { + return m_VulkanFunctions; + } + + VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; } + + VkDeviceSize GetBufferImageGranularity() const + { + return VMA_MAX( + static_cast(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY), + m_PhysicalDeviceProperties.limits.bufferImageGranularity); + } + + uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; } + uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; } + + uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const + { + VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount); + return m_MemProps.memoryTypes[memTypeIndex].heapIndex; + } + // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT. + bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const + { + return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) == + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; + } + // Minimum alignment for all allocations in specific memory type. + VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const + { + return IsMemoryTypeNonCoherent(memTypeIndex) ? + VMA_MAX((VkDeviceSize)VMA_MIN_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) : + (VkDeviceSize)VMA_MIN_ALIGNMENT; + } + + bool IsIntegratedGpu() const + { + return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + } + + uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; } + + void GetBufferMemoryRequirements( + VkBuffer hBuffer, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const; + void GetImageMemoryRequirements( + VkImage hImage, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const; + VkResult FindMemoryTypeIndex( + uint32_t memoryTypeBits, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VmaBufferImageUsage bufImgUsage, + uint32_t* pMemoryTypeIndex) const; + + // Main allocation function. + VkResult AllocateMemory( + const VkMemoryRequirements& vkMemReq, + bool requiresDedicatedAllocation, + bool prefersDedicatedAllocation, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations); + + // Main deallocation function. + void FreeMemory( + size_t allocationCount, + const VmaAllocation* pAllocations); + + void CalculateStatistics(VmaTotalStatistics* pStats); + + void GetHeapBudgets( + VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount); + +#if VMA_STATS_STRING_ENABLED + void PrintDetailedMap(class VmaJsonWriter& json); +#endif + + static void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo); + static void GetAllocationInfo2(VmaAllocation hAllocation, VmaAllocationInfo2* pAllocationInfo); + + VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool); + void DestroyPool(VmaPool pool); + static void GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats); + static void CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats); + + void SetCurrentFrameIndex(uint32_t frameIndex); + uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); } + + static VkResult CheckPoolCorruption(VmaPool hPool); + VkResult CheckCorruption(uint32_t memoryTypeBits); + + // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping. + VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory); + // Call to Vulkan function vkFreeMemory with accompanying bookkeeping. + void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory); + // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR. + VkResult BindVulkanBuffer( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkBuffer buffer, + const void* pNext) const; + // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR. + VkResult BindVulkanImage( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkImage image, + const void* pNext) const; + + VkResult Map(VmaAllocation hAllocation, void** ppData); + void Unmap(VmaAllocation hAllocation); + + VkResult BindBufferMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext); + VkResult BindImageMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext); + + VkResult FlushOrInvalidateAllocation( + VmaAllocation hAllocation, + VkDeviceSize offset, VkDeviceSize size, + VMA_CACHE_OPERATION op); + VkResult FlushOrInvalidateAllocations( + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, const VkDeviceSize* sizes, + VMA_CACHE_OPERATION op); + + VkResult CopyMemoryToAllocation( + const void* pSrcHostPointer, + VmaAllocation dstAllocation, + VkDeviceSize dstAllocationLocalOffset, + VkDeviceSize size); + VkResult CopyAllocationToMemory( + VmaAllocation srcAllocation, + VkDeviceSize srcAllocationLocalOffset, + void* pDstHostPointer, + VkDeviceSize size); + + void FillAllocation(VmaAllocation hAllocation, uint8_t pattern); + + /* + Returns bit mask of memory types that can support defragmentation on GPU as + they support creation of required buffer for copy operations. + */ + uint32_t GetGpuDefragmentationMemoryTypeBits(); + +#if VMA_EXTERNAL_MEMORY + VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const + { + return m_TypeExternalMemoryHandleTypes[memTypeIndex]; + } +#endif // #if VMA_EXTERNAL_MEMORY + +private: + VkDeviceSize m_PreferredLargeHeapBlockSize; + + VkPhysicalDevice m_PhysicalDevice; + VMA_ATOMIC_UINT32 m_CurrentFrameIndex; + VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized. +#if VMA_EXTERNAL_MEMORY + VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES]; +#endif // #if VMA_EXTERNAL_MEMORY + + VMA_RW_MUTEX m_PoolsMutex; + typedef VmaIntrusiveLinkedList PoolList; + // Protected by m_PoolsMutex. + PoolList m_Pools; + uint32_t m_NextPoolId; + + VmaVulkanFunctions m_VulkanFunctions; + + // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types. + uint32_t m_GlobalMemoryTypeBits; + + void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions); + +#if VMA_STATIC_VULKAN_FUNCTIONS == 1 + void ImportVulkanFunctions_Static(); +#endif + + void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions); + +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + void ImportVulkanFunctions_Dynamic(); +#endif + + void ValidateVulkanFunctions() const; + + VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex); + + VkResult AllocateMemoryOfType( + VmaPool pool, + VkDeviceSize size, + VkDeviceSize alignment, + bool dedicatedPreferred, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + const VmaAllocationCreateInfo& createInfo, + uint32_t memTypeIndex, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + VmaBlockVector& blockVector, + size_t allocationCount, + VmaAllocation* pAllocations); + + // Helper function only to be used inside AllocateDedicatedMemory. + VkResult AllocateDedicatedMemoryPage( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + uint32_t memTypeIndex, + const VkMemoryAllocateInfo& allocInfo, + bool map, + bool isUserDataString, + bool isMappingAllowed, + void* pUserData, + VmaAllocation* pAllocation); + + // Allocates and registers new VkDeviceMemory specifically for dedicated allocations. + VkResult AllocateDedicatedMemory( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + uint32_t memTypeIndex, + bool map, + bool isUserDataString, + bool isMappingAllowed, + bool canAliasMemory, + void* pUserData, + float priority, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + size_t allocationCount, + VmaAllocation* pAllocations, + const void* pNextChain = VMA_NULL); + + void FreeDedicatedMemory(VmaAllocation allocation); + + VkResult CalcMemTypeParams( + VmaAllocationCreateInfo& outCreateInfo, + uint32_t memTypeIndex, + VkDeviceSize size, + size_t allocationCount); + static VkResult CalcAllocationParams( + VmaAllocationCreateInfo& outCreateInfo, + bool dedicatedRequired); + + /* + Calculates and returns bit mask of memory types that can support defragmentation + on GPU as they support creation of required buffer for copy operations. + */ + uint32_t CalculateGpuDefragmentationMemoryTypeBits() const; + uint32_t CalculateGlobalMemoryTypeBits() const; + + bool GetFlushOrInvalidateRange( + VmaAllocation allocation, + VkDeviceSize offset, VkDeviceSize size, + VkMappedMemoryRange& outRange) const; + +#if VMA_MEMORY_BUDGET + void UpdateVulkanBudget(); +#endif // #if VMA_MEMORY_BUDGET +}; + + +#ifndef _VMA_MEMORY_FUNCTIONS +static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment) +{ + return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment); +} + +static void VmaFree(VmaAllocator hAllocator, void* ptr) +{ + VmaFree(&hAllocator->m_AllocationCallbacks, ptr); +} + +template +static T* VmaAllocate(VmaAllocator hAllocator) +{ + return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T)); +} + +template +static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count) +{ + return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T)); +} + +template +static void vma_delete(VmaAllocator hAllocator, T* ptr) +{ + if(ptr != VMA_NULL) + { + ptr->~T(); + VmaFree(hAllocator, ptr); + } +} + +template +static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count) +{ + if(ptr != VMA_NULL) + { + for(size_t i = count; i--; ) + ptr[i].~T(); + VmaFree(hAllocator, ptr); + } +} +#endif // _VMA_MEMORY_FUNCTIONS + +#ifndef _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS +VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) + : m_pMetadata(VMA_NULL), + m_hParentPool(nullptr), + m_MemoryTypeIndex(UINT32_MAX), + m_Id(0), + m_hMemory(VK_NULL_HANDLE), + m_MapCount(0), + m_pMappedData(VMA_NULL){} + +VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock() +{ + VMA_ASSERT_LEAK(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped."); + VMA_ASSERT_LEAK(m_hMemory == VK_NULL_HANDLE); +} + +void VmaDeviceMemoryBlock::Init( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t newMemoryTypeIndex, + VkDeviceMemory newMemory, + VkDeviceSize newSize, + uint32_t id, + uint32_t algorithm, + VkDeviceSize bufferImageGranularity) +{ + VMA_ASSERT(m_hMemory == VK_NULL_HANDLE); + + m_hParentPool = hParentPool; + m_MemoryTypeIndex = newMemoryTypeIndex; + m_Id = id; + m_hMemory = newMemory; + + switch (algorithm) + { + case 0: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_TLSF)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + break; + case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT: + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + break; + default: + VMA_ASSERT(0); + m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_TLSF)(hAllocator->GetAllocationCallbacks(), + bufferImageGranularity, false); // isVirtual + } + m_pMetadata->Init(newSize); +} + +void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator) +{ + // Define macro VMA_DEBUG_LOG_FORMAT or more specialized VMA_LEAK_LOG_FORMAT + // to receive the list of the unfreed allocations. + if (!m_pMetadata->IsEmpty()) + m_pMetadata->DebugLogAllAllocations(); + // This is the most important assert in the entire library. + // Hitting it means you have some memory leak - unreleased VmaAllocation objects. + VMA_ASSERT_LEAK(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!"); + + VMA_ASSERT_LEAK(m_hMemory != VK_NULL_HANDLE); + allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory); + m_hMemory = VK_NULL_HANDLE; + + vma_delete(allocator, m_pMetadata); + m_pMetadata = VMA_NULL; +} + +void VmaDeviceMemoryBlock::PostAlloc(VmaAllocator hAllocator) +{ + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + m_MappingHysteresis.PostAlloc(); +} + +void VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator) +{ + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + if(m_MappingHysteresis.PostFree()) + { + VMA_ASSERT(m_MappingHysteresis.GetExtraMapping() == 0); + if (m_MapCount == 0) + { + m_pMappedData = VMA_NULL; + (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); + } + } +} + +bool VmaDeviceMemoryBlock::Validate() const +{ + VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) && + (m_pMetadata->GetSize() != 0)); + + return m_pMetadata->Validate(); +} + +VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator) +{ + void* pData = VMA_NULL; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + res = m_pMetadata->CheckCorruption(pData); + + Unmap(hAllocator, 1); + + return res; +} + +VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData) +{ + if (count == 0) + { + return VK_SUCCESS; + } + + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + const uint32_t oldTotalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping(); + if (oldTotalMapCount != 0) + { + VMA_ASSERT(m_pMappedData != VMA_NULL); + m_MappingHysteresis.PostMap(); + m_MapCount += count; + if (ppData != VMA_NULL) + { + *ppData = m_pMappedData; + } + return VK_SUCCESS; + } + + VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)( + hAllocator->m_hDevice, + m_hMemory, + 0, // offset + VK_WHOLE_SIZE, + 0, // flags + &m_pMappedData); + if (result == VK_SUCCESS) + { + VMA_ASSERT(m_pMappedData != VMA_NULL); + m_MappingHysteresis.PostMap(); + m_MapCount = count; + if (ppData != VMA_NULL) + { + *ppData = m_pMappedData; + } + } + return result; +} + +void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count) +{ + if (count == 0) + { + return; + } + + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + if (m_MapCount >= count) + { + m_MapCount -= count; + const uint32_t totalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping(); + if (totalMapCount == 0) + { + m_pMappedData = VMA_NULL; + (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory); + } + m_MappingHysteresis.PostUnmap(); + } + else + { + VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped."); + } +} + +VkResult VmaDeviceMemoryBlock::WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize) +{ + VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION); + + void* pData = VMA_NULL; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + VmaWriteMagicValue(pData, allocOffset + allocSize); + + Unmap(hAllocator, 1); + return VK_SUCCESS; +} + +VkResult VmaDeviceMemoryBlock::ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize) +{ + VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION); + + void* pData = VMA_NULL; + VkResult res = Map(hAllocator, 1, &pData); + if (res != VK_SUCCESS) + { + return res; + } + + if (!VmaValidateMagicValue(pData, allocOffset + allocSize)) + { + VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!"); + } + + Unmap(hAllocator, 1); + return VK_SUCCESS; +} + +VkResult VmaDeviceMemoryBlock::BindBufferMemory( + VmaAllocator hAllocator, + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext) +{ + VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK && + hAllocation->GetBlock() == this); + VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() && + "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?"); + const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset; + // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads. + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext); +} + +VkResult VmaDeviceMemoryBlock::BindImageMemory( + VmaAllocator hAllocator, + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext) +{ + VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK && + hAllocation->GetBlock() == this); + VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() && + "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?"); + const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset; + // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads. + VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); + return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext); +} + +#if VMA_EXTERNAL_MEMORY_WIN32 +VkResult VmaDeviceMemoryBlock::CreateWin32Handle(const VmaAllocator hAllocator, PFN_vkGetMemoryWin32HandleKHR pvkGetMemoryWin32HandleKHR, HANDLE hTargetProcess, HANDLE* pHandle) noexcept +{ + VMA_ASSERT(pHandle); + return m_Handle.GetHandle(hAllocator->m_hDevice, m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle); +} +#endif // VMA_EXTERNAL_MEMORY_WIN32 +#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS + +#ifndef _VMA_ALLOCATION_T_FUNCTIONS +VmaAllocation_T::VmaAllocation_T(bool mappingAllowed) + : m_Alignment{ 1 }, + m_Size{ 0 }, + m_pUserData{ VMA_NULL }, + m_pName{ VMA_NULL }, + m_MemoryTypeIndex{ 0 }, + m_Type{ (uint8_t)ALLOCATION_TYPE_NONE }, + m_SuballocationType{ (uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN }, + m_MapCount{ 0 }, + m_Flags{ 0 } +{ + if(mappingAllowed) + m_Flags |= (uint8_t)FLAG_MAPPING_ALLOWED; +} + +VmaAllocation_T::~VmaAllocation_T() +{ + VMA_ASSERT_LEAK(m_MapCount == 0 && "Allocation was not unmapped before destruction."); + + // Check if owned string was freed. + VMA_ASSERT(m_pName == VMA_NULL); +} + +void VmaAllocation_T::InitBlockAllocation( + VmaDeviceMemoryBlock* block, + VmaAllocHandle allocHandle, + VkDeviceSize alignment, + VkDeviceSize size, + uint32_t memoryTypeIndex, + VmaSuballocationType suballocationType, + bool mapped) +{ + VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); + VMA_ASSERT(block != VMA_NULL); + m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK; + m_Alignment = alignment; + m_Size = size; + m_MemoryTypeIndex = memoryTypeIndex; + if(mapped) + { + VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); + m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP; + } + m_SuballocationType = (uint8_t)suballocationType; + m_BlockAllocation.m_Block = block; + m_BlockAllocation.m_AllocHandle = allocHandle; +} + +void VmaAllocation_T::InitDedicatedAllocation( + VmaAllocator allocator, + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceMemory hMemory, + VmaSuballocationType suballocationType, + void* pMappedData, + VkDeviceSize size) +{ + VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE); + VMA_ASSERT(hMemory != VK_NULL_HANDLE); + m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED; + m_Alignment = 0; + m_Size = size; + m_MemoryTypeIndex = memoryTypeIndex; + m_SuballocationType = (uint8_t)suballocationType; + m_DedicatedAllocation.m_ExtraData = VMA_NULL; + m_DedicatedAllocation.m_hParentPool = hParentPool; + m_DedicatedAllocation.m_hMemory = hMemory; + m_DedicatedAllocation.m_Prev = VMA_NULL; + m_DedicatedAllocation.m_Next = VMA_NULL; + + if (pMappedData != VMA_NULL) + { + VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); + m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP; + EnsureExtraData(allocator); + m_DedicatedAllocation.m_ExtraData->m_pMappedData = pMappedData; + } +} + +void VmaAllocation_T::Destroy(VmaAllocator allocator) +{ + FreeName(allocator); + + if (GetType() == ALLOCATION_TYPE_DEDICATED) + { + vma_delete(allocator, m_DedicatedAllocation.m_ExtraData); + } +} + +void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName) +{ + VMA_ASSERT(pName == VMA_NULL || pName != m_pName); + + FreeName(hAllocator); + + if (pName != VMA_NULL) + m_pName = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), pName); +} + +uint8_t VmaAllocation_T::SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation) +{ + VMA_ASSERT(allocation != VMA_NULL); + VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); + VMA_ASSERT(allocation->m_Type == ALLOCATION_TYPE_BLOCK); + + if (m_MapCount != 0) + m_BlockAllocation.m_Block->Unmap(hAllocator, m_MapCount); + + m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, allocation); + std::swap(m_BlockAllocation, allocation->m_BlockAllocation); + m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, this); + +#if VMA_STATS_STRING_ENABLED + std::swap(m_BufferImageUsage, allocation->m_BufferImageUsage); +#endif + return m_MapCount; +} + +VmaAllocHandle VmaAllocation_T::GetAllocHandle() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_AllocHandle; + case ALLOCATION_TYPE_DEDICATED: + return VK_NULL_HANDLE; + default: + VMA_ASSERT(0); + return VK_NULL_HANDLE; + } +} + +VkDeviceSize VmaAllocation_T::GetOffset() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->m_pMetadata->GetAllocationOffset(m_BlockAllocation.m_AllocHandle); + case ALLOCATION_TYPE_DEDICATED: + return 0; + default: + VMA_ASSERT(0); + return 0; + } +} + +VmaPool VmaAllocation_T::GetParentPool() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->GetParentPool(); + case ALLOCATION_TYPE_DEDICATED: + return m_DedicatedAllocation.m_hParentPool; + default: + VMA_ASSERT(0); + return VK_NULL_HANDLE; + } +} + +VkDeviceMemory VmaAllocation_T::GetMemory() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->GetDeviceMemory(); + case ALLOCATION_TYPE_DEDICATED: + return m_DedicatedAllocation.m_hMemory; + default: + VMA_ASSERT(0); + return VK_NULL_HANDLE; + } +} + +void* VmaAllocation_T::GetMappedData() const +{ + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + if (m_MapCount != 0 || IsPersistentMap()) + { + void* pBlockData = m_BlockAllocation.m_Block->GetMappedData(); + VMA_ASSERT(pBlockData != VMA_NULL); + return (char*)pBlockData + GetOffset(); + } + else + { + return VMA_NULL; + } + break; + case ALLOCATION_TYPE_DEDICATED: + VMA_ASSERT((m_DedicatedAllocation.m_ExtraData != VMA_NULL && m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL) == + (m_MapCount != 0 || IsPersistentMap())); + return m_DedicatedAllocation.m_ExtraData != VMA_NULL ? m_DedicatedAllocation.m_ExtraData->m_pMappedData : VMA_NULL; + default: + VMA_ASSERT(0); + return VMA_NULL; + } +} + +void VmaAllocation_T::BlockAllocMap() +{ + VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK); + VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); + + if (m_MapCount < 0xFF) + { + ++m_MapCount; + } + else + { + VMA_ASSERT(0 && "Allocation mapped too many times simultaneously."); + } +} + +void VmaAllocation_T::BlockAllocUnmap() +{ + VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK); + + if (m_MapCount > 0) + { + --m_MapCount; + } + else + { + VMA_ASSERT(0 && "Unmapping allocation not previously mapped."); + } +} + +VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData) +{ + VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED); + VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it."); + + EnsureExtraData(hAllocator); + + if (m_MapCount != 0 || IsPersistentMap()) + { + if (m_MapCount < 0xFF) + { + VMA_ASSERT(m_DedicatedAllocation.m_ExtraData->m_pMappedData != VMA_NULL); + *ppData = m_DedicatedAllocation.m_ExtraData->m_pMappedData; + ++m_MapCount; + return VK_SUCCESS; + } + + VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously."); + return VK_ERROR_MEMORY_MAP_FAILED; + } + + VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)( + hAllocator->m_hDevice, + m_DedicatedAllocation.m_hMemory, + 0, // offset + VK_WHOLE_SIZE, + 0, // flags + ppData); + if (result == VK_SUCCESS) + { + m_DedicatedAllocation.m_ExtraData->m_pMappedData = *ppData; + m_MapCount = 1; + } + return result; +} + +void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator) +{ + VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED); + + if (m_MapCount > 0) + { + --m_MapCount; + if (m_MapCount == 0 && !IsPersistentMap()) + { + VMA_ASSERT(m_DedicatedAllocation.m_ExtraData != VMA_NULL); + m_DedicatedAllocation.m_ExtraData->m_pMappedData = VMA_NULL; + (*hAllocator->GetVulkanFunctions().vkUnmapMemory)( + hAllocator->m_hDevice, + m_DedicatedAllocation.m_hMemory); + } + } + else + { + VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped."); + } +} + +#if VMA_STATS_STRING_ENABLED +void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const +{ + json.WriteString("Type"); + json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]); + + json.WriteString("Size"); + json.WriteNumber(m_Size); + json.WriteString("Usage"); + json.WriteNumber(m_BufferImageUsage.Value); // It may be uint32_t or uint64_t. + + if (m_pUserData != VMA_NULL) + { + json.WriteString("CustomData"); + json.BeginString(); + json.ContinueString_Pointer(m_pUserData); + json.EndString(); + } + if (m_pName != VMA_NULL) + { + json.WriteString("Name"); + json.WriteString(m_pName); + } +} +#if VMA_EXTERNAL_MEMORY_WIN32 +VkResult VmaAllocation_T::GetWin32Handle(VmaAllocator hAllocator, HANDLE hTargetProcess, HANDLE* pHandle) noexcept +{ + auto pvkGetMemoryWin32HandleKHR = hAllocator->GetVulkanFunctions().vkGetMemoryWin32HandleKHR; + switch (m_Type) + { + case ALLOCATION_TYPE_BLOCK: + return m_BlockAllocation.m_Block->CreateWin32Handle(hAllocator, pvkGetMemoryWin32HandleKHR, hTargetProcess, pHandle); + case ALLOCATION_TYPE_DEDICATED: + EnsureExtraData(hAllocator); + return m_DedicatedAllocation.m_ExtraData->m_Handle.GetHandle(hAllocator->m_hDevice, m_DedicatedAllocation.m_hMemory, pvkGetMemoryWin32HandleKHR, hTargetProcess, hAllocator->m_UseMutex, pHandle); + default: + VMA_ASSERT(0); + return VK_ERROR_FEATURE_NOT_PRESENT; + } +} +#endif // VMA_EXTERNAL_MEMORY_WIN32 +#endif // VMA_STATS_STRING_ENABLED + +void VmaAllocation_T::EnsureExtraData(VmaAllocator hAllocator) +{ + if (m_DedicatedAllocation.m_ExtraData == VMA_NULL) + { + m_DedicatedAllocation.m_ExtraData = vma_new(hAllocator, VmaAllocationExtraData)(); + } +} + +void VmaAllocation_T::FreeName(VmaAllocator hAllocator) +{ + if(m_pName) + { + VmaFreeString(hAllocator->GetAllocationCallbacks(), m_pName); + m_pName = VMA_NULL; + } +} +#endif // _VMA_ALLOCATION_T_FUNCTIONS + +#ifndef _VMA_BLOCK_VECTOR_FUNCTIONS +VmaBlockVector::VmaBlockVector( + VmaAllocator hAllocator, + VmaPool hParentPool, + uint32_t memoryTypeIndex, + VkDeviceSize preferredBlockSize, + size_t minBlockCount, + size_t maxBlockCount, + VkDeviceSize bufferImageGranularity, + bool explicitBlockSize, + uint32_t algorithm, + float priority, + VkDeviceSize minAllocationAlignment, + void* pMemoryAllocateNext) + : m_hAllocator(hAllocator), + m_hParentPool(hParentPool), + m_MemoryTypeIndex(memoryTypeIndex), + m_PreferredBlockSize(preferredBlockSize), + m_MinBlockCount(minBlockCount), + m_MaxBlockCount(maxBlockCount), + m_BufferImageGranularity(bufferImageGranularity), + m_ExplicitBlockSize(explicitBlockSize), + m_Algorithm(algorithm), + m_Priority(priority), + m_MinAllocationAlignment(minAllocationAlignment), + m_pMemoryAllocateNext(pMemoryAllocateNext), + m_Blocks(VmaStlAllocator(hAllocator->GetAllocationCallbacks())), + m_NextBlockId(0) {} + +VmaBlockVector::~VmaBlockVector() +{ + for (size_t i = m_Blocks.size(); i--; ) + { + m_Blocks[i]->Destroy(m_hAllocator); + vma_delete(m_hAllocator, m_Blocks[i]); + } +} + +VkResult VmaBlockVector::CreateMinBlocks() +{ + for (size_t i = 0; i < m_MinBlockCount; ++i) + { + VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL); + if (res != VK_SUCCESS) + { + return res; + } + } + return VK_SUCCESS; +} + +void VmaBlockVector::AddStatistics(VmaStatistics& inoutStats) +{ + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + + const size_t blockCount = m_Blocks.size(); + for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pBlock); + VMA_HEAVY_ASSERT(pBlock->Validate()); + pBlock->m_pMetadata->AddStatistics(inoutStats); + } +} + +void VmaBlockVector::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) +{ + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + + const size_t blockCount = m_Blocks.size(); + for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex) + { + const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pBlock); + VMA_HEAVY_ASSERT(pBlock->Validate()); + pBlock->m_pMetadata->AddDetailedStatistics(inoutStats); + } +} + +bool VmaBlockVector::IsEmpty() +{ + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + return m_Blocks.empty(); +} + +bool VmaBlockVector::IsCorruptionDetectionEnabled() const +{ + const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + return (VMA_DEBUG_DETECT_CORRUPTION != 0) && + (VMA_DEBUG_MARGIN > 0) && + (m_Algorithm == 0 || m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) && + (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags; +} + +VkResult VmaBlockVector::Allocate( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations) +{ + size_t allocIndex = 0; + VkResult res = VK_SUCCESS; + + alignment = VMA_MAX(alignment, m_MinAllocationAlignment); + + if (IsCorruptionDetectionEnabled()) + { + size = VmaAlignUp(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE)); + alignment = VmaAlignUp(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE)); + } + + { + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); + for (; allocIndex < allocationCount; ++allocIndex) + { + res = AllocatePage( + size, + alignment, + createInfo, + suballocType, + pAllocations + allocIndex); + if (res != VK_SUCCESS) + { + break; + } + } + } + + if (res != VK_SUCCESS) + { + // Free all already created allocations. + while (allocIndex--) + Free(pAllocations[allocIndex]); + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + } + + return res; +} + +VkResult VmaBlockVector::AllocatePage( + VkDeviceSize size, + VkDeviceSize alignment, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + VmaAllocation* pAllocation) +{ + const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0; + + VkDeviceSize freeMemory = 0; + { + const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex); + VmaBudget heapBudget = {}; + m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1); + freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0; + } + + const bool canFallbackToDedicated = !HasExplicitBlockSize() && + (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0; + const bool canCreateNewBlock = + ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) && + (m_Blocks.size() < m_MaxBlockCount) && + (freeMemory >= size || !canFallbackToDedicated); + uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK; + + // Upper address can only be used with linear allocator and within single memory block. + if (isUpperAddress && + (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1)) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + // Early reject: requested allocation size is larger that maximum block size for this block vector. + if (size + VMA_DEBUG_MARGIN > m_PreferredBlockSize) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + + // 1. Search existing allocations. Try to allocate. + if (m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) + { + // Use only last block. + if (!m_Blocks.empty()) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back(); + VMA_ASSERT(pCurrBlock); + VkResult res = AllocateFromBlock( + pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG_FORMAT(" Returned from last block #%" PRIu32, pCurrBlock->GetId()); + IncrementallySortBlocks(); + return VK_SUCCESS; + } + } + } + else + { + if (strategy != VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT) // MIN_MEMORY or default + { + const bool isHostVisible = + (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0; + if(isHostVisible) + { + const bool isMappingAllowed = (createInfo.flags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0; + /* + For non-mappable allocations, check blocks that are not mapped first. + For mappable allocations, check blocks that are already mapped first. + This way, having many blocks, we will separate mappable and non-mappable allocations, + hopefully limiting the number of blocks that are mapped, which will help tools like RenderDoc. + */ + for(size_t mappingI = 0; mappingI < 2; ++mappingI) + { + // Forward order in m_Blocks - prefer blocks with smallest amount of free space. + for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pCurrBlock); + const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL; + if((mappingI == 0) == (isMappingAllowed == isBlockMapped)) + { + VkResult res = AllocateFromBlock( + pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG_FORMAT(" Returned from existing block #%" PRIu32, pCurrBlock->GetId()); + IncrementallySortBlocks(); + return VK_SUCCESS; + } + } + } + } + } + else + { + // Forward order in m_Blocks - prefer blocks with smallest amount of free space. + for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pCurrBlock); + VkResult res = AllocateFromBlock( + pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG_FORMAT(" Returned from existing block #%" PRIu32, pCurrBlock->GetId()); + IncrementallySortBlocks(); + return VK_SUCCESS; + } + } + } + } + else // VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT + { + // Backward order in m_Blocks - prefer blocks with largest amount of free space. + for (size_t blockIndex = m_Blocks.size(); blockIndex--; ) + { + VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pCurrBlock); + VkResult res = AllocateFromBlock(pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG_FORMAT(" Returned from existing block #%" PRIu32, pCurrBlock->GetId()); + IncrementallySortBlocks(); + return VK_SUCCESS; + } + } + } + } + + // 2. Try to create new block. + if (canCreateNewBlock) + { + // Calculate optimal size for new block. + VkDeviceSize newBlockSize = m_PreferredBlockSize; + uint32_t newBlockSizeShift = 0; + const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3; + + if (!m_ExplicitBlockSize) + { + // Allocate 1/8, 1/4, 1/2 as first blocks. + const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize(); + for (uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i) + { + const VkDeviceSize smallerNewBlockSize = newBlockSize / 2; + if (smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2) + { + newBlockSize = smallerNewBlockSize; + ++newBlockSizeShift; + } + else + { + break; + } + } + } + + size_t newBlockIndex = 0; + VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ? + CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY; + // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize. + if (!m_ExplicitBlockSize) + { + while (res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX) + { + const VkDeviceSize smallerNewBlockSize = newBlockSize / 2; + if (smallerNewBlockSize >= size) + { + newBlockSize = smallerNewBlockSize; + ++newBlockSizeShift; + res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ? + CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + else + { + break; + } + } + } + + if (res == VK_SUCCESS) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex]; + VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size); + + res = AllocateFromBlock( + pBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation); + if (res == VK_SUCCESS) + { + VMA_DEBUG_LOG_FORMAT(" Created new block #%" PRIu32 " Size=%" PRIu64, pBlock->GetId(), newBlockSize); + IncrementallySortBlocks(); + return VK_SUCCESS; + } + + // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment. + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + } + + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + +void VmaBlockVector::Free(VmaAllocation hAllocation) +{ + VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL; + + bool budgetExceeded = false; + { + const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex); + VmaBudget heapBudget = {}; + m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1); + budgetExceeded = heapBudget.usage >= heapBudget.budget; + } + + // Scope for lock. + { + VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex); + + VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock(); + + if (IsCorruptionDetectionEnabled()) + { + VkResult res = pBlock->ValidateMagicValueAfterAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize()); + VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value."); + } + + if (hAllocation->IsPersistentMap()) + { + pBlock->Unmap(m_hAllocator, 1); + } + + const bool hadEmptyBlockBeforeFree = HasEmptyBlock(); + pBlock->m_pMetadata->Free(hAllocation->GetAllocHandle()); + pBlock->PostFree(m_hAllocator); + VMA_HEAVY_ASSERT(pBlock->Validate()); + + VMA_DEBUG_LOG_FORMAT(" Freed from MemoryTypeIndex=%" PRIu32, m_MemoryTypeIndex); + + const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount; + // pBlock became empty after this deallocation. + if (pBlock->m_pMetadata->IsEmpty()) + { + // Already had empty block. We don't want to have two, so delete this one. + if ((hadEmptyBlockBeforeFree || budgetExceeded) && canDeleteBlock) + { + pBlockToDelete = pBlock; + Remove(pBlock); + } + // else: We now have one empty block - leave it. A hysteresis to avoid allocating whole block back and forth. + } + // pBlock didn't become empty, but we have another empty block - find and free that one. + // (This is optional, heuristics.) + else if (hadEmptyBlockBeforeFree && canDeleteBlock) + { + VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back(); + if (pLastBlock->m_pMetadata->IsEmpty()) + { + pBlockToDelete = pLastBlock; + m_Blocks.pop_back(); + } + } + + IncrementallySortBlocks(); + + m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize()); + hAllocation->Destroy(m_hAllocator); + m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation); + } + + // Destruction of a free block. Deferred until this point, outside of mutex + // lock, for performance reason. + if (pBlockToDelete != VMA_NULL) + { + VMA_DEBUG_LOG_FORMAT(" Deleted empty block #%" PRIu32, pBlockToDelete->GetId()); + pBlockToDelete->Destroy(m_hAllocator); + vma_delete(m_hAllocator, pBlockToDelete); + } +} + +VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const +{ + VkDeviceSize result = 0; + for (size_t i = m_Blocks.size(); i--; ) + { + result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize()); + if (result >= m_PreferredBlockSize) + { + break; + } + } + return result; +} + +void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock) +{ + for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + { + if (m_Blocks[blockIndex] == pBlock) + { + VmaVectorRemove(m_Blocks, blockIndex); + return; + } + } + VMA_ASSERT(0); +} + +void VmaBlockVector::IncrementallySortBlocks() +{ + if (!m_IncrementalSort) + return; + if (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) + { + // Bubble sort only until first swap. + for (size_t i = 1; i < m_Blocks.size(); ++i) + { + if (m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize()) + { + std::swap(m_Blocks[i - 1], m_Blocks[i]); + return; + } + } + } +} + +void VmaBlockVector::SortByFreeSize() +{ + VMA_SORT(m_Blocks.begin(), m_Blocks.end(), + [](VmaDeviceMemoryBlock* b1, VmaDeviceMemoryBlock* b2) -> bool + { + return b1->m_pMetadata->GetSumFreeSize() < b2->m_pMetadata->GetSumFreeSize(); + }); +} + +VkResult VmaBlockVector::AllocateFromBlock( + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize size, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + uint32_t strategy, + VmaAllocation* pAllocation) +{ + const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0; + + VmaAllocationRequest currRequest = {}; + if (pBlock->m_pMetadata->CreateAllocationRequest( + size, + alignment, + isUpperAddress, + suballocType, + strategy, + &currRequest)) + { + return CommitAllocationRequest(currRequest, pBlock, alignment, allocFlags, pUserData, suballocType, pAllocation); + } + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + +VkResult VmaBlockVector::CommitAllocationRequest( + VmaAllocationRequest& allocRequest, + VmaDeviceMemoryBlock* pBlock, + VkDeviceSize alignment, + VmaAllocationCreateFlags allocFlags, + void* pUserData, + VmaSuballocationType suballocType, + VmaAllocation* pAllocation) +{ + const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0; + const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0; + const bool isMappingAllowed = (allocFlags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0; + + pBlock->PostAlloc(m_hAllocator); + // Allocate from pCurrBlock. + if (mapped) + { + VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL); + if (res != VK_SUCCESS) + { + return res; + } + } + + *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(isMappingAllowed); + pBlock->m_pMetadata->Alloc(allocRequest, suballocType, *pAllocation); + (*pAllocation)->InitBlockAllocation( + pBlock, + allocRequest.allocHandle, + alignment, + allocRequest.size, // Not size, as actual allocation size may be larger than requested! + m_MemoryTypeIndex, + suballocType, + mapped); + VMA_HEAVY_ASSERT(pBlock->Validate()); + if (isUserDataString) + (*pAllocation)->SetName(m_hAllocator, (const char*)pUserData); + else + (*pAllocation)->SetUserData(m_hAllocator, pUserData); + m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), allocRequest.size); + if (VMA_DEBUG_INITIALIZE_ALLOCATIONS) + { + m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED); + } + if (IsCorruptionDetectionEnabled()) + { + VkResult res = pBlock->WriteMagicValueAfterAllocation(m_hAllocator, (*pAllocation)->GetOffset(), allocRequest.size); + VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value."); + } + return VK_SUCCESS; +} + +VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex) +{ + VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + allocInfo.pNext = m_pMemoryAllocateNext; + allocInfo.memoryTypeIndex = m_MemoryTypeIndex; + allocInfo.allocationSize = blockSize; + +#if VMA_BUFFER_DEVICE_ADDRESS + // Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature. + VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR }; + if (m_hAllocator->m_UseKhrBufferDeviceAddress) + { + allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo); + } +#endif // VMA_BUFFER_DEVICE_ADDRESS + +#if VMA_MEMORY_PRIORITY + VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; + if (m_hAllocator->m_UseExtMemoryPriority) + { + VMA_ASSERT(m_Priority >= 0.F && m_Priority <= 1.F); + priorityInfo.priority = m_Priority; + VmaPnextChainPushFront(&allocInfo, &priorityInfo); + } +#endif // VMA_MEMORY_PRIORITY + +#if VMA_EXTERNAL_MEMORY + // Attach VkExportMemoryAllocateInfoKHR if necessary. + VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; + exportMemoryAllocInfo.handleTypes = m_hAllocator->GetExternalMemoryHandleTypeFlags(m_MemoryTypeIndex); + if (exportMemoryAllocInfo.handleTypes != 0) + { + VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo); + } +#endif // VMA_EXTERNAL_MEMORY + + VkDeviceMemory mem = VK_NULL_HANDLE; + VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem); + if (res < 0) + { + return res; + } + + // New VkDeviceMemory successfully created. + + // Create new Allocation for it. + VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator); + pBlock->Init( + m_hAllocator, + m_hParentPool, + m_MemoryTypeIndex, + mem, + allocInfo.allocationSize, + m_NextBlockId++, + m_Algorithm, + m_BufferImageGranularity); + + m_Blocks.push_back(pBlock); + if (pNewBlockIndex != VMA_NULL) + { + *pNewBlockIndex = m_Blocks.size() - 1; + } + + return VK_SUCCESS; +} + +bool VmaBlockVector::HasEmptyBlock() +{ + for (size_t index = 0, count = m_Blocks.size(); index < count; ++index) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[index]; + if (pBlock->m_pMetadata->IsEmpty()) + { + return true; + } + } + return false; +} + +#if VMA_STATS_STRING_ENABLED +void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json) +{ + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + + + json.BeginObject(); + for (size_t i = 0; i < m_Blocks.size(); ++i) + { + json.BeginString(); + json.ContinueString(m_Blocks[i]->GetId()); + json.EndString(); + + json.BeginObject(); + json.WriteString("MapRefCount"); + json.WriteNumber(m_Blocks[i]->GetMapRefCount()); + + m_Blocks[i]->m_pMetadata->PrintDetailedMap(json); + json.EndObject(); + } + json.EndObject(); +} +#endif // VMA_STATS_STRING_ENABLED + +VkResult VmaBlockVector::CheckCorruption() +{ + if (!IsCorruptionDetectionEnabled()) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex); + for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex) + { + VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex]; + VMA_ASSERT(pBlock); + VkResult res = pBlock->CheckCorruption(m_hAllocator); + if (res != VK_SUCCESS) + { + return res; + } + } + return VK_SUCCESS; +} + +#endif // _VMA_BLOCK_VECTOR_FUNCTIONS + +#ifndef _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS +VmaDefragmentationContext_T::VmaDefragmentationContext_T( + VmaAllocator hAllocator, + const VmaDefragmentationInfo& info) + : m_MaxPassBytes(info.maxBytesPerPass == 0 ? VK_WHOLE_SIZE : info.maxBytesPerPass), + m_MaxPassAllocations(info.maxAllocationsPerPass == 0 ? UINT32_MAX : info.maxAllocationsPerPass), + m_BreakCallback(info.pfnBreakCallback), + m_BreakCallbackUserData(info.pBreakCallbackUserData), + m_MoveAllocator(hAllocator->GetAllocationCallbacks()), + m_Moves(m_MoveAllocator), + m_Algorithm(info.flags & VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK) +{ + if (info.pool != VMA_NULL) + { + m_BlockVectorCount = 1; + m_PoolBlockVector = &info.pool->m_BlockVector; + m_pBlockVectors = &m_PoolBlockVector; + m_PoolBlockVector->SetIncrementalSort(false); + m_PoolBlockVector->SortByFreeSize(); + } + else + { + m_BlockVectorCount = hAllocator->GetMemoryTypeCount(); + m_PoolBlockVector = VMA_NULL; + m_pBlockVectors = hAllocator->m_pBlockVectors; + for (uint32_t i = 0; i < m_BlockVectorCount; ++i) + { + VmaBlockVector* vector = m_pBlockVectors[i]; + if (vector != VMA_NULL) + { + vector->SetIncrementalSort(false); + vector->SortByFreeSize(); + } + } + } + + switch (m_Algorithm) + { + case 0: // Default algorithm + m_Algorithm = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT; + m_AlgorithmState = vma_new_array(hAllocator, StateBalanced, m_BlockVectorCount); + break; + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT: + m_AlgorithmState = vma_new_array(hAllocator, StateBalanced, m_BlockVectorCount); + break; + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT: + if (hAllocator->GetBufferImageGranularity() > 1) + { + m_AlgorithmState = vma_new_array(hAllocator, StateExtensive, m_BlockVectorCount); + } + break; + default: + ; // Do nothing. + } +} + +VmaDefragmentationContext_T::~VmaDefragmentationContext_T() +{ + if (m_PoolBlockVector != VMA_NULL) + { + m_PoolBlockVector->SetIncrementalSort(true); + } + else + { + for (uint32_t i = 0; i < m_BlockVectorCount; ++i) + { + VmaBlockVector* vector = m_pBlockVectors[i]; + if (vector != VMA_NULL) + vector->SetIncrementalSort(true); + } + } + + if (m_AlgorithmState) + { + switch (m_Algorithm) + { + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT: + vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast(m_AlgorithmState), m_BlockVectorCount); + break; + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT: + vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast(m_AlgorithmState), m_BlockVectorCount); + break; + default: + VMA_ASSERT(0); + } + } +} + +VkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo) +{ + if (m_PoolBlockVector != VMA_NULL) + { + VmaMutexLockWrite lock(m_PoolBlockVector->GetMutex(), m_PoolBlockVector->GetAllocator()->m_UseMutex); + + if (m_PoolBlockVector->GetBlockCount() > 1) + ComputeDefragmentation(*m_PoolBlockVector, 0); + else if (m_PoolBlockVector->GetBlockCount() == 1) + ReallocWithinBlock(*m_PoolBlockVector, m_PoolBlockVector->GetBlock(0)); + } + else + { + for (uint32_t i = 0; i < m_BlockVectorCount; ++i) + { + if (m_pBlockVectors[i] != VMA_NULL) + { + VmaMutexLockWrite lock(m_pBlockVectors[i]->GetMutex(), m_pBlockVectors[i]->GetAllocator()->m_UseMutex); + + if (m_pBlockVectors[i]->GetBlockCount() > 1) + { + if (ComputeDefragmentation(*m_pBlockVectors[i], i)) + break; + } + else if (m_pBlockVectors[i]->GetBlockCount() == 1) + { + if (ReallocWithinBlock(*m_pBlockVectors[i], m_pBlockVectors[i]->GetBlock(0))) + break; + } + } + } + } + + moveInfo.moveCount = static_cast(m_Moves.size()); + if (moveInfo.moveCount > 0) + { + moveInfo.pMoves = m_Moves.data(); + return VK_INCOMPLETE; + } + + moveInfo.pMoves = VMA_NULL; + return VK_SUCCESS; +} + +VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo) +{ + VMA_ASSERT(moveInfo.moveCount > 0 ? moveInfo.pMoves != VMA_NULL : true); + + VkResult result = VK_SUCCESS; + VmaStlAllocator blockAllocator(m_MoveAllocator.m_pCallbacks); + VmaVector> immovableBlocks(blockAllocator); + VmaVector> mappedBlocks(blockAllocator); + + VmaAllocator allocator = VMA_NULL; + for (uint32_t i = 0; i < moveInfo.moveCount; ++i) + { + VmaDefragmentationMove& move = moveInfo.pMoves[i]; + size_t prevCount = 0; + size_t currentCount = 0; + VkDeviceSize freedBlockSize = 0; + + uint32_t vectorIndex = 0; + VmaBlockVector* vector = VMA_NULL; + if (m_PoolBlockVector != VMA_NULL) + { + vector = m_PoolBlockVector; + } + else + { + vectorIndex = move.srcAllocation->GetMemoryTypeIndex(); + vector = m_pBlockVectors[vectorIndex]; + VMA_ASSERT(vector != VMA_NULL); + } + + switch (move.operation) + { + case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY: + { + uint8_t mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation); + if (mapCount > 0) + { + allocator = vector->m_hAllocator; + VmaDeviceMemoryBlock* newMapBlock = move.srcAllocation->GetBlock(); + bool notPresent = true; + for (FragmentedBlock& block : mappedBlocks) + { + if (block.block == newMapBlock) + { + notPresent = false; + block.data += mapCount; + break; + } + } + if (notPresent) + mappedBlocks.push_back({ mapCount, newMapBlock }); + } + + // Scope for locks, Free have it's own lock + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + prevCount = vector->GetBlockCount(); + freedBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize(); + } + vector->Free(move.dstTmpAllocation); + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + currentCount = vector->GetBlockCount(); + } + + result = VK_INCOMPLETE; + break; + } + case VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE: + { + m_PassStats.bytesMoved -= move.srcAllocation->GetSize(); + --m_PassStats.allocationsMoved; + vector->Free(move.dstTmpAllocation); + + VmaDeviceMemoryBlock* newBlock = move.srcAllocation->GetBlock(); + bool notPresent = true; + for (const FragmentedBlock& block : immovableBlocks) + { + if (block.block == newBlock) + { + notPresent = false; + break; + } + } + if (notPresent) + immovableBlocks.push_back({ vectorIndex, newBlock }); + break; + } + case VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY: + { + m_PassStats.bytesMoved -= move.srcAllocation->GetSize(); + --m_PassStats.allocationsMoved; + // Scope for locks, Free have it's own lock + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + prevCount = vector->GetBlockCount(); + freedBlockSize = move.srcAllocation->GetBlock()->m_pMetadata->GetSize(); + } + vector->Free(move.srcAllocation); + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + currentCount = vector->GetBlockCount(); + } + freedBlockSize *= prevCount - currentCount; + + VkDeviceSize dstBlockSize = SIZE_MAX; + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + dstBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize(); + } + vector->Free(move.dstTmpAllocation); + { + VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + freedBlockSize += dstBlockSize * (currentCount - vector->GetBlockCount()); + currentCount = vector->GetBlockCount(); + } + + result = VK_INCOMPLETE; + break; + } + default: + VMA_ASSERT(0); + } + + if (prevCount > currentCount) + { + size_t freedBlocks = prevCount - currentCount; + m_PassStats.deviceMemoryBlocksFreed += static_cast(freedBlocks); + m_PassStats.bytesFreed += freedBlockSize; + } + + if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT && + m_AlgorithmState != VMA_NULL) + { + // Avoid unnecessary tries to allocate when new free block is available + StateExtensive& state = reinterpret_cast(m_AlgorithmState)[vectorIndex]; + if (state.firstFreeBlock != SIZE_MAX) + { + const size_t diff = prevCount - currentCount; + if (state.firstFreeBlock >= diff) + { + state.firstFreeBlock -= diff; + if (state.firstFreeBlock != 0) + state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty(); + } + else + state.firstFreeBlock = 0; + } + } + } + moveInfo.moveCount = 0; + moveInfo.pMoves = VMA_NULL; + m_Moves.clear(); + + // Update stats + m_GlobalStats.allocationsMoved += m_PassStats.allocationsMoved; + m_GlobalStats.bytesFreed += m_PassStats.bytesFreed; + m_GlobalStats.bytesMoved += m_PassStats.bytesMoved; + m_GlobalStats.deviceMemoryBlocksFreed += m_PassStats.deviceMemoryBlocksFreed; + m_PassStats = { 0 }; + + // Move blocks with immovable allocations according to algorithm + if (!immovableBlocks.empty()) + { + do + { + if(m_Algorithm == VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT) + { + if (m_AlgorithmState != VMA_NULL) + { + bool swapped = false; + // Move to the start of free blocks range + for (const FragmentedBlock& block : immovableBlocks) + { + StateExtensive& state = reinterpret_cast(m_AlgorithmState)[block.data]; + if (state.operation != StateExtensive::Operation::Cleanup) + { + VmaBlockVector* vector = m_pBlockVectors[block.data]; + VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + + for (size_t i = 0, count = vector->GetBlockCount() - m_ImmovableBlockCount; i < count; ++i) + { + if (vector->GetBlock(i) == block.block) + { + std::swap(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]); + if (state.firstFreeBlock != SIZE_MAX) + { + if (i + 1 < state.firstFreeBlock) + { + if (state.firstFreeBlock > 1) + std::swap(vector->m_Blocks[i], vector->m_Blocks[--state.firstFreeBlock]); + else + --state.firstFreeBlock; + } + } + swapped = true; + break; + } + } + } + } + if (swapped) + result = VK_INCOMPLETE; + break; + } + } + + // Move to the beginning + for (const FragmentedBlock& block : immovableBlocks) + { + VmaBlockVector* vector = m_pBlockVectors[block.data]; + VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex); + + for (size_t i = m_ImmovableBlockCount; i < vector->GetBlockCount(); ++i) + { + if (vector->GetBlock(i) == block.block) + { + std::swap(vector->m_Blocks[i], vector->m_Blocks[m_ImmovableBlockCount++]); + break; + } + } + } + } while (false); + } + + // Bulk-map destination blocks + for (const FragmentedBlock& block : mappedBlocks) + { + VkResult res = block.block->Map(allocator, block.data, VMA_NULL); + VMA_ASSERT(res == VK_SUCCESS); + } + return result; +} + +bool VmaDefragmentationContext_T::ComputeDefragmentation(VmaBlockVector& vector, size_t index) +{ + switch (m_Algorithm) + { + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT: + return ComputeDefragmentation_Fast(vector); + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT: + return ComputeDefragmentation_Balanced(vector, index, true); + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT: + return ComputeDefragmentation_Full(vector); + case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT: + return ComputeDefragmentation_Extensive(vector, index); + default: + VMA_ASSERT(0); + return ComputeDefragmentation_Balanced(vector, index, true); + } +} + +VmaDefragmentationContext_T::MoveAllocationData VmaDefragmentationContext_T::GetMoveData( + VmaAllocHandle handle, VmaBlockMetadata* metadata) +{ + MoveAllocationData moveData; + moveData.move.srcAllocation = (VmaAllocation)metadata->GetAllocationUserData(handle); + moveData.size = moveData.move.srcAllocation->GetSize(); + moveData.alignment = moveData.move.srcAllocation->GetAlignment(); + moveData.type = moveData.move.srcAllocation->GetSuballocationType(); + moveData.flags = 0; + + if (moveData.move.srcAllocation->IsPersistentMap()) + moveData.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT; + if (moveData.move.srcAllocation->IsMappingAllowed()) + moveData.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; + + return moveData; +} + +VmaDefragmentationContext_T::CounterStatus VmaDefragmentationContext_T::CheckCounters(VkDeviceSize bytes) +{ + // Check custom criteria if exists + if (m_BreakCallback && m_BreakCallback(m_BreakCallbackUserData)) + return CounterStatus::End; + + // Ignore allocation if will exceed max size for copy + if (m_PassStats.bytesMoved + bytes > m_MaxPassBytes) + { + if (++m_IgnoredAllocs < MAX_ALLOCS_TO_IGNORE) + return CounterStatus::Ignore; + return CounterStatus::End; + } + + m_IgnoredAllocs = 0; + return CounterStatus::Pass; +} + +bool VmaDefragmentationContext_T::IncrementCounters(VkDeviceSize bytes) +{ + m_PassStats.bytesMoved += bytes; + // Early return when max found + if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes) + { + VMA_ASSERT((m_PassStats.allocationsMoved == m_MaxPassAllocations || + m_PassStats.bytesMoved == m_MaxPassBytes) && "Exceeded maximal pass threshold!"); + return true; + } + return false; +} + +bool VmaDefragmentationContext_T::ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block) +{ + VmaBlockMetadata* metadata = block->m_pMetadata; + + for (VmaAllocHandle handle = metadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = metadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, metadata); + // Ignore newly created allocations by defragmentation algorithm + if (moveData.move.srcAllocation->GetUserData() == this) + continue; + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + VkDeviceSize offset = moveData.move.srcAllocation->GetOffset(); + if (offset != 0 && metadata->GetSumFreeSize() >= moveData.size) + { + VmaAllocationRequest request = {}; + if (metadata->CreateAllocationRequest( + moveData.size, + moveData.alignment, + false, + moveData.type, + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + &request)) + { + if (metadata->GetAllocationOffset(request.allocHandle) < offset) + { + if (vector.CommitAllocationRequest( + request, + block, + moveData.alignment, + moveData.flags, + this, + moveData.type, + &moveData.move.dstTmpAllocation) == VK_SUCCESS) + { + m_Moves.push_back(moveData.move); + if (IncrementCounters(moveData.size)) + return true; + } + } + } + } + } + return false; +} + +bool VmaDefragmentationContext_T::AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector) +{ + for (; start < end; ++start) + { + VmaDeviceMemoryBlock* dstBlock = vector.GetBlock(start); + if (dstBlock->m_pMetadata->GetSumFreeSize() >= data.size) + { + if (vector.AllocateFromBlock(dstBlock, + data.size, + data.alignment, + data.flags, + this, + data.type, + 0, + &data.move.dstTmpAllocation) == VK_SUCCESS) + { + m_Moves.push_back(data.move); + if (IncrementCounters(data.size)) + return true; + break; + } + } + } + return false; +} + +bool VmaDefragmentationContext_T::ComputeDefragmentation_Fast(VmaBlockVector& vector) +{ + // Move only between blocks + + // Go through allocations in last blocks and try to fit them inside first ones + for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i) + { + VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata; + + for (VmaAllocHandle handle = metadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = metadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, metadata); + // Ignore newly created allocations by defragmentation algorithm + if (moveData.move.srcAllocation->GetUserData() == this) + continue; + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + // Check all previous blocks for free space + if (AllocInOtherBlock(0, i, moveData, vector)) + return true; + } + } + return false; +} + +bool VmaDefragmentationContext_T::ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update) +{ + // Go over every allocation and try to fit it in previous blocks at lowest offsets, + // if not possible: realloc within single block to minimize offset (exclude offset == 0), + // but only if there are noticeable gaps between them (some heuristic, ex. average size of allocation in block) + VMA_ASSERT(m_AlgorithmState != VMA_NULL); + + StateBalanced& vectorState = reinterpret_cast(m_AlgorithmState)[index]; + if (update && vectorState.avgAllocSize == UINT64_MAX) + UpdateVectorStatistics(vector, vectorState); + + const size_t startMoveCount = m_Moves.size(); + VkDeviceSize minimalFreeRegion = vectorState.avgFreeSize / 2; + for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i) + { + VmaDeviceMemoryBlock* block = vector.GetBlock(i); + VmaBlockMetadata* metadata = block->m_pMetadata; + VkDeviceSize prevFreeRegionSize = 0; + + for (VmaAllocHandle handle = metadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = metadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, metadata); + // Ignore newly created allocations by defragmentation algorithm + if (moveData.move.srcAllocation->GetUserData() == this) + continue; + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + // Check all previous blocks for free space + const size_t prevMoveCount = m_Moves.size(); + if (AllocInOtherBlock(0, i, moveData, vector)) + return true; + + VkDeviceSize nextFreeRegionSize = metadata->GetNextFreeRegionSize(handle); + // If no room found then realloc within block for lower offset + VkDeviceSize offset = moveData.move.srcAllocation->GetOffset(); + if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size) + { + // Check if realloc will make sense + if (prevFreeRegionSize >= minimalFreeRegion || + nextFreeRegionSize >= minimalFreeRegion || + moveData.size <= vectorState.avgFreeSize || + moveData.size <= vectorState.avgAllocSize) + { + VmaAllocationRequest request = {}; + if (metadata->CreateAllocationRequest( + moveData.size, + moveData.alignment, + false, + moveData.type, + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + &request)) + { + if (metadata->GetAllocationOffset(request.allocHandle) < offset) + { + if (vector.CommitAllocationRequest( + request, + block, + moveData.alignment, + moveData.flags, + this, + moveData.type, + &moveData.move.dstTmpAllocation) == VK_SUCCESS) + { + m_Moves.push_back(moveData.move); + if (IncrementCounters(moveData.size)) + return true; + } + } + } + } + } + prevFreeRegionSize = nextFreeRegionSize; + } + } + + // No moves performed, update statistics to current vector state + if (startMoveCount == m_Moves.size() && !update) + { + vectorState.avgAllocSize = UINT64_MAX; + return ComputeDefragmentation_Balanced(vector, index, false); + } + return false; +} + +bool VmaDefragmentationContext_T::ComputeDefragmentation_Full(VmaBlockVector& vector) +{ + // Go over every allocation and try to fit it in previous blocks at lowest offsets, + // if not possible: realloc within single block to minimize offset (exclude offset == 0) + + for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i) + { + VmaDeviceMemoryBlock* block = vector.GetBlock(i); + VmaBlockMetadata* metadata = block->m_pMetadata; + + for (VmaAllocHandle handle = metadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = metadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, metadata); + // Ignore newly created allocations by defragmentation algorithm + if (moveData.move.srcAllocation->GetUserData() == this) + continue; + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + // Check all previous blocks for free space + const size_t prevMoveCount = m_Moves.size(); + if (AllocInOtherBlock(0, i, moveData, vector)) + return true; + + // If no room found then realloc within block for lower offset + VkDeviceSize offset = moveData.move.srcAllocation->GetOffset(); + if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size) + { + VmaAllocationRequest request = {}; + if (metadata->CreateAllocationRequest( + moveData.size, + moveData.alignment, + false, + moveData.type, + VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT, + &request)) + { + if (metadata->GetAllocationOffset(request.allocHandle) < offset) + { + if (vector.CommitAllocationRequest( + request, + block, + moveData.alignment, + moveData.flags, + this, + moveData.type, + &moveData.move.dstTmpAllocation) == VK_SUCCESS) + { + m_Moves.push_back(moveData.move); + if (IncrementCounters(moveData.size)) + return true; + } + } + } + } + } + } + return false; +} + +bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index) +{ + // First free single block, then populate it to the brim, then free another block, and so on + + // Fallback to previous algorithm since without granularity conflicts it can achieve max packing + if (vector.m_BufferImageGranularity == 1) + return ComputeDefragmentation_Full(vector); + + VMA_ASSERT(m_AlgorithmState != VMA_NULL); + + StateExtensive& vectorState = reinterpret_cast(m_AlgorithmState)[index]; + + bool texturePresent = false; + bool bufferPresent = false; + bool otherPresent = false; + switch (vectorState.operation) + { + case StateExtensive::Operation::Done: // Vector defragmented + return false; + case StateExtensive::Operation::FindFreeBlockBuffer: + case StateExtensive::Operation::FindFreeBlockTexture: + case StateExtensive::Operation::FindFreeBlockAll: + { + // No more blocks to free, just perform fast realloc and move to cleanup + if (vectorState.firstFreeBlock == 0) + { + vectorState.operation = StateExtensive::Operation::Cleanup; + return ComputeDefragmentation_Fast(vector); + } + + // No free blocks, have to clear last one + size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1; + VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata; + + const size_t prevMoveCount = m_Moves.size(); + for (VmaAllocHandle handle = freeMetadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = freeMetadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, freeMetadata); + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + // Check all previous blocks for free space + if (AllocInOtherBlock(0, last, moveData, vector)) + { + // Full clear performed already + if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE) + vectorState.firstFreeBlock = last; + return true; + } + } + + if (prevMoveCount == m_Moves.size()) + { + // Cannot perform full clear, have to move data in other blocks around + if (last != 0) + { + for (size_t i = last - 1; i; --i) + { + if (ReallocWithinBlock(vector, vector.GetBlock(i))) + return true; + } + } + + if (prevMoveCount == m_Moves.size()) + { + // No possible reallocs within blocks, try to move them around fast + return ComputeDefragmentation_Fast(vector); + } + } + else + { + switch (vectorState.operation) + { + case StateExtensive::Operation::FindFreeBlockBuffer: + vectorState.operation = StateExtensive::Operation::MoveBuffers; + break; + case StateExtensive::Operation::FindFreeBlockTexture: + vectorState.operation = StateExtensive::Operation::MoveTextures; + break; + case StateExtensive::Operation::FindFreeBlockAll: + vectorState.operation = StateExtensive::Operation::MoveAll; + break; + default: + VMA_ASSERT(0); + vectorState.operation = StateExtensive::Operation::MoveTextures; + } + vectorState.firstFreeBlock = last; + // Nothing done, block found without reallocations, can perform another reallocs in same pass + return ComputeDefragmentation_Extensive(vector, index); + } + break; + } + case StateExtensive::Operation::MoveTextures: + { + if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL, vector, + vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent)) + { + if (texturePresent) + { + vectorState.operation = StateExtensive::Operation::FindFreeBlockTexture; + return ComputeDefragmentation_Extensive(vector, index); + } + + if (!bufferPresent && !otherPresent) + { + vectorState.operation = StateExtensive::Operation::Cleanup; + break; + } + + // No more textures to move, check buffers + vectorState.operation = StateExtensive::Operation::MoveBuffers; + bufferPresent = false; + otherPresent = false; + } + else + break; + VMA_FALLTHROUGH; // Fallthrough + } + case StateExtensive::Operation::MoveBuffers: + { + if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_BUFFER, vector, + vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent)) + { + if (bufferPresent) + { + vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer; + return ComputeDefragmentation_Extensive(vector, index); + } + + if (!otherPresent) + { + vectorState.operation = StateExtensive::Operation::Cleanup; + break; + } + + // No more buffers to move, check all others + vectorState.operation = StateExtensive::Operation::MoveAll; + otherPresent = false; + } + else + break; + VMA_FALLTHROUGH; // Fallthrough + } + case StateExtensive::Operation::MoveAll: + { + if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_FREE, vector, + vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent)) + { + if (otherPresent) + { + vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer; + return ComputeDefragmentation_Extensive(vector, index); + } + // Everything moved + vectorState.operation = StateExtensive::Operation::Cleanup; + } + break; + } + case StateExtensive::Operation::Cleanup: + // Cleanup is handled below so that other operations may reuse the cleanup code. This case is here to prevent the unhandled enum value warning (C4062). + break; + } + + if (vectorState.operation == StateExtensive::Operation::Cleanup) + { + // All other work done, pack data in blocks even tighter if possible + const size_t prevMoveCount = m_Moves.size(); + for (size_t i = 0; i < vector.GetBlockCount(); ++i) + { + if (ReallocWithinBlock(vector, vector.GetBlock(i))) + return true; + } + + if (prevMoveCount == m_Moves.size()) + vectorState.operation = StateExtensive::Operation::Done; + } + return false; +} + +void VmaDefragmentationContext_T::UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state) +{ + size_t allocCount = 0; + size_t freeCount = 0; + state.avgFreeSize = 0; + state.avgAllocSize = 0; + + for (size_t i = 0; i < vector.GetBlockCount(); ++i) + { + VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata; + + allocCount += metadata->GetAllocationCount(); + freeCount += metadata->GetFreeRegionsCount(); + state.avgFreeSize += metadata->GetSumFreeSize(); + state.avgAllocSize += metadata->GetSize(); + } + + state.avgAllocSize = (state.avgAllocSize - state.avgFreeSize) / allocCount; + state.avgFreeSize /= freeCount; +} + +bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType, + VmaBlockVector& vector, size_t firstFreeBlock, + bool& texturePresent, bool& bufferPresent, bool& otherPresent) +{ + const size_t prevMoveCount = m_Moves.size(); + for (size_t i = firstFreeBlock ; i;) + { + VmaDeviceMemoryBlock* block = vector.GetBlock(--i); + VmaBlockMetadata* metadata = block->m_pMetadata; + + for (VmaAllocHandle handle = metadata->GetAllocationListBegin(); + handle != VK_NULL_HANDLE; + handle = metadata->GetNextAllocation(handle)) + { + MoveAllocationData moveData = GetMoveData(handle, metadata); + // Ignore newly created allocations by defragmentation algorithm + if (moveData.move.srcAllocation->GetUserData() == this) + continue; + switch (CheckCounters(moveData.move.srcAllocation->GetSize())) + { + case CounterStatus::Ignore: + continue; + case CounterStatus::End: + return true; + case CounterStatus::Pass: + break; + default: + VMA_ASSERT(0); + } + + // Move only single type of resources at once + if (!VmaIsBufferImageGranularityConflict(moveData.type, currentType)) + { + // Try to fit allocation into free blocks + if (AllocInOtherBlock(firstFreeBlock, vector.GetBlockCount(), moveData, vector)) + return false; + } + + if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)) + texturePresent = true; + else if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_BUFFER)) + bufferPresent = true; + else + otherPresent = true; + } + } + return prevMoveCount == m_Moves.size(); +} +#endif // _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS + +#ifndef _VMA_POOL_T_FUNCTIONS +VmaPool_T::VmaPool_T( + VmaAllocator hAllocator, + const VmaPoolCreateInfo& createInfo, + VkDeviceSize preferredBlockSize) + : m_BlockVector( + hAllocator, + this, // hParentPool + createInfo.memoryTypeIndex, + createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize, + createInfo.minBlockCount, + createInfo.maxBlockCount, + (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(), + createInfo.blockSize != 0, // explicitBlockSize + createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm + createInfo.priority, + VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment), + createInfo.pMemoryAllocateNext), + m_Id(0), + m_Name(VMA_NULL) {} + +VmaPool_T::~VmaPool_T() +{ + VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL); + + const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks(); + VmaFreeString(allocs, m_Name); +} + +void VmaPool_T::SetName(const char* pName) +{ + const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks(); + VmaFreeString(allocs, m_Name); + + if (pName != VMA_NULL) + { + m_Name = VmaCreateStringCopy(allocs, pName); + } + else + { + m_Name = VMA_NULL; + } +} +#endif // _VMA_POOL_T_FUNCTIONS + +#ifndef _VMA_ALLOCATOR_T_FUNCTIONS +VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) : + m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0), + m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0), + m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0), + m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0), + m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0), + m_UseAmdDeviceCoherentMemory((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0), + m_UseKhrBufferDeviceAddress((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0), + m_UseExtMemoryPriority((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT) != 0), + m_UseKhrMaintenance4((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0), + m_UseKhrMaintenance5((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT) != 0), + m_UseKhrExternalMemoryWin32((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0), + m_hDevice(pCreateInfo->device), + m_hInstance(pCreateInfo->instance), + m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL), + m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ? + *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks), + m_AllocationObjectAllocator(&m_AllocationCallbacks), + m_HeapSizeLimitMask(0), + m_DeviceMemoryCount(0), + m_PreferredLargeHeapBlockSize(0), + m_PhysicalDevice(pCreateInfo->physicalDevice), + m_GpuDefragmentationMemoryTypeBits(UINT32_MAX), + m_NextPoolId(0), + m_GlobalMemoryTypeBits(UINT32_MAX) +{ + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + m_UseKhrDedicatedAllocation = false; + m_UseKhrBindMemory2 = false; + } + + if(VMA_DEBUG_DETECT_CORRUPTION) + { + // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it. + VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0); + } + + VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device && pCreateInfo->instance); + + if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0)) + { +#if !(VMA_DEDICATED_ALLOCATION) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros."); + } +#endif +#if !(VMA_BIND_MEMORY2) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros."); + } +#endif + } +#if !(VMA_MEMORY_BUDGET) + if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros."); + } +#endif +#if !(VMA_BUFFER_DEVICE_ADDRESS) + if(m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif +#if VMA_VULKAN_VERSION < 1004000 + VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 4, 0) && "vulkanApiVersion >= VK_API_VERSION_1_4 but required Vulkan version is disabled by preprocessor macros."); +#endif +#if VMA_VULKAN_VERSION < 1003000 + VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 3, 0) && "vulkanApiVersion >= VK_API_VERSION_1_3 but required Vulkan version is disabled by preprocessor macros."); +#endif +#if VMA_VULKAN_VERSION < 1002000 + VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 2, 0) && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros."); +#endif +#if VMA_VULKAN_VERSION < 1001000 + VMA_ASSERT(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0) && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros."); +#endif +#if !(VMA_MEMORY_PRIORITY) + if(m_UseExtMemoryPriority) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif +#if !(VMA_KHR_MAINTENANCE4) + if(m_UseKhrMaintenance4) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif +#if !(VMA_KHR_MAINTENANCE5) + if(m_UseKhrMaintenance5) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif +#if !(VMA_KHR_MAINTENANCE5) + if(m_UseKhrMaintenance5) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif + +#if !(VMA_EXTERNAL_MEMORY_WIN32) + if(m_UseKhrExternalMemoryWin32) + { + VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT is set but required extension is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro."); + } +#endif + + memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks)); + memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties)); + memset(&m_MemProps, 0, sizeof(m_MemProps)); + + memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors)); + memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions)); + +#if VMA_EXTERNAL_MEMORY + memset(&m_TypeExternalMemoryHandleTypes, 0, sizeof(m_TypeExternalMemoryHandleTypes)); +#endif // #if VMA_EXTERNAL_MEMORY + + if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL) + { + m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData; + m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate; + m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree; + } + + ImportVulkanFunctions(pCreateInfo->pVulkanFunctions); + + (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties); + (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps); + + VMA_ASSERT(VmaIsPow2(VMA_MIN_ALIGNMENT)); + VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY)); + VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity)); + VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize)); + + m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ? + pCreateInfo->preferredLargeHeapBlockSize : static_cast(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE); + + m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits(); + +#if VMA_EXTERNAL_MEMORY + if(pCreateInfo->pTypeExternalMemoryHandleTypes != VMA_NULL) + { + memcpy(m_TypeExternalMemoryHandleTypes, pCreateInfo->pTypeExternalMemoryHandleTypes, + sizeof(VkExternalMemoryHandleTypeFlagsKHR) * GetMemoryTypeCount()); + } +#endif // #if VMA_EXTERNAL_MEMORY + + if(pCreateInfo->pHeapSizeLimit != VMA_NULL) + { + for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) + { + const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex]; + if(limit != VK_WHOLE_SIZE) + { + m_HeapSizeLimitMask |= 1U << heapIndex; + if(limit < m_MemProps.memoryHeaps[heapIndex].size) + { + m_MemProps.memoryHeaps[heapIndex].size = limit; + } + } + } + } + + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + // Create only supported types + if((m_GlobalMemoryTypeBits & (1U << memTypeIndex)) != 0) + { + const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex); + m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)( + this, + VK_NULL_HANDLE, // hParentPool + memTypeIndex, + preferredBlockSize, + 0, + SIZE_MAX, + GetBufferImageGranularity(), + false, // explicitBlockSize + 0, // algorithm + 0.5F, // priority (0.5 is the default per Vulkan spec) + GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment + VMA_NULL); // // pMemoryAllocateNext + // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here, + // because minBlockCount is 0. + } + } +} + +VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo) +{ + VkResult res = VK_SUCCESS; + +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + UpdateVulkanBudget(); + } +#endif // #if VMA_MEMORY_BUDGET + + return res; +} + +VmaAllocator_T::~VmaAllocator_T() +{ + VMA_ASSERT(m_Pools.IsEmpty()); + + for(size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; ) + { + vma_delete(this, m_pBlockVectors[memTypeIndex]); + } +} + +void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions) +{ +#if VMA_STATIC_VULKAN_FUNCTIONS == 1 + ImportVulkanFunctions_Static(); +#endif + + if(pVulkanFunctions != VMA_NULL) + { + ImportVulkanFunctions_Custom(pVulkanFunctions); + } + +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + ImportVulkanFunctions_Dynamic(); +#endif + + ValidateVulkanFunctions(); +} + +#if VMA_STATIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Static() +{ + // Vulkan 1.0 + m_VulkanFunctions.vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr; + m_VulkanFunctions.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr; + m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties; + m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties; + m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory; + m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory; + m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory; + m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory; + m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges; + m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges; + m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory; + m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory; + m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements; + m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements; + m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer; + m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer; + m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage; + m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage; + m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer; + + // Vulkan 1.1 +#if VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2; + m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2; + m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2; + m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2; + } +#endif + +#if VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2; + } +#endif + +#if VMA_VULKAN_VERSION >= 1003000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + { + m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)vkGetDeviceBufferMemoryRequirements; + m_VulkanFunctions.vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)vkGetDeviceImageMemoryRequirements; + } +#endif +} + +#endif // VMA_STATIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions) +{ + VMA_ASSERT(pVulkanFunctions != VMA_NULL); + +#define VMA_COPY_IF_NOT_NULL(funcName) \ + if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName; + + VMA_COPY_IF_NOT_NULL(vkGetInstanceProcAddr); + VMA_COPY_IF_NOT_NULL(vkGetDeviceProcAddr); + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties); + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties); + VMA_COPY_IF_NOT_NULL(vkAllocateMemory); + VMA_COPY_IF_NOT_NULL(vkFreeMemory); + VMA_COPY_IF_NOT_NULL(vkMapMemory); + VMA_COPY_IF_NOT_NULL(vkUnmapMemory); + VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges); + VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges); + VMA_COPY_IF_NOT_NULL(vkBindBufferMemory); + VMA_COPY_IF_NOT_NULL(vkBindImageMemory); + VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements); + VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements); + VMA_COPY_IF_NOT_NULL(vkCreateBuffer); + VMA_COPY_IF_NOT_NULL(vkDestroyBuffer); + VMA_COPY_IF_NOT_NULL(vkCreateImage); + VMA_COPY_IF_NOT_NULL(vkDestroyImage); + VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer); + +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR); + VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR); +#endif + +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR); + VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR); +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR); +#endif + +#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements); + VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements); +#endif +#if VMA_EXTERNAL_MEMORY_WIN32 + VMA_COPY_IF_NOT_NULL(vkGetMemoryWin32HandleKHR); +#endif +#undef VMA_COPY_IF_NOT_NULL +} + +#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ImportVulkanFunctions_Dynamic() +{ + VMA_ASSERT(m_VulkanFunctions.vkGetInstanceProcAddr && m_VulkanFunctions.vkGetDeviceProcAddr && + "To use VMA_DYNAMIC_VULKAN_FUNCTIONS in new versions of VMA you now have to pass " + "VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VmaAllocatorCreateInfo::pVulkanFunctions. " + "Other members can be null."); + +#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \ + if(m_VulkanFunctions.memberName == VMA_NULL) \ + m_VulkanFunctions.memberName = \ + (functionPointerType)m_VulkanFunctions.vkGetInstanceProcAddr(m_hInstance, functionNameString); +#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \ + if(m_VulkanFunctions.memberName == VMA_NULL) \ + m_VulkanFunctions.memberName = \ + (functionPointerType)m_VulkanFunctions.vkGetDeviceProcAddr(m_hDevice, functionNameString); + + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties"); + VMA_FETCH_DEVICE_FUNC(vkAllocateMemory, PFN_vkAllocateMemory, "vkAllocateMemory"); + VMA_FETCH_DEVICE_FUNC(vkFreeMemory, PFN_vkFreeMemory, "vkFreeMemory"); + VMA_FETCH_DEVICE_FUNC(vkMapMemory, PFN_vkMapMemory, "vkMapMemory"); + VMA_FETCH_DEVICE_FUNC(vkUnmapMemory, PFN_vkUnmapMemory, "vkUnmapMemory"); + VMA_FETCH_DEVICE_FUNC(vkFlushMappedMemoryRanges, PFN_vkFlushMappedMemoryRanges, "vkFlushMappedMemoryRanges"); + VMA_FETCH_DEVICE_FUNC(vkInvalidateMappedMemoryRanges, PFN_vkInvalidateMappedMemoryRanges, "vkInvalidateMappedMemoryRanges"); + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory, PFN_vkBindBufferMemory, "vkBindBufferMemory"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory, PFN_vkBindImageMemory, "vkBindImageMemory"); + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements, PFN_vkGetBufferMemoryRequirements, "vkGetBufferMemoryRequirements"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements, PFN_vkGetImageMemoryRequirements, "vkGetImageMemoryRequirements"); + VMA_FETCH_DEVICE_FUNC(vkCreateBuffer, PFN_vkCreateBuffer, "vkCreateBuffer"); + VMA_FETCH_DEVICE_FUNC(vkDestroyBuffer, PFN_vkDestroyBuffer, "vkDestroyBuffer"); + VMA_FETCH_DEVICE_FUNC(vkCreateImage, PFN_vkCreateImage, "vkCreateImage"); + VMA_FETCH_DEVICE_FUNC(vkDestroyImage, PFN_vkDestroyImage, "vkDestroyImage"); + VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, "vkCmdCopyBuffer"); + +#if VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2, "vkGetBufferMemoryRequirements2"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2, "vkGetImageMemoryRequirements2"); + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2, "vkBindBufferMemory2"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2, "vkBindImageMemory2"); + } +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); + // Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); + } + else if(m_UseExtMemoryBudget) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); + // Try to fetch the pointer from the other name, based on suspected driver bug - see issue #410. + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); + } +#endif + +#if VMA_DEDICATED_ALLOCATION + if(m_UseKhrDedicatedAllocation) + { + VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, "vkGetBufferMemoryRequirements2KHR"); + VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, "vkGetImageMemoryRequirements2KHR"); + } +#endif + +#if VMA_BIND_MEMORY2 + if(m_UseKhrBindMemory2) + { + VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, "vkBindBufferMemory2KHR"); + VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, "vkBindImageMemory2KHR"); + } +#endif // #if VMA_BIND_MEMORY2 + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2"); + } + else if(m_UseExtMemoryBudget) + { + VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR"); + } +#endif // #if VMA_MEMORY_BUDGET + +#if VMA_VULKAN_VERSION >= 1003000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + { + VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirements, "vkGetDeviceBufferMemoryRequirements"); + VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirements, "vkGetDeviceImageMemoryRequirements"); + } +#endif +#if VMA_KHR_MAINTENANCE4 + if(m_UseKhrMaintenance4) + { + VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirementsKHR, "vkGetDeviceBufferMemoryRequirementsKHR"); + VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirementsKHR, "vkGetDeviceImageMemoryRequirementsKHR"); + } +#endif +#if VMA_EXTERNAL_MEMORY_WIN32 + if (m_UseKhrExternalMemoryWin32) + { + VMA_FETCH_DEVICE_FUNC(vkGetMemoryWin32HandleKHR, PFN_vkGetMemoryWin32HandleKHR, "vkGetMemoryWin32HandleKHR"); + } +#endif +#undef VMA_FETCH_DEVICE_FUNC +#undef VMA_FETCH_INSTANCE_FUNC +} + +#endif // VMA_DYNAMIC_VULKAN_FUNCTIONS == 1 + +void VmaAllocator_T::ValidateVulkanFunctions() const +{ + VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL); + +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation) + { + VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL); + } +#endif + +#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000 + if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2) + { + VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL); + VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL); + } +#endif + +#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000 + if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL); + } +#endif +#if VMA_EXTERNAL_MEMORY_WIN32 + if (m_UseKhrExternalMemoryWin32) + { + VMA_ASSERT(m_VulkanFunctions.vkGetMemoryWin32HandleKHR != VMA_NULL); + } +#endif + + // Not validating these due to suspected driver bugs with these function + // pointers being null despite correct extension or Vulkan version is enabled. + // See issue #397. Their usage in VMA is optional anyway. + // + // VMA_ASSERT(m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements != VMA_NULL); + // VMA_ASSERT(m_VulkanFunctions.vkGetDeviceImageMemoryRequirements != VMA_NULL); +} + +VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex) +{ + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size; + const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE; + return VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32); +} + +VkResult VmaAllocator_T::AllocateMemoryOfType( + VmaPool pool, + VkDeviceSize size, + VkDeviceSize alignment, + bool dedicatedPreferred, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + const VmaAllocationCreateInfo& createInfo, + uint32_t memTypeIndex, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + VmaBlockVector& blockVector, + size_t allocationCount, + VmaAllocation* pAllocations) +{ + VMA_ASSERT(pAllocations != VMA_NULL); + VMA_DEBUG_LOG_FORMAT(" AllocateMemory: MemoryTypeIndex=%" PRIu32 ", AllocationCount=%zu, Size=%" PRIu64, memTypeIndex, allocationCount, size); + + VmaAllocationCreateInfo finalCreateInfo = createInfo; + VkResult res = CalcMemTypeParams( + finalCreateInfo, + memTypeIndex, + size, + allocationCount); + if(res != VK_SUCCESS) + return res; + + if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + { + return AllocateDedicatedMemory( + pool, + size, + suballocType, + dedicatedAllocations, + memTypeIndex, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, + finalCreateInfo.pUserData, + finalCreateInfo.priority, + dedicatedBuffer, + dedicatedImage, + dedicatedBufferImageUsage, + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); + } + + const bool canAllocateDedicated = + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 && + (pool == VK_NULL_HANDLE || !blockVector.HasExplicitBlockSize()); + + if(canAllocateDedicated) + { + // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size. + if(size > blockVector.GetPreferredBlockSize() / 2) + { + dedicatedPreferred = true; + } + // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget, + // which can quickly deplete maxMemoryAllocationCount: Don't prefer dedicated allocations when above + // 3/4 of the maximum allocation count. + if(m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount < UINT32_MAX / 4 && + m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4) + { + dedicatedPreferred = false; + } + + if(dedicatedPreferred) + { + res = AllocateDedicatedMemory( + pool, + size, + suballocType, + dedicatedAllocations, + memTypeIndex, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, + finalCreateInfo.pUserData, + finalCreateInfo.priority, + dedicatedBuffer, + dedicatedImage, + dedicatedBufferImageUsage, + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); + if(res == VK_SUCCESS) + { + // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here. + VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); + return VK_SUCCESS; + } + } + } + + res = blockVector.Allocate( + size, + alignment, + finalCreateInfo, + suballocType, + allocationCount, + pAllocations); + if(res == VK_SUCCESS) + return VK_SUCCESS; + + // Try dedicated memory. + if(canAllocateDedicated && !dedicatedPreferred) + { + res = AllocateDedicatedMemory( + pool, + size, + suballocType, + dedicatedAllocations, + memTypeIndex, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, + (finalCreateInfo.flags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0, + (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0, + finalCreateInfo.pUserData, + finalCreateInfo.priority, + dedicatedBuffer, + dedicatedImage, + dedicatedBufferImageUsage, + allocationCount, + pAllocations, + blockVector.GetAllocationNextPtr()); + if(res == VK_SUCCESS) + { + // Succeeded: AllocateDedicatedMemory function already filled pMemory, nothing more to do here. + VMA_DEBUG_LOG(" Allocated as DedicatedMemory"); + return VK_SUCCESS; + } + } + // Everything failed: Return error code. + VMA_DEBUG_LOG(" vkAllocateMemory FAILED"); + return res; +} + +VkResult VmaAllocator_T::AllocateDedicatedMemory( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + VmaDedicatedAllocationList& dedicatedAllocations, + uint32_t memTypeIndex, + bool map, + bool isUserDataString, + bool isMappingAllowed, + bool canAliasMemory, + void* pUserData, + float priority, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + size_t allocationCount, + VmaAllocation* pAllocations, + const void* pNextChain) +{ + VMA_ASSERT(allocationCount > 0 && pAllocations); + + VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + allocInfo.memoryTypeIndex = memTypeIndex; + allocInfo.allocationSize = size; + allocInfo.pNext = pNextChain; + +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR }; + if(!canAliasMemory) + { + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + if(dedicatedBuffer != VK_NULL_HANDLE) + { + VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE); + dedicatedAllocInfo.buffer = dedicatedBuffer; + VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); + } + else if(dedicatedImage != VK_NULL_HANDLE) + { + dedicatedAllocInfo.image = dedicatedImage; + VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); + } + } + } +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + +#if VMA_BUFFER_DEVICE_ADDRESS + VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR }; + if(m_UseKhrBufferDeviceAddress) + { + bool canContainBufferWithDeviceAddress = true; + if(dedicatedBuffer != VK_NULL_HANDLE) + { + canContainBufferWithDeviceAddress = dedicatedBufferImageUsage == VmaBufferImageUsage::UNKNOWN || + dedicatedBufferImageUsage.Contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT); + } + else if(dedicatedImage != VK_NULL_HANDLE) + { + canContainBufferWithDeviceAddress = false; + } + if(canContainBufferWithDeviceAddress) + { + allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo); + } + } +#endif // #if VMA_BUFFER_DEVICE_ADDRESS + +#if VMA_MEMORY_PRIORITY + VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT }; + if(m_UseExtMemoryPriority) + { + VMA_ASSERT(priority >= 0.F && priority <= 1.F); + priorityInfo.priority = priority; + VmaPnextChainPushFront(&allocInfo, &priorityInfo); + } +#endif // #if VMA_MEMORY_PRIORITY + +#if VMA_EXTERNAL_MEMORY + // Attach VkExportMemoryAllocateInfoKHR if necessary. + VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; + exportMemoryAllocInfo.handleTypes = GetExternalMemoryHandleTypeFlags(memTypeIndex); + if(exportMemoryAllocInfo.handleTypes != 0) + { + VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo); + } +#endif // #if VMA_EXTERNAL_MEMORY + + size_t allocIndex = 0; + VkResult res = VK_SUCCESS; + for(; allocIndex < allocationCount; ++allocIndex) + { + res = AllocateDedicatedMemoryPage( + pool, + size, + suballocType, + memTypeIndex, + allocInfo, + map, + isUserDataString, + isMappingAllowed, + pUserData, + pAllocations + allocIndex); + if(res != VK_SUCCESS) + { + break; + } + } + + if(res == VK_SUCCESS) + { + for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + dedicatedAllocations.Register(pAllocations[allocIndex]); + } + VMA_DEBUG_LOG_FORMAT(" Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%" PRIu32, allocationCount, memTypeIndex); + } + else + { + // Free all already created allocations. + while(allocIndex--) + { + VmaAllocation currAlloc = pAllocations[allocIndex]; + VkDeviceMemory hMemory = currAlloc->GetMemory(); + + /* + There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory + before vkFreeMemory. + + if(currAlloc->GetMappedData() != VMA_NULL) + { + (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory); + } + */ + + FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory); + m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize()); + m_AllocationObjectAllocator.Free(currAlloc); + } + + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + } + + return res; +} + +VkResult VmaAllocator_T::AllocateDedicatedMemoryPage( + VmaPool pool, + VkDeviceSize size, + VmaSuballocationType suballocType, + uint32_t memTypeIndex, + const VkMemoryAllocateInfo& allocInfo, + bool map, + bool isUserDataString, + bool isMappingAllowed, + void* pUserData, + VmaAllocation* pAllocation) +{ + VkDeviceMemory hMemory = VK_NULL_HANDLE; + VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory); + if(res < 0) + { + VMA_DEBUG_LOG(" vkAllocateMemory FAILED"); + return res; + } + + void* pMappedData = VMA_NULL; + if(map) + { + res = (*m_VulkanFunctions.vkMapMemory)( + m_hDevice, + hMemory, + 0, + VK_WHOLE_SIZE, + 0, + &pMappedData); + if(res < 0) + { + VMA_DEBUG_LOG(" vkMapMemory FAILED"); + FreeVulkanMemory(memTypeIndex, size, hMemory); + return res; + } + } + + *pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed); + (*pAllocation)->InitDedicatedAllocation(this, pool, memTypeIndex, hMemory, suballocType, pMappedData, size); + if (isUserDataString) + (*pAllocation)->SetName(this, (const char*)pUserData); + else + (*pAllocation)->SetUserData(this, pUserData); + m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size); + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) + { + FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED); + } + + return VK_SUCCESS; +} + +void VmaAllocator_T::GetBufferMemoryRequirements( + VkBuffer hBuffer, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const +{ +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR }; + memReqInfo.buffer = hBuffer; + + VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR }; + + VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR }; + VmaPnextChainPushFront(&memReq2, &memDedicatedReq); + + (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2); + + memReq = memReq2.memoryRequirements; + requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE); + prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + } + else +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + { + (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq); + requiresDedicatedAllocation = false; + prefersDedicatedAllocation = false; + } +} + +void VmaAllocator_T::GetImageMemoryRequirements( + VkImage hImage, + VkMemoryRequirements& memReq, + bool& requiresDedicatedAllocation, + bool& prefersDedicatedAllocation) const +{ +#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR }; + memReqInfo.image = hImage; + + VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR }; + + VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR }; + VmaPnextChainPushFront(&memReq2, &memDedicatedReq); + + (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2); + + memReq = memReq2.memoryRequirements; + requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE); + prefersDedicatedAllocation = (memDedicatedReq.prefersDedicatedAllocation != VK_FALSE); + } + else +#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 + { + (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq); + requiresDedicatedAllocation = false; + prefersDedicatedAllocation = false; + } +} + +VkResult VmaAllocator_T::FindMemoryTypeIndex( + uint32_t memoryTypeBits, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VmaBufferImageUsage bufImgUsage, + uint32_t* pMemoryTypeIndex) const +{ + memoryTypeBits &= GetGlobalMemoryTypeBits(); + + if(pAllocationCreateInfo->memoryTypeBits != 0) + { + memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits; + } + + VkMemoryPropertyFlags requiredFlags = 0; + VkMemoryPropertyFlags preferredFlags = 0; + VkMemoryPropertyFlags notPreferredFlags = 0; + if(!FindMemoryPreferences( + IsIntegratedGpu(), + *pAllocationCreateInfo, + bufImgUsage, + requiredFlags, preferredFlags, notPreferredFlags)) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + *pMemoryTypeIndex = UINT32_MAX; + uint32_t minCost = UINT32_MAX; + for(uint32_t memTypeIndex = 0, memTypeBit = 1; + memTypeIndex < GetMemoryTypeCount(); + ++memTypeIndex, memTypeBit <<= 1) + { + // This memory type is acceptable according to memoryTypeBits bitmask. + if((memTypeBit & memoryTypeBits) != 0) + { + const VkMemoryPropertyFlags currFlags = + m_MemProps.memoryTypes[memTypeIndex].propertyFlags; + // This memory type contains requiredFlags. + if((requiredFlags & ~currFlags) == 0) + { + // Calculate cost as number of bits from preferredFlags not present in this memory type. + uint32_t currCost = VMA_COUNT_BITS_SET(preferredFlags & ~currFlags) + + VMA_COUNT_BITS_SET(currFlags & notPreferredFlags); + // Remember memory type with lowest cost. + if(currCost < minCost) + { + *pMemoryTypeIndex = memTypeIndex; + if(currCost == 0) + { + return VK_SUCCESS; + } + minCost = currCost; + } + } + } + } + return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT; +} + +VkResult VmaAllocator_T::CalcMemTypeParams( + VmaAllocationCreateInfo& inoutCreateInfo, + uint32_t memTypeIndex, + VkDeviceSize size, + size_t allocationCount) +{ + // If memory type is not HOST_VISIBLE, disable MAPPED. + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 && + (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + inoutCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT; + } + + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0) + { + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex); + VmaBudget heapBudget = {}; + GetHeapBudgets(&heapBudget, heapIndex, 1); + if(heapBudget.usage + size * allocationCount > heapBudget.budget) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + } + return VK_SUCCESS; +} + +VkResult VmaAllocator_T::CalcAllocationParams( + VmaAllocationCreateInfo& inoutCreateInfo, + bool dedicatedRequired) +{ + VMA_ASSERT((inoutCreateInfo.flags & + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != + (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) && + "Specifying both flags VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT and VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT is incorrect."); + VMA_ASSERT((((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) == 0 || + (inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0)) && + "Specifying VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT requires also VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT."); + if(inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST) + { + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0) + { + VMA_ASSERT((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0 && + "When using VMA_ALLOCATION_CREATE_MAPPED_BIT and usage = VMA_MEMORY_USAGE_AUTO*, you must also specify VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT."); + } + } + + // If memory is lazily allocated, it should be always dedicated. + if(dedicatedRequired || + inoutCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED) + { + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + } + + if(inoutCreateInfo.pool != VK_NULL_HANDLE) + { + if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0) + { + VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations."); + return VK_ERROR_FEATURE_NOT_PRESENT; + } + inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority(); + } + + if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) + { + VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense."); + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + if(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY && + (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) + { + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + } + + // Non-auto USAGE values imply HOST_ACCESS flags. + // And so does VMA_MEMORY_USAGE_UNKNOWN because it is used with custom pools. + // Which specific flag is used doesn't matter. They change things only when used with VMA_MEMORY_USAGE_AUTO*. + // Otherwise they just protect from assert on mapping. + if(inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO && + inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE && + inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_HOST) + { + if((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) == 0) + { + inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; + } + } + + return VK_SUCCESS; +} + +VkResult VmaAllocator_T::AllocateMemory( + const VkMemoryRequirements& vkMemReq, + bool requiresDedicatedAllocation, + bool prefersDedicatedAllocation, + VkBuffer dedicatedBuffer, + VkImage dedicatedImage, + VmaBufferImageUsage dedicatedBufferImageUsage, + const VmaAllocationCreateInfo& createInfo, + VmaSuballocationType suballocType, + size_t allocationCount, + VmaAllocation* pAllocations) +{ + memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount); + + VMA_ASSERT(VmaIsPow2(vkMemReq.alignment)); + + if(vkMemReq.size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + VmaAllocationCreateInfo createInfoFinal = createInfo; + VkResult res = CalcAllocationParams(createInfoFinal, requiresDedicatedAllocation); + if(res != VK_SUCCESS) + return res; + + if(createInfoFinal.pool != VK_NULL_HANDLE) + { + VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector; + return AllocateMemoryOfType( + createInfoFinal.pool, + vkMemReq.size, + vkMemReq.alignment, + prefersDedicatedAllocation, + dedicatedBuffer, + dedicatedImage, + dedicatedBufferImageUsage, + createInfoFinal, + blockVector.GetMemoryTypeIndex(), + suballocType, + createInfoFinal.pool->m_DedicatedAllocations, + blockVector, + allocationCount, + pAllocations); + } + + // Bit mask of memory Vulkan types acceptable for this allocation. + uint32_t memoryTypeBits = vkMemReq.memoryTypeBits; + uint32_t memTypeIndex = UINT32_MAX; + res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex); + // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT. + if(res != VK_SUCCESS) + return res; + + do + { + VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(blockVector && "Trying to use unsupported memory type!"); + res = AllocateMemoryOfType( + VK_NULL_HANDLE, + vkMemReq.size, + vkMemReq.alignment, + requiresDedicatedAllocation || prefersDedicatedAllocation, + dedicatedBuffer, + dedicatedImage, + dedicatedBufferImageUsage, + createInfoFinal, + memTypeIndex, + suballocType, + m_DedicatedAllocations[memTypeIndex], + *blockVector, + allocationCount, + pAllocations); + // Allocation succeeded + if(res == VK_SUCCESS) + return VK_SUCCESS; + + // Remove old memTypeIndex from list of possibilities. + memoryTypeBits &= ~(1U << memTypeIndex); + // Find alternative memTypeIndex. + res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex); + } while(res == VK_SUCCESS); + + // No other matching memory type index could be found. + // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once. + return VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + +void VmaAllocator_T::FreeMemory( + size_t allocationCount, + const VmaAllocation* pAllocations) +{ + VMA_ASSERT(pAllocations); + + for(size_t allocIndex = allocationCount; allocIndex--; ) + { + VmaAllocation allocation = pAllocations[allocIndex]; + + if(allocation != VK_NULL_HANDLE) + { + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS) + { + FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED); + } + + switch(allocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaBlockVector* pBlockVector = VMA_NULL; + VmaPool hPool = allocation->GetParentPool(); + if(hPool != VK_NULL_HANDLE) + { + pBlockVector = &hPool->m_BlockVector; + } + else + { + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + pBlockVector = m_pBlockVectors[memTypeIndex]; + VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!"); + } + pBlockVector->Free(allocation); + } + break; + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + FreeDedicatedMemory(allocation); + break; + default: + VMA_ASSERT(0); + } + } + } +} + +void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats) +{ + // Initialize. + VmaClearDetailedStatistics(pStats->total); + for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) + VmaClearDetailedStatistics(pStats->memoryType[i]); + for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i) + VmaClearDetailedStatistics(pStats->memoryHeap[i]); + + // Process default pools. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; + if (pBlockVector != VMA_NULL) + pBlockVector->AddDetailedStatistics(pStats->memoryType[memTypeIndex]); + } + + // Process custom pools. + { + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { + VmaBlockVector& blockVector = pool->m_BlockVector; + const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex(); + blockVector.AddDetailedStatistics(pStats->memoryType[memTypeIndex]); + pool->m_DedicatedAllocations.AddDetailedStatistics(pStats->memoryType[memTypeIndex]); + } + } + + // Process dedicated allocations. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + m_DedicatedAllocations[memTypeIndex].AddDetailedStatistics(pStats->memoryType[memTypeIndex]); + } + + // Sum from memory types to memory heaps. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + const uint32_t memHeapIndex = m_MemProps.memoryTypes[memTypeIndex].heapIndex; + VmaAddDetailedStatistics(pStats->memoryHeap[memHeapIndex], pStats->memoryType[memTypeIndex]); + } + + // Sum from memory heaps to total. + for(uint32_t memHeapIndex = 0; memHeapIndex < GetMemoryHeapCount(); ++memHeapIndex) + VmaAddDetailedStatistics(pStats->total, pStats->memoryHeap[memHeapIndex]); + + VMA_ASSERT(pStats->total.statistics.allocationCount == 0 || + pStats->total.allocationSizeMax >= pStats->total.allocationSizeMin); + VMA_ASSERT(pStats->total.unusedRangeCount == 0 || + pStats->total.unusedRangeSizeMax >= pStats->total.unusedRangeSizeMin); +} + +void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount) +{ +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + if(m_Budget.m_OperationsSinceBudgetFetch < 30) + { + VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex); + for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) + { + const uint32_t heapIndex = firstHeap + i; + + outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex]; + outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex]; + outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex]; + outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex]; + + if(m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]) + { + outBudgets->usage = m_Budget.m_VulkanUsage[heapIndex] + + outBudgets->statistics.blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; + } + else + { + outBudgets->usage = 0; + } + + // Have to take MIN with heap size because explicit HeapSizeLimit is included in it. + outBudgets->budget = VMA_MIN( + m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size); + } + } + else + { + UpdateVulkanBudget(); // Outside of mutex lock + GetHeapBudgets(outBudgets, firstHeap, heapCount); // Recursion + } + } + else +#endif + { + for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets) + { + const uint32_t heapIndex = firstHeap + i; + + outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex]; + outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex]; + outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex]; + outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex]; + + outBudgets->usage = outBudgets->statistics.blockBytes; + outBudgets->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics. + } + } +} + +void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo) +{ + pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex(); + pAllocationInfo->deviceMemory = hAllocation->GetMemory(); + pAllocationInfo->offset = hAllocation->GetOffset(); + pAllocationInfo->size = hAllocation->GetSize(); + pAllocationInfo->pMappedData = hAllocation->GetMappedData(); + pAllocationInfo->pUserData = hAllocation->GetUserData(); + pAllocationInfo->pName = hAllocation->GetName(); +} + +void VmaAllocator_T::GetAllocationInfo2(VmaAllocation hAllocation, VmaAllocationInfo2* pAllocationInfo) +{ + GetAllocationInfo(hAllocation, &pAllocationInfo->allocationInfo); + + switch (hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + pAllocationInfo->blockSize = hAllocation->GetBlock()->m_pMetadata->GetSize(); + pAllocationInfo->dedicatedMemory = VK_FALSE; + break; + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + pAllocationInfo->blockSize = pAllocationInfo->allocationInfo.size; + pAllocationInfo->dedicatedMemory = VK_TRUE; + break; + default: + VMA_ASSERT(0); + } +} + +VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool) +{ + VMA_DEBUG_LOG_FORMAT(" CreatePool: MemoryTypeIndex=%" PRIu32 ", flags=%" PRIu32, pCreateInfo->memoryTypeIndex, pCreateInfo->flags); + + VmaPoolCreateInfo newCreateInfo = *pCreateInfo; + + // Protection against uninitialized new structure member. If garbage data are left there, this pointer dereference would crash. + if(pCreateInfo->pMemoryAllocateNext) + { + VMA_ASSERT(((const VkBaseInStructure*)pCreateInfo->pMemoryAllocateNext)->sType != 0); + } + + if(newCreateInfo.maxBlockCount == 0) + { + newCreateInfo.maxBlockCount = SIZE_MAX; + } + if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + // Memory type index out of range or forbidden. + if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() || + ((1U << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0) + { + return VK_ERROR_FEATURE_NOT_PRESENT; + } + if(newCreateInfo.minAllocationAlignment > 0) + { + VMA_ASSERT(VmaIsPow2(newCreateInfo.minAllocationAlignment)); + } + + const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex); + + *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize); + + VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks(); + if(res != VK_SUCCESS) + { + vma_delete(this, *pPool); + *pPool = VMA_NULL; + return res; + } + + // Add to m_Pools. + { + VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex); + (*pPool)->SetId(m_NextPoolId++); + m_Pools.PushBack(*pPool); + } + + return VK_SUCCESS; +} + +void VmaAllocator_T::DestroyPool(VmaPool pool) +{ + // Remove from m_Pools. + { + VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex); + m_Pools.Remove(pool); + } + + vma_delete(this, pool); +} + +void VmaAllocator_T::GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats) +{ + VmaClearStatistics(*pPoolStats); + pool->m_BlockVector.AddStatistics(*pPoolStats); + pool->m_DedicatedAllocations.AddStatistics(*pPoolStats); +} + +void VmaAllocator_T::CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats) +{ + VmaClearDetailedStatistics(*pPoolStats); + pool->m_BlockVector.AddDetailedStatistics(*pPoolStats); + pool->m_DedicatedAllocations.AddDetailedStatistics(*pPoolStats); +} + +void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex) +{ + m_CurrentFrameIndex.store(frameIndex); + +#if VMA_MEMORY_BUDGET + if(m_UseExtMemoryBudget) + { + UpdateVulkanBudget(); + } +#endif // #if VMA_MEMORY_BUDGET +} + +VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool) +{ + return hPool->m_BlockVector.CheckCorruption(); +} + +VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits) +{ + VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT; + + // Process default pools. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex]; + if(pBlockVector != VMA_NULL) + { + VkResult localRes = pBlockVector->CheckCorruption(); + switch(localRes) + { + case VK_ERROR_FEATURE_NOT_PRESENT: + break; + case VK_SUCCESS: + finalRes = VK_SUCCESS; + break; + default: + return localRes; + } + } + } + + // Process custom pools. + { + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { + if(((1U << pool->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0) + { + VkResult localRes = pool->m_BlockVector.CheckCorruption(); + switch(localRes) + { + case VK_ERROR_FEATURE_NOT_PRESENT: + break; + case VK_SUCCESS: + finalRes = VK_SUCCESS; + break; + default: + return localRes; + } + } + } + } + + return finalRes; +} + +VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory) +{ + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex); + +#if VMA_DEBUG_DONT_EXCEED_HEAP_SIZE_WITH_ALLOCATION_SIZE + if (pAllocateInfo->allocationSize > m_MemProps.memoryHeaps[heapIndex].size) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } +#endif + + AtomicTransactionalIncrement deviceMemoryCountIncrement; + const uint64_t prevDeviceMemoryCount = deviceMemoryCountIncrement.Increment(&m_DeviceMemoryCount); +#if VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT + if(prevDeviceMemoryCount >= m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount) + { + return VK_ERROR_TOO_MANY_OBJECTS; + } +#endif + + // HeapSizeLimit is in effect for this heap. + if((m_HeapSizeLimitMask & (1U << heapIndex)) != 0) + { + const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size; + VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex]; + for(;;) + { + const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize; + if(blockBytesAfterAllocation > heapSize) + { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation)) + { + break; + } + } + } + else + { + m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize; + } + ++m_Budget.m_BlockCount[heapIndex]; + + // VULKAN CALL vkAllocateMemory. + VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory); + + if(res == VK_SUCCESS) + { +#if VMA_MEMORY_BUDGET + ++m_Budget.m_OperationsSinceBudgetFetch; +#endif + + // Informative callback. + if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL) + { + (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize, m_DeviceMemoryCallbacks.pUserData); + } + + deviceMemoryCountIncrement.Commit(); + } + else + { + --m_Budget.m_BlockCount[heapIndex]; + m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize; + } + + return res; +} + +void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory) +{ + // Informative callback. + if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL) + { + (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size, m_DeviceMemoryCallbacks.pUserData); + } + + // VULKAN CALL vkFreeMemory. + (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks()); + + const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType); + --m_Budget.m_BlockCount[heapIndex]; + m_Budget.m_BlockBytes[heapIndex] -= size; + + --m_DeviceMemoryCount; +} + +VkResult VmaAllocator_T::BindVulkanBuffer( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkBuffer buffer, + const void* pNext) const +{ + if(pNext != VMA_NULL) + { +#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL) + { + VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR }; + bindBufferMemoryInfo.pNext = pNext; + bindBufferMemoryInfo.buffer = buffer; + bindBufferMemoryInfo.memory = memory; + bindBufferMemoryInfo.memoryOffset = memoryOffset; + return (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo); + } +#endif // #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + else + { + return (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset); + } +} + +VkResult VmaAllocator_T::BindVulkanImage( + VkDeviceMemory memory, + VkDeviceSize memoryOffset, + VkImage image, + const void* pNext) const +{ + if(pNext != VMA_NULL) + { +#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2 + if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) && + m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL) + { + VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR }; + bindBufferMemoryInfo.pNext = pNext; + bindBufferMemoryInfo.image = image; + bindBufferMemoryInfo.memory = memory; + bindBufferMemoryInfo.memoryOffset = memoryOffset; + return (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo); + } +#endif // #if VMA_BIND_MEMORY2 + + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + return (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset); +} + +VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData) +{ + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + char *pBytes = VMA_NULL; + VkResult res = pBlock->Map(this, 1, (void**)&pBytes); + if(res == VK_SUCCESS) + { + *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset(); + hAllocation->BlockAllocMap(); + } + return res; + } + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + return hAllocation->DedicatedAllocMap(this, ppData); + default: + VMA_ASSERT(0); + return VK_ERROR_MEMORY_MAP_FAILED; + } +} + +void VmaAllocator_T::Unmap(VmaAllocation hAllocation) +{ + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + hAllocation->BlockAllocUnmap(); + pBlock->Unmap(this, 1); + } + break; + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + hAllocation->DedicatedAllocUnmap(this); + break; + default: + VMA_ASSERT(0); + } +} + +VkResult VmaAllocator_T::BindBufferMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkBuffer hBuffer, + const void* pNext) +{ + VkResult res = VK_ERROR_UNKNOWN_COPY; + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext); + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock(); + VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block."); + res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext); + break; + } + default: + VMA_ASSERT(0); + } + return res; +} + +VkResult VmaAllocator_T::BindImageMemory( + VmaAllocation hAllocation, + VkDeviceSize allocationLocalOffset, + VkImage hImage, + const void* pNext) +{ + VkResult res = VK_ERROR_UNKNOWN_COPY; + switch(hAllocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext); + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock(); + VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block."); + res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext); + break; + } + default: + VMA_ASSERT(0); + } + return res; +} + +VkResult VmaAllocator_T::FlushOrInvalidateAllocation( + VmaAllocation hAllocation, + VkDeviceSize offset, VkDeviceSize size, + VMA_CACHE_OPERATION op) +{ + VkResult res = VK_SUCCESS; + + VkMappedMemoryRange memRange = {}; + if(GetFlushOrInvalidateRange(hAllocation, offset, size, memRange)) + { + switch(op) + { + case VMA_CACHE_FLUSH: + res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange); + break; + case VMA_CACHE_INVALIDATE: + res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange); + break; + default: + VMA_ASSERT(0); + } + } + // else: Just ignore this call. + return res; +} + +VkResult VmaAllocator_T::FlushOrInvalidateAllocations( + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, const VkDeviceSize* sizes, + VMA_CACHE_OPERATION op) +{ + typedef VmaStlAllocator RangeAllocator; + typedef VmaSmallVector RangeVector; + RangeVector ranges = RangeVector(RangeAllocator(GetAllocationCallbacks())); + + for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex) + { + const VmaAllocation alloc = allocations[allocIndex]; + const VkDeviceSize offset = offsets != VMA_NULL ? offsets[allocIndex] : 0; + const VkDeviceSize size = sizes != VMA_NULL ? sizes[allocIndex] : VK_WHOLE_SIZE; + VkMappedMemoryRange newRange; + if(GetFlushOrInvalidateRange(alloc, offset, size, newRange)) + { + ranges.push_back(newRange); + } + } + + VkResult res = VK_SUCCESS; + if(!ranges.empty()) + { + switch(op) + { + case VMA_CACHE_FLUSH: + res = (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data()); + break; + case VMA_CACHE_INVALIDATE: + res = (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, (uint32_t)ranges.size(), ranges.data()); + break; + default: + VMA_ASSERT(0); + } + } + // else: Just ignore this call. + return res; +} + +VkResult VmaAllocator_T::CopyMemoryToAllocation( + const void* pSrcHostPointer, + VmaAllocation dstAllocation, + VkDeviceSize dstAllocationLocalOffset, + VkDeviceSize size) +{ + void* dstMappedData = VMA_NULL; + VkResult res = Map(dstAllocation, &dstMappedData); + if(res == VK_SUCCESS) + { + memcpy((char*)dstMappedData + dstAllocationLocalOffset, pSrcHostPointer, (size_t)size); + Unmap(dstAllocation); + res = FlushOrInvalidateAllocation(dstAllocation, dstAllocationLocalOffset, size, VMA_CACHE_FLUSH); + } + return res; +} + +VkResult VmaAllocator_T::CopyAllocationToMemory( + VmaAllocation srcAllocation, + VkDeviceSize srcAllocationLocalOffset, + void* pDstHostPointer, + VkDeviceSize size) +{ + void* srcMappedData = VMA_NULL; + VkResult res = Map(srcAllocation, &srcMappedData); + if(res == VK_SUCCESS) + { + res = FlushOrInvalidateAllocation(srcAllocation, srcAllocationLocalOffset, size, VMA_CACHE_INVALIDATE); + if(res == VK_SUCCESS) + { + memcpy(pDstHostPointer, (const char*)srcMappedData + srcAllocationLocalOffset, (size_t)size); + Unmap(srcAllocation); + } + } + return res; +} + +void VmaAllocator_T::FreeDedicatedMemory(VmaAllocation allocation) +{ + VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED); + + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + VmaPool parentPool = allocation->GetParentPool(); + if(parentPool == VK_NULL_HANDLE) + { + // Default pool + m_DedicatedAllocations[memTypeIndex].Unregister(allocation); + } + else + { + // Custom pool + parentPool->m_DedicatedAllocations.Unregister(allocation); + } + + VkDeviceMemory hMemory = allocation->GetMemory(); + + /* + There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory + before vkFreeMemory. + + if(allocation->GetMappedData() != VMA_NULL) + { + (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory); + } + */ + + FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory); + + m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize()); + allocation->Destroy(this); + m_AllocationObjectAllocator.Free(allocation); + + VMA_DEBUG_LOG_FORMAT(" Freed DedicatedMemory MemoryTypeIndex=%" PRIu32, memTypeIndex); +} + +uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const +{ + VkBufferCreateInfo dummyBufCreateInfo; + VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo); + + uint32_t memoryTypeBits = 0; + + // Create buffer. + VkBuffer buf = VK_NULL_HANDLE; + VkResult res = (*GetVulkanFunctions().vkCreateBuffer)( + m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf); + if(res == VK_SUCCESS) + { + // Query for supported memory types. + VkMemoryRequirements memReq; + (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq); + memoryTypeBits = memReq.memoryTypeBits; + + // Destroy buffer. + (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks()); + } + + return memoryTypeBits; +} + +uint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits() const +{ + // Make sure memory information is already fetched. + VMA_ASSERT(GetMemoryTypeCount() > 0); + + uint32_t memoryTypeBits = UINT32_MAX; + + if(!m_UseAmdDeviceCoherentMemory) + { + // Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD. + for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0) + { + memoryTypeBits &= ~(1U << memTypeIndex); + } + } + } + + return memoryTypeBits; +} + +bool VmaAllocator_T::GetFlushOrInvalidateRange( + VmaAllocation allocation, + VkDeviceSize offset, VkDeviceSize size, + VkMappedMemoryRange& outRange) const +{ + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex)) + { + const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize; + const VkDeviceSize allocationSize = allocation->GetSize(); + VMA_ASSERT(offset <= allocationSize); + + outRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + outRange.pNext = VMA_NULL; + outRange.memory = allocation->GetMemory(); + + switch(allocation->GetType()) + { + case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED: + outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); + if(size == VK_WHOLE_SIZE) + { + outRange.size = allocationSize - outRange.offset; + } + else + { + VMA_ASSERT(offset + size <= allocationSize); + outRange.size = VMA_MIN( + VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize), + allocationSize - outRange.offset); + } + break; + case VmaAllocation_T::ALLOCATION_TYPE_BLOCK: + { + // 1. Still within this allocation. + outRange.offset = VmaAlignDown(offset, nonCoherentAtomSize); + if(size == VK_WHOLE_SIZE) + { + size = allocationSize - offset; + } + else + { + VMA_ASSERT(offset + size <= allocationSize); + } + outRange.size = VmaAlignUp(size + (offset - outRange.offset), nonCoherentAtomSize); + + // 2. Adjust to whole block. + const VkDeviceSize allocationOffset = allocation->GetOffset(); + VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0); + const VkDeviceSize blockSize = allocation->GetBlock()->m_pMetadata->GetSize(); + outRange.offset += allocationOffset; + outRange.size = VMA_MIN(outRange.size, blockSize - outRange.offset); + + break; + } + default: + VMA_ASSERT(0); + } + return true; + } + return false; +} + +#if VMA_MEMORY_BUDGET +void VmaAllocator_T::UpdateVulkanBudget() +{ + VMA_ASSERT(m_UseExtMemoryBudget); + + VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR }; + + VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT }; + VmaPnextChainPushFront(&memProps, &budgetProps); + + GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &memProps); + + { + VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex); + + for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex) + { + m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex]; + m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex]; + m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load(); + + // Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size. + if(m_Budget.m_VulkanBudget[heapIndex] == 0) + { + m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics. + } + else if(m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size) + { + m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size; + } + if(m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0) + { + m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex]; + } + } + m_Budget.m_OperationsSinceBudgetFetch = 0; + } +} +#endif // VMA_MEMORY_BUDGET + +void VmaAllocator_T::FillAllocation(VmaAllocation hAllocation, uint8_t pattern) +{ + if(VMA_DEBUG_INITIALIZE_ALLOCATIONS && + hAllocation->IsMappingAllowed() && + (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) + { + void* pData = VMA_NULL; + VkResult res = Map(hAllocation, &pData); + if(res == VK_SUCCESS) + { + memset(pData, (int)pattern, (size_t)hAllocation->GetSize()); + FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH); + Unmap(hAllocation); + } + else + { + VMA_ASSERT(0 && "VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation."); + } + } +} + +uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits() +{ + uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load(); + if(memoryTypeBits == UINT32_MAX) + { + memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits(); + m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits); + } + return memoryTypeBits; +} + +#if VMA_STATS_STRING_ENABLED +void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json) +{ + json.WriteString("DefaultPools"); + json.BeginObject(); + { + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + VmaBlockVector* pBlockVector = m_pBlockVectors[memTypeIndex]; + VmaDedicatedAllocationList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex]; + if (pBlockVector != VMA_NULL) + { + json.BeginString("Type "); + json.ContinueString(memTypeIndex); + json.EndString(); + json.BeginObject(); + { + json.WriteString("PreferredBlockSize"); + json.WriteNumber(pBlockVector->GetPreferredBlockSize()); + + json.WriteString("Blocks"); + pBlockVector->PrintDetailedMap(json); + + json.WriteString("DedicatedAllocations"); + dedicatedAllocList.BuildStatsString(json); + } + json.EndObject(); + } + } + } + json.EndObject(); + + json.WriteString("CustomPools"); + json.BeginObject(); + { + VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex); + if (!m_Pools.IsEmpty()) + { + for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex) + { + bool displayType = true; + size_t index = 0; + for (VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool)) + { + VmaBlockVector& blockVector = pool->m_BlockVector; + if (blockVector.GetMemoryTypeIndex() == memTypeIndex) + { + if (displayType) + { + json.BeginString("Type "); + json.ContinueString(memTypeIndex); + json.EndString(); + json.BeginArray(); + displayType = false; + } + + json.BeginObject(); + { + json.WriteString("Name"); + json.BeginString(); + json.ContinueString((uint64_t)index++); + if (pool->GetName()) + { + json.ContinueString(" - "); + json.ContinueString(pool->GetName()); + } + json.EndString(); + + json.WriteString("PreferredBlockSize"); + json.WriteNumber(blockVector.GetPreferredBlockSize()); + + json.WriteString("Blocks"); + blockVector.PrintDetailedMap(json); + + json.WriteString("DedicatedAllocations"); + pool->m_DedicatedAllocations.BuildStatsString(json); + } + json.EndObject(); + } + } + + if (!displayType) + json.EndArray(); + } + } + } + json.EndObject(); +} +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_ALLOCATOR_T_FUNCTIONS + + +#ifndef _VMA_PUBLIC_INTERFACE + +#ifdef VOLK_HEADER_VERSION + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaImportVulkanFunctionsFromVolk( + const VmaAllocatorCreateInfo* VMA_NOT_NULL pAllocatorCreateInfo, + VmaVulkanFunctions* VMA_NOT_NULL pDstVulkanFunctions) +{ + VMA_ASSERT(pAllocatorCreateInfo != VMA_NULL); + VMA_ASSERT(pAllocatorCreateInfo->instance != VK_NULL_HANDLE); + VMA_ASSERT(pAllocatorCreateInfo->device != VK_NULL_HANDLE); + + memset(pDstVulkanFunctions, 0, sizeof(*pDstVulkanFunctions)); + + VolkDeviceTable src = {}; + volkLoadDeviceTable(&src, pAllocatorCreateInfo->device); + +#define COPY_GLOBAL_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = volkName; +#define COPY_DEVICE_TO_VMA_FUNC(volkName, vmaName) if(!pDstVulkanFunctions->vmaName) pDstVulkanFunctions->vmaName = src.volkName; + + COPY_GLOBAL_TO_VMA_FUNC(vkGetInstanceProcAddr, vkGetInstanceProcAddr) + COPY_GLOBAL_TO_VMA_FUNC(vkGetDeviceProcAddr, vkGetDeviceProcAddr) + COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceProperties) + COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties, vkGetPhysicalDeviceMemoryProperties) + COPY_DEVICE_TO_VMA_FUNC(vkAllocateMemory, vkAllocateMemory) + COPY_DEVICE_TO_VMA_FUNC(vkFreeMemory, vkFreeMemory) + COPY_DEVICE_TO_VMA_FUNC(vkMapMemory, vkMapMemory) + COPY_DEVICE_TO_VMA_FUNC(vkUnmapMemory, vkUnmapMemory) + COPY_DEVICE_TO_VMA_FUNC(vkFlushMappedMemoryRanges, vkFlushMappedMemoryRanges) + COPY_DEVICE_TO_VMA_FUNC(vkInvalidateMappedMemoryRanges, vkInvalidateMappedMemoryRanges) + COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory, vkBindBufferMemory) + COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory, vkBindImageMemory) + COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements, vkGetBufferMemoryRequirements) + COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements, vkGetImageMemoryRequirements) + COPY_DEVICE_TO_VMA_FUNC(vkCreateBuffer, vkCreateBuffer) + COPY_DEVICE_TO_VMA_FUNC(vkDestroyBuffer, vkDestroyBuffer) + COPY_DEVICE_TO_VMA_FUNC(vkCreateImage, vkCreateImage) + COPY_DEVICE_TO_VMA_FUNC(vkDestroyImage, vkDestroyImage) + COPY_DEVICE_TO_VMA_FUNC(vkCmdCopyBuffer, vkCmdCopyBuffer) +#if VMA_VULKAN_VERSION >= 1001000 + if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) + { + COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2, vkGetPhysicalDeviceMemoryProperties2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2, vkGetBufferMemoryRequirements2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2, vkGetImageMemoryRequirements2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2, vkBindBufferMemory2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2, vkBindImageMemory2KHR) + } +#endif +#if VMA_VULKAN_VERSION >= 1003000 + if (pAllocatorCreateInfo->vulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0)) + { + COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirements) + COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirements) + } +#endif +#if VMA_KHR_MAINTENANCE4 + if((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT) != 0) + { + COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceBufferMemoryRequirementsKHR, vkGetDeviceBufferMemoryRequirements) + COPY_DEVICE_TO_VMA_FUNC(vkGetDeviceImageMemoryRequirementsKHR, vkGetDeviceImageMemoryRequirements) + } +#endif +#if VMA_DEDICATED_ALLOCATION + if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0) + { + COPY_DEVICE_TO_VMA_FUNC(vkGetBufferMemoryRequirements2KHR, vkGetBufferMemoryRequirements2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkGetImageMemoryRequirements2KHR, vkGetImageMemoryRequirements2KHR) + } +#endif +#if VMA_BIND_MEMORY2 + if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0) + { + COPY_DEVICE_TO_VMA_FUNC(vkBindBufferMemory2KHR, vkBindBufferMemory2KHR) + COPY_DEVICE_TO_VMA_FUNC(vkBindImageMemory2KHR, vkBindImageMemory2KHR) + } +#endif +#if VMA_MEMORY_BUDGET + if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0) + { + COPY_GLOBAL_TO_VMA_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, vkGetPhysicalDeviceMemoryProperties2KHR) + } +#endif +#if VMA_EXTERNAL_MEMORY_WIN32 + if ((pAllocatorCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT) != 0) + { + COPY_DEVICE_TO_VMA_FUNC(vkGetMemoryWin32HandleKHR, vkGetMemoryWin32HandleKHR) + } +#endif + +#undef COPY_DEVICE_TO_VMA_FUNC +#undef COPY_GLOBAL_TO_VMA_FUNC + + return VK_SUCCESS; +} + +#endif // #ifdef VOLK_HEADER_VERSION + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator( + const VmaAllocatorCreateInfo* pCreateInfo, + VmaAllocator* pAllocator) +{ + VMA_ASSERT(pCreateInfo && pAllocator); + VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 || + (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 4)); + VMA_DEBUG_LOG("vmaCreateAllocator"); + *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo); + VkResult result = (*pAllocator)->Init(pCreateInfo); + if(result < 0) + { + vma_delete(pCreateInfo->pAllocationCallbacks, *pAllocator); + *pAllocator = VK_NULL_HANDLE; + } + return result; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator( + VmaAllocator allocator) +{ + if(allocator != VK_NULL_HANDLE) + { + VMA_DEBUG_LOG("vmaDestroyAllocator"); + VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; // Have to copy the callbacks when destroying. + vma_delete(&allocationCallbacks, allocator); + } +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo* pAllocatorInfo) +{ + VMA_ASSERT(allocator && pAllocatorInfo); + pAllocatorInfo->instance = allocator->m_hInstance; + pAllocatorInfo->physicalDevice = allocator->GetPhysicalDevice(); + pAllocatorInfo->device = allocator->m_hDevice; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties( + VmaAllocator allocator, + const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties) +{ + VMA_ASSERT(allocator && ppPhysicalDeviceProperties); + *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties( + VmaAllocator allocator, + const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties) +{ + VMA_ASSERT(allocator && ppPhysicalDeviceMemoryProperties); + *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties( + VmaAllocator allocator, + uint32_t memoryTypeIndex, + VkMemoryPropertyFlags* pFlags) +{ + VMA_ASSERT(allocator && pFlags); + VMA_ASSERT(memoryTypeIndex < allocator->GetMemoryTypeCount()); + *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex( + VmaAllocator allocator, + uint32_t frameIndex) +{ + VMA_ASSERT(allocator); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->SetCurrentFrameIndex(frameIndex); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics( + VmaAllocator allocator, + VmaTotalStatistics* pStats) +{ + VMA_ASSERT(allocator && pStats); + VMA_DEBUG_GLOBAL_MUTEX_LOCK + allocator->CalculateStatistics(pStats); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets( + VmaAllocator allocator, + VmaBudget* pBudgets) +{ + VMA_ASSERT(allocator && pBudgets); + VMA_DEBUG_GLOBAL_MUTEX_LOCK + allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount()); +} + +#if VMA_STATS_STRING_ENABLED + +VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString( + VmaAllocator allocator, + char** ppStatsString, + VkBool32 detailedMap) +{ + VMA_ASSERT(allocator && ppStatsString); + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VmaStringBuilder sb(allocator->GetAllocationCallbacks()); + { + VmaBudget budgets[VK_MAX_MEMORY_HEAPS]; + allocator->GetHeapBudgets(budgets, 0, allocator->GetMemoryHeapCount()); + + VmaTotalStatistics stats; + allocator->CalculateStatistics(&stats); + + VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb); + json.BeginObject(); + { + json.WriteString("General"); + json.BeginObject(); + { + const VkPhysicalDeviceProperties& deviceProperties = allocator->m_PhysicalDeviceProperties; + const VkPhysicalDeviceMemoryProperties& memoryProperties = allocator->m_MemProps; + + json.WriteString("API"); + json.WriteString("Vulkan"); + + json.WriteString("apiVersion"); + json.BeginString(); + json.ContinueString(VK_VERSION_MAJOR(deviceProperties.apiVersion)); + json.ContinueString("."); + json.ContinueString(VK_VERSION_MINOR(deviceProperties.apiVersion)); + json.ContinueString("."); + json.ContinueString(VK_VERSION_PATCH(deviceProperties.apiVersion)); + json.EndString(); + + json.WriteString("GPU"); + json.WriteString(deviceProperties.deviceName); + json.WriteString("deviceType"); + json.WriteNumber(static_cast(deviceProperties.deviceType)); + + json.WriteString("maxMemoryAllocationCount"); + json.WriteNumber(deviceProperties.limits.maxMemoryAllocationCount); + json.WriteString("bufferImageGranularity"); + json.WriteNumber(deviceProperties.limits.bufferImageGranularity); + json.WriteString("nonCoherentAtomSize"); + json.WriteNumber(deviceProperties.limits.nonCoherentAtomSize); + + json.WriteString("memoryHeapCount"); + json.WriteNumber(memoryProperties.memoryHeapCount); + json.WriteString("memoryTypeCount"); + json.WriteNumber(memoryProperties.memoryTypeCount); + } + json.EndObject(); + } + { + json.WriteString("Total"); + VmaPrintDetailedStatistics(json, stats.total); + } + { + json.WriteString("MemoryInfo"); + json.BeginObject(); + { + for (uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex) + { + json.BeginString("Heap "); + json.ContinueString(heapIndex); + json.EndString(); + json.BeginObject(); + { + const VkMemoryHeap& heapInfo = allocator->m_MemProps.memoryHeaps[heapIndex]; + json.WriteString("Flags"); + json.BeginArray(true); + { + if (heapInfo.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) + json.WriteString("DEVICE_LOCAL"); + #if VMA_VULKAN_VERSION >= 1001000 + if (heapInfo.flags & VK_MEMORY_HEAP_MULTI_INSTANCE_BIT) + json.WriteString("MULTI_INSTANCE"); + #endif + + VkMemoryHeapFlags flags = heapInfo.flags & + ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT + #if VMA_VULKAN_VERSION >= 1001000 + | VK_MEMORY_HEAP_MULTI_INSTANCE_BIT + #endif + ); + if (flags != 0) + json.WriteNumber(flags); + } + json.EndArray(); + + json.WriteString("Size"); + json.WriteNumber(heapInfo.size); + + json.WriteString("Budget"); + json.BeginObject(); + { + json.WriteString("BudgetBytes"); + json.WriteNumber(budgets[heapIndex].budget); + json.WriteString("UsageBytes"); + json.WriteNumber(budgets[heapIndex].usage); + } + json.EndObject(); + + json.WriteString("Stats"); + VmaPrintDetailedStatistics(json, stats.memoryHeap[heapIndex]); + + json.WriteString("MemoryPools"); + json.BeginObject(); + { + for (uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex) + { + if (allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex) + { + json.BeginString("Type "); + json.ContinueString(typeIndex); + json.EndString(); + json.BeginObject(); + { + json.WriteString("Flags"); + json.BeginArray(true); + { + VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags; + if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) + json.WriteString("DEVICE_LOCAL"); + if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + json.WriteString("HOST_VISIBLE"); + if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + json.WriteString("HOST_COHERENT"); + if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) + json.WriteString("HOST_CACHED"); + if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) + json.WriteString("LAZILY_ALLOCATED"); + #if VMA_VULKAN_VERSION >= 1001000 + if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) + json.WriteString("PROTECTED"); + #endif + #if VK_AMD_device_coherent_memory + if (flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) + json.WriteString("DEVICE_COHERENT_AMD"); + if (flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) + json.WriteString("DEVICE_UNCACHED_AMD"); + #endif + + flags &= ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT + #if VMA_VULKAN_VERSION >= 1001000 + | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT + #endif + #if VK_AMD_device_coherent_memory + | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY + | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY + #endif + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT); + if (flags != 0) + json.WriteNumber(flags); + } + json.EndArray(); + + json.WriteString("Stats"); + VmaPrintDetailedStatistics(json, stats.memoryType[typeIndex]); + } + json.EndObject(); + } + } + + } + json.EndObject(); + } + json.EndObject(); + } + } + json.EndObject(); + } + + if (detailedMap == VK_TRUE) + allocator->PrintDetailedMap(json); + + json.EndObject(); + } + + *ppStatsString = VmaCreateStringCopy(allocator->GetAllocationCallbacks(), sb.GetData(), sb.GetLength()); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( + VmaAllocator allocator, + char* pStatsString) +{ + if(pStatsString != VMA_NULL) + { + VMA_ASSERT(allocator); + VmaFreeString(allocator->GetAllocationCallbacks(), pStatsString); + } +} + +#endif // VMA_STATS_STRING_ENABLED + +/* +This function is not protected by any mutex because it just reads immutable data. +*/ +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex( + VmaAllocator allocator, + uint32_t memoryTypeBits, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + uint32_t* pMemoryTypeIndex) +{ + VMA_ASSERT(allocator != VK_NULL_HANDLE); + VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); + VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + + return allocator->FindMemoryTypeIndex(memoryTypeBits, pAllocationCreateInfo, VmaBufferImageUsage::UNKNOWN, pMemoryTypeIndex); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo( + VmaAllocator allocator, + const VkBufferCreateInfo* pBufferCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + uint32_t* pMemoryTypeIndex) +{ + VMA_ASSERT(allocator != VK_NULL_HANDLE); + VMA_ASSERT(pBufferCreateInfo != VMA_NULL); + VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); + VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + + const VkDevice hDev = allocator->m_hDevice; + const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions(); + VkResult res = VK_SUCCESS; + +#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + if(funcs->vkGetDeviceBufferMemoryRequirements) + { + // Can query straight from VkBufferCreateInfo :) + VkDeviceBufferMemoryRequirementsKHR devBufMemReq = {VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR}; + devBufMemReq.pCreateInfo = pBufferCreateInfo; + + VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2}; + (*funcs->vkGetDeviceBufferMemoryRequirements)(hDev, &devBufMemReq, &memReq); + + res = allocator->FindMemoryTypeIndex( + memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, + VmaBufferImageUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5), pMemoryTypeIndex); + } + else +#endif // VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + { + // Must create a dummy buffer to query :( + VkBuffer hBuffer = VK_NULL_HANDLE; + res = funcs->vkCreateBuffer( + hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer); + if(res == VK_SUCCESS) + { + VkMemoryRequirements memReq = {}; + funcs->vkGetBufferMemoryRequirements(hDev, hBuffer, &memReq); + + res = allocator->FindMemoryTypeIndex( + memReq.memoryTypeBits, pAllocationCreateInfo, + VmaBufferImageUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5), pMemoryTypeIndex); + + funcs->vkDestroyBuffer( + hDev, hBuffer, allocator->GetAllocationCallbacks()); + } + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo( + VmaAllocator allocator, + const VkImageCreateInfo* pImageCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + uint32_t* pMemoryTypeIndex) +{ + VMA_ASSERT(allocator != VK_NULL_HANDLE); + VMA_ASSERT(pImageCreateInfo != VMA_NULL); + VMA_ASSERT(pAllocationCreateInfo != VMA_NULL); + VMA_ASSERT(pMemoryTypeIndex != VMA_NULL); + + const VkDevice hDev = allocator->m_hDevice; + const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions(); + VkResult res = VK_SUCCESS; + +#if VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + if(funcs->vkGetDeviceImageMemoryRequirements) + { + // Can query straight from VkImageCreateInfo :) + VkDeviceImageMemoryRequirementsKHR devImgMemReq = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR}; + devImgMemReq.pCreateInfo = pImageCreateInfo; + VMA_ASSERT(pImageCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY && (pImageCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_COPY) == 0 && + "Cannot use this VkImageCreateInfo with vmaFindMemoryTypeIndexForImageInfo as I don't know what to pass as VkDeviceImageMemoryRequirements::planeAspect."); + + VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2}; + (*funcs->vkGetDeviceImageMemoryRequirements)(hDev, &devImgMemReq, &memReq); + + res = allocator->FindMemoryTypeIndex( + memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, + VmaBufferImageUsage(*pImageCreateInfo), pMemoryTypeIndex); + } + else +#endif // VMA_KHR_MAINTENANCE4 || VMA_VULKAN_VERSION >= 1003000 + { + // Must create a dummy image to query :( + VkImage hImage = VK_NULL_HANDLE; + res = funcs->vkCreateImage( + hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage); + if(res == VK_SUCCESS) + { + VkMemoryRequirements memReq = {}; + funcs->vkGetImageMemoryRequirements(hDev, hImage, &memReq); + + res = allocator->FindMemoryTypeIndex( + memReq.memoryTypeBits, pAllocationCreateInfo, + VmaBufferImageUsage(*pImageCreateInfo), pMemoryTypeIndex); + + funcs->vkDestroyImage( + hDev, hImage, allocator->GetAllocationCallbacks()); + } + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool( + VmaAllocator allocator, + const VmaPoolCreateInfo* pCreateInfo, + VmaPool* pPool) +{ + VMA_ASSERT(allocator && pCreateInfo && pPool); + + VMA_DEBUG_LOG("vmaCreatePool"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->CreatePool(pCreateInfo, pPool); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool( + VmaAllocator allocator, + VmaPool pool) +{ + VMA_ASSERT(allocator); + + if(pool == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaDestroyPool"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->DestroyPool(pool); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics( + VmaAllocator allocator, + VmaPool pool, + VmaStatistics* pPoolStats) +{ + VMA_ASSERT(allocator && pool && pPoolStats); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->GetPoolStatistics(pool, pPoolStats); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics( + VmaAllocator allocator, + VmaPool pool, + VmaDetailedStatistics* pPoolStats) +{ + VMA_ASSERT(allocator && pool && pPoolStats); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->CalculatePoolStatistics(pool, pPoolStats); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool) +{ + VMA_ASSERT(allocator && pool); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VMA_DEBUG_LOG("vmaCheckPoolCorruption"); + + return allocator->CheckPoolCorruption(pool); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName( + VmaAllocator allocator, + VmaPool pool, + const char** ppName) +{ + VMA_ASSERT(allocator && pool && ppName); + + VMA_DEBUG_LOG("vmaGetPoolName"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *ppName = pool->GetName(); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName( + VmaAllocator allocator, + VmaPool pool, + const char* pName) +{ + VMA_ASSERT(allocator && pool); + + VMA_DEBUG_LOG("vmaSetPoolName"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + pool->SetName(pName); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory( + VmaAllocator allocator, + const VkMemoryRequirements* pVkMemoryRequirements, + const VmaAllocationCreateInfo* pCreateInfo, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocation); + + VMA_DEBUG_LOG("vmaAllocateMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VkResult result = allocator->AllocateMemory( + *pVkMemoryRequirements, + false, // requiresDedicatedAllocation + false, // prefersDedicatedAllocation + VK_NULL_HANDLE, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_UNKNOWN, + 1, // allocationCount + pAllocation); + + if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return result; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages( + VmaAllocator allocator, + const VkMemoryRequirements* pVkMemoryRequirements, + const VmaAllocationCreateInfo* pCreateInfo, + size_t allocationCount, + VmaAllocation* pAllocations, + VmaAllocationInfo* pAllocationInfo) +{ + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations); + + VMA_DEBUG_LOG("vmaAllocateMemoryPages"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VkResult result = allocator->AllocateMemory( + *pVkMemoryRequirements, + false, // requiresDedicatedAllocation + false, // prefersDedicatedAllocation + VK_NULL_HANDLE, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_UNKNOWN, + allocationCount, + pAllocations); + + if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS) + { + for(size_t i = 0; i < allocationCount; ++i) + { + allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i); + } + } + + return result; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer( + VmaAllocator allocator, + VkBuffer buffer, + const VmaAllocationCreateInfo* pCreateInfo, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && buffer != VK_NULL_HANDLE && pCreateInfo && pAllocation); + + VMA_DEBUG_LOG("vmaAllocateMemoryForBuffer"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetBufferMemoryRequirements(buffer, vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation); + + VkResult result = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + buffer, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount + pAllocation); + + if(pAllocationInfo && result == VK_SUCCESS) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return result; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage( + VmaAllocator allocator, + VkImage image, + const VmaAllocationCreateInfo* pCreateInfo, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && image != VK_NULL_HANDLE && pCreateInfo && pAllocation); + + VMA_DEBUG_LOG("vmaAllocateMemoryForImage"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetImageMemoryRequirements(image, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + VkResult result = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + VK_NULL_HANDLE, // dedicatedBuffer + image, // dedicatedImage + VmaBufferImageUsage::UNKNOWN, // dedicatedBufferImageUsage + *pCreateInfo, + VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN, + 1, // allocationCount + pAllocation); + + if(pAllocationInfo && result == VK_SUCCESS) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return result; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory( + VmaAllocator allocator, + VmaAllocation allocation) +{ + VMA_ASSERT(allocator); + + if(allocation == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaFreeMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->FreeMemory( + 1, // allocationCount + &allocation); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages( + VmaAllocator allocator, + size_t allocationCount, + const VmaAllocation* pAllocations) +{ + if(allocationCount == 0) + { + return; + } + + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaFreeMemoryPages"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->FreeMemory(allocationCount, pAllocations); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo( + VmaAllocator allocator, + VmaAllocation allocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && allocation && pAllocationInfo); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->GetAllocationInfo(allocation, pAllocationInfo); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo2( + VmaAllocator allocator, + VmaAllocation allocation, + VmaAllocationInfo2* pAllocationInfo) +{ + VMA_ASSERT(allocator && allocation && pAllocationInfo); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->GetAllocationInfo2(allocation, pAllocationInfo); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData( + VmaAllocator allocator, + VmaAllocation allocation, + void* pUserData) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocation->SetUserData(allocator, pUserData); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const char* VMA_NULLABLE pName) +{ + allocation->SetName(allocator, pName); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkMemoryPropertyFlags* VMA_NOT_NULL pFlags) +{ + VMA_ASSERT(allocator && allocation && pFlags); + const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex(); + *pFlags = allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory( + VmaAllocator allocator, + VmaAllocation allocation, + void** ppData) +{ + VMA_ASSERT(allocator && allocation && ppData); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->Map(allocation, ppData); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory( + VmaAllocator allocator, + VmaAllocation allocation) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + allocator->Unmap(allocation); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize offset, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_LOG("vmaFlushAllocation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize offset, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && allocation); + + VMA_DEBUG_LOG("vmaInvalidateAllocation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations( + VmaAllocator allocator, + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, + const VkDeviceSize* sizes) +{ + VMA_ASSERT(allocator); + + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocations); + + VMA_DEBUG_LOG("vmaFlushAllocations"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations( + VmaAllocator allocator, + uint32_t allocationCount, + const VmaAllocation* allocations, + const VkDeviceSize* offsets, + const VkDeviceSize* sizes) +{ + VMA_ASSERT(allocator); + + if(allocationCount == 0) + { + return VK_SUCCESS; + } + + VMA_ASSERT(allocations); + + VMA_DEBUG_LOG("vmaInvalidateAllocations"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyMemoryToAllocation( + VmaAllocator allocator, + const void* pSrcHostPointer, + VmaAllocation dstAllocation, + VkDeviceSize dstAllocationLocalOffset, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && pSrcHostPointer && dstAllocation); + + if(size == 0) + { + return VK_SUCCESS; + } + + VMA_DEBUG_LOG("vmaCopyMemoryToAllocation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->CopyMemoryToAllocation(pSrcHostPointer, dstAllocation, dstAllocationLocalOffset, size); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCopyAllocationToMemory( + VmaAllocator allocator, + VmaAllocation srcAllocation, + VkDeviceSize srcAllocationLocalOffset, + void* pDstHostPointer, + VkDeviceSize size) +{ + VMA_ASSERT(allocator && srcAllocation && pDstHostPointer); + + if(size == 0) + { + return VK_SUCCESS; + } + + VMA_DEBUG_LOG("vmaCopyAllocationToMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->CopyAllocationToMemory(srcAllocation, srcAllocationLocalOffset, pDstHostPointer, size); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption( + VmaAllocator allocator, + uint32_t memoryTypeBits) +{ + VMA_ASSERT(allocator); + + VMA_DEBUG_LOG("vmaCheckCorruption"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->CheckCorruption(memoryTypeBits); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation( + VmaAllocator allocator, + const VmaDefragmentationInfo* pInfo, + VmaDefragmentationContext* pContext) +{ + VMA_ASSERT(allocator && pInfo && pContext); + + VMA_DEBUG_LOG("vmaBeginDefragmentation"); + + if (pInfo->pool != VMA_NULL) + { + // Check if run on supported algorithms + if (pInfo->pool->m_BlockVector.GetAlgorithm() & VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) + return VK_ERROR_FEATURE_NOT_PRESENT; + } + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *pContext = vma_new(allocator, VmaDefragmentationContext_T)(allocator, *pInfo); + return VK_SUCCESS; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation( + VmaAllocator allocator, + VmaDefragmentationContext context, + VmaDefragmentationStats* pStats) +{ + VMA_ASSERT(allocator && context); + + VMA_DEBUG_LOG("vmaEndDefragmentation"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + if (pStats) + context->GetStats(*pStats); + vma_delete(allocator, context); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo) +{ + VMA_ASSERT(context && pPassInfo); + + VMA_DEBUG_LOG("vmaBeginDefragmentationPass"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return context->DefragmentPassBegin(*pPassInfo); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass( + VmaAllocator VMA_NOT_NULL allocator, + VmaDefragmentationContext VMA_NOT_NULL context, + VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo) +{ + VMA_ASSERT(context && pPassInfo); + + VMA_DEBUG_LOG("vmaEndDefragmentationPass"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return context->DefragmentPassEnd(*pPassInfo); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory( + VmaAllocator allocator, + VmaAllocation allocation, + VkBuffer buffer) +{ + VMA_ASSERT(allocator && allocation && buffer); + + VMA_DEBUG_LOG("vmaBindBufferMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize allocationLocalOffset, + VkBuffer buffer, + const void* pNext) +{ + VMA_ASSERT(allocator && allocation && buffer); + + VMA_DEBUG_LOG("vmaBindBufferMemory2"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory( + VmaAllocator allocator, + VmaAllocation allocation, + VkImage image) +{ + VMA_ASSERT(allocator && allocation && image); + + VMA_DEBUG_LOG("vmaBindImageMemory"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindImageMemory(allocation, 0, image, VMA_NULL); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2( + VmaAllocator allocator, + VmaAllocation allocation, + VkDeviceSize allocationLocalOffset, + VkImage image, + const void* pNext) +{ + VMA_ASSERT(allocator && allocation && image); + + VMA_DEBUG_LOG("vmaBindImageMemory2"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + return allocator->BindImageMemory(allocation, allocationLocalOffset, image, pNext); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer( + VmaAllocator allocator, + const VkBufferCreateInfo* pBufferCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VkBuffer* pBuffer, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation); + + if(pBufferCreateInfo->size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + !allocator->m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_LOG("vmaCreateBuffer"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *pBuffer = VK_NULL_HANDLE; + *pAllocation = VK_NULL_HANDLE; + + // 1. Create VkBuffer. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( + allocator->m_hDevice, + pBufferCreateInfo, + allocator->GetAllocationCallbacks(), + pBuffer); + if(res >= 0) + { + // 2. vkGetBufferMemoryRequirements. + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + // 3. Allocate memory using allocator. + res = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + *pBuffer, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5), // dedicatedBufferImageUsage + *pAllocationCreateInfo, + VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount + pAllocation); + + if(res >= 0) + { + // 3. Bind buffer with memory. + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); + } + if(res >= 0) + { + // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); + #endif + if(pAllocationInfo != VMA_NULL) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return VK_SUCCESS; + } + allocator->FreeMemory( + 1, // allocationCount + pAllocation); + *pAllocation = VK_NULL_HANDLE; + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment( + VmaAllocator allocator, + const VkBufferCreateInfo* pBufferCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VkDeviceSize minAlignment, + VkBuffer* pBuffer, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && VmaIsPow2(minAlignment) && pBuffer && pAllocation); + + if(pBufferCreateInfo->size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + !allocator->m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_LOG("vmaCreateBufferWithAlignment"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *pBuffer = VK_NULL_HANDLE; + *pAllocation = VK_NULL_HANDLE; + + // 1. Create VkBuffer. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( + allocator->m_hDevice, + pBufferCreateInfo, + allocator->GetAllocationCallbacks(), + pBuffer); + if(res >= 0) + { + // 2. vkGetBufferMemoryRequirements. + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + // 2a. Include minAlignment + vkMemReq.alignment = VMA_MAX(vkMemReq.alignment, minAlignment); + + // 3. Allocate memory using allocator. + res = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + *pBuffer, // dedicatedBuffer + VK_NULL_HANDLE, // dedicatedImage + VmaBufferImageUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5), // dedicatedBufferImageUsage + *pAllocationCreateInfo, + VMA_SUBALLOCATION_TYPE_BUFFER, + 1, // allocationCount + pAllocation); + + if(res >= 0) + { + // 3. Bind buffer with memory. + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL); + } + if(res >= 0) + { + // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitBufferUsage(*pBufferCreateInfo, allocator->m_UseKhrMaintenance5); + #endif + if(pAllocationInfo != VMA_NULL) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return VK_SUCCESS; + } + allocator->FreeMemory( + 1, // allocationCount + pAllocation); + *pAllocation = VK_NULL_HANDLE; + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + *pBuffer = VK_NULL_HANDLE; + return res; + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer) +{ + return vmaCreateAliasingBuffer2(allocator, allocation, 0, pBufferCreateInfo, pBuffer); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo, + VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer) +{ + VMA_ASSERT(allocator && pBufferCreateInfo && pBuffer && allocation); + VMA_ASSERT(allocationLocalOffset + pBufferCreateInfo->size <= allocation->GetSize()); + + VMA_DEBUG_LOG("vmaCreateAliasingBuffer2"); + + *pBuffer = VK_NULL_HANDLE; + + if (pBufferCreateInfo->size == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + if ((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 && + !allocator->m_UseKhrBufferDeviceAddress) + { + VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used."); + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + // 1. Create VkBuffer. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)( + allocator->m_hDevice, + pBufferCreateInfo, + allocator->GetAllocationCallbacks(), + pBuffer); + if (res >= 0) + { + // 2. Bind buffer with memory. + res = allocator->BindBufferMemory(allocation, allocationLocalOffset, *pBuffer, VMA_NULL); + if (res >= 0) + { + return VK_SUCCESS; + } + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks()); + } + return res; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer( + VmaAllocator allocator, + VkBuffer buffer, + VmaAllocation allocation) +{ + VMA_ASSERT(allocator); + + if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaDestroyBuffer"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + if(buffer != VK_NULL_HANDLE) + { + (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks()); + } + + if(allocation != VK_NULL_HANDLE) + { + allocator->FreeMemory( + 1, // allocationCount + &allocation); + } +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage( + VmaAllocator allocator, + const VkImageCreateInfo* pImageCreateInfo, + const VmaAllocationCreateInfo* pAllocationCreateInfo, + VkImage* pImage, + VmaAllocation* pAllocation, + VmaAllocationInfo* pAllocationInfo) +{ + VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation); + + VMA_ASSERT((pImageCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_COPY) == 0 && + "vmaCreateImage() doesn't support disjoint multi-planar images. Please allocate memory for the planes using vmaAllocateMemory() and bind them using vmaBindImageMemory2()."); + + if(pImageCreateInfo->extent.width == 0 || + pImageCreateInfo->extent.height == 0 || + pImageCreateInfo->extent.depth == 0 || + pImageCreateInfo->mipLevels == 0 || + pImageCreateInfo->arrayLayers == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_LOG("vmaCreateImage"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + *pImage = VK_NULL_HANDLE; + *pAllocation = VK_NULL_HANDLE; + + // 1. Create VkImage. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)( + allocator->m_hDevice, + pImageCreateInfo, + allocator->GetAllocationCallbacks(), + pImage); + if(res == VK_SUCCESS) + { + VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ? + VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL : + VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR; + + // 2. Allocate memory using allocator. + VkMemoryRequirements vkMemReq = {}; + bool requiresDedicatedAllocation = false; + bool prefersDedicatedAllocation = false; + allocator->GetImageMemoryRequirements(*pImage, vkMemReq, + requiresDedicatedAllocation, prefersDedicatedAllocation); + + res = allocator->AllocateMemory( + vkMemReq, + requiresDedicatedAllocation, + prefersDedicatedAllocation, + VK_NULL_HANDLE, // dedicatedBuffer + *pImage, // dedicatedImage + VmaBufferImageUsage(*pImageCreateInfo), // dedicatedBufferImageUsage + *pAllocationCreateInfo, + suballocType, + 1, // allocationCount + pAllocation); + + if(res == VK_SUCCESS) + { + // 3. Bind image with memory. + if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0) + { + res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL); + } + if(res == VK_SUCCESS) + { + // All steps succeeded. + #if VMA_STATS_STRING_ENABLED + (*pAllocation)->InitImageUsage(*pImageCreateInfo); + #endif + if(pAllocationInfo != VMA_NULL) + { + allocator->GetAllocationInfo(*pAllocation, pAllocationInfo); + } + + return VK_SUCCESS; + } + allocator->FreeMemory( + 1, // allocationCount + pAllocation); + *pAllocation = VK_NULL_HANDLE; + (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks()); + *pImage = VK_NULL_HANDLE; + return res; + } + (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks()); + *pImage = VK_NULL_HANDLE; + return res; + } + return res; +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage) +{ + return vmaCreateAliasingImage2(allocator, allocation, 0, pImageCreateInfo, pImage); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage2( + VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, + VkDeviceSize allocationLocalOffset, + const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo, + VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage) +{ + VMA_ASSERT(allocator && pImageCreateInfo && pImage && allocation); + + *pImage = VK_NULL_HANDLE; + + VMA_DEBUG_LOG("vmaCreateImage2"); + + if (pImageCreateInfo->extent.width == 0 || + pImageCreateInfo->extent.height == 0 || + pImageCreateInfo->extent.depth == 0 || + pImageCreateInfo->mipLevels == 0 || + pImageCreateInfo->arrayLayers == 0) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + // 1. Create VkImage. + VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)( + allocator->m_hDevice, + pImageCreateInfo, + allocator->GetAllocationCallbacks(), + pImage); + if (res >= 0) + { + // 2. Bind image with memory. + res = allocator->BindImageMemory(allocation, allocationLocalOffset, *pImage, VMA_NULL); + if (res >= 0) + { + return VK_SUCCESS; + } + (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks()); + } + return res; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage( + VmaAllocator VMA_NOT_NULL allocator, + VkImage VMA_NULLABLE_NON_DISPATCHABLE image, + VmaAllocation VMA_NULLABLE allocation) +{ + VMA_ASSERT(allocator); + + if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE) + { + return; + } + + VMA_DEBUG_LOG("vmaDestroyImage"); + + VMA_DEBUG_GLOBAL_MUTEX_LOCK + + if(image != VK_NULL_HANDLE) + { + (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks()); + } + if(allocation != VK_NULL_HANDLE) + { + allocator->FreeMemory( + 1, // allocationCount + &allocation); + } +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock( + const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo, + VmaVirtualBlock VMA_NULLABLE * VMA_NOT_NULL pVirtualBlock) +{ + VMA_ASSERT(pCreateInfo && pVirtualBlock); + VMA_ASSERT(pCreateInfo->size > 0); + VMA_DEBUG_LOG("vmaCreateVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + *pVirtualBlock = vma_new(pCreateInfo->pAllocationCallbacks, VmaVirtualBlock_T)(*pCreateInfo); + return VK_SUCCESS; + + /* + Code for the future if we ever need a separate Init() method that could fail: + + VkResult res = (*pVirtualBlock)->Init(); + if(res < 0) + { + vma_delete(pCreateInfo->pAllocationCallbacks, *pVirtualBlock); + *pVirtualBlock = VK_NULL_HANDLE; + } + return res; + */ +} + +VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(VmaVirtualBlock VMA_NULLABLE virtualBlock) +{ + if(virtualBlock != VK_NULL_HANDLE) + { + VMA_DEBUG_LOG("vmaDestroyVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + VkAllocationCallbacks allocationCallbacks = virtualBlock->m_AllocationCallbacks; // Have to copy the callbacks when destroying. + vma_delete(&allocationCallbacks, virtualBlock); + } +} + +VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(VmaVirtualBlock VMA_NOT_NULL virtualBlock) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaIsVirtualBlockEmpty"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + return virtualBlock->IsEmpty() ? VK_TRUE : VK_FALSE; +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pVirtualAllocInfo != VMA_NULL); + VMA_DEBUG_LOG("vmaGetVirtualAllocationInfo"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->GetAllocationInfo(allocation, *pVirtualAllocInfo); +} + +VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation, + VkDeviceSize* VMA_NULLABLE pOffset) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pCreateInfo != VMA_NULL && pAllocation != VMA_NULL); + VMA_DEBUG_LOG("vmaVirtualAllocate"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + return virtualBlock->Allocate(*pCreateInfo, *pAllocation, pOffset); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(VmaVirtualBlock VMA_NOT_NULL virtualBlock, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation) +{ + if(allocation != VK_NULL_HANDLE) + { + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaVirtualFree"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->Free(allocation); + } +} + +VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(VmaVirtualBlock VMA_NOT_NULL virtualBlock) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaClearVirtualBlock"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->Clear(); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, void* VMA_NULLABLE pUserData) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_LOG("vmaSetVirtualAllocationUserData"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->SetAllocationUserData(allocation, pUserData); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaStatistics* VMA_NOT_NULL pStats) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL); + VMA_DEBUG_LOG("vmaGetVirtualBlockStatistics"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->GetStatistics(*pStats); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + VmaDetailedStatistics* VMA_NOT_NULL pStats) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL); + VMA_DEBUG_LOG("vmaCalculateVirtualBlockStatistics"); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + virtualBlock->CalculateDetailedStatistics(*pStats); +} + +#if VMA_STATS_STRING_ENABLED + +VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap) +{ + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && ppStatsString != VMA_NULL); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + const VkAllocationCallbacks* allocationCallbacks = virtualBlock->GetAllocationCallbacks(); + VmaStringBuilder sb(allocationCallbacks); + virtualBlock->BuildStatsString(detailedMap != VK_FALSE, sb); + *ppStatsString = VmaCreateStringCopy(allocationCallbacks, sb.GetData(), sb.GetLength()); +} + +VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock, + char* VMA_NULLABLE pStatsString) +{ + if(pStatsString != VMA_NULL) + { + VMA_ASSERT(virtualBlock != VK_NULL_HANDLE); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString); + } +} +#if VMA_EXTERNAL_MEMORY_WIN32 +VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator, + VmaAllocation VMA_NOT_NULL allocation, HANDLE hTargetProcess, HANDLE* VMA_NOT_NULL pHandle) +{ + VMA_ASSERT(allocator && allocation && pHandle); + VMA_DEBUG_GLOBAL_MUTEX_LOCK; + return allocation->GetWin32Handle(allocator, hTargetProcess, pHandle); +} +#endif // VMA_EXTERNAL_MEMORY_WIN32 +#endif // VMA_STATS_STRING_ENABLED +#endif // _VMA_PUBLIC_INTERFACE +#endif // VMA_IMPLEMENTATION + +/** +\page faq Frequenty asked questions + +What is VMA? + +Vulkan(R) Memory Allocator (VMA) is a software library for developers who use the Vulkan graphics API in their code. +It is written in C++. + +What is the license of VMA? + +VMA is licensed under MIT, which means it is open source and free software. + +What is the purpose of VMA? + +VMA helps with handling one aspect of Vulkan usage, which is device memory management - +allocation of `VkDeviceMemory` objects, and creation of `VkBuffer` and `VkImage` objects. + +Do I need to use VMA? + +You don't need to, but it may be beneficial in many cases. +Vulkan is a complex and low-level API, so libraries like this that abstract certain aspects of the API +and bring them to a higher level are useful. +When developing any non-trivial Vulkan application, you likely need to use a memory allocator. +Using VMA can save time compared to implementing your own. + +When should I not use VMA? + +While VMA is useful for most applications that use the Vulkan API, there are cases +when it may be a better choice not to use it. +For example, if the application is very simple, e.g. serving as a sample or a learning exercise +to help you understand or teach others the basics of Vulkan, +and it creates only a small number of buffers and images, then including VMA may be an overkill. +Developing your own memory allocator may also be a good learning exercise. + +What are the benefits of using VMA? + +-# VMA helps in choosing the optimal memory type for your resource (buffer or image). + In Vulkan, we have a two-level hierarchy of memory heaps and types with different flags, + and each device can expose a different set of those. + Implementing logic that would select the best memory type on each platform is a non-trivial task. + VMA does that, expecting only a high-level description of the intended usage of your resource. + For more information, see \subpage choosing_memory_type. +-# VMA allocates large blocks of `VkDeviceMemory` and sub-allocates parts of them for your resources. + Allocating a new block of device memory may be a time-consuming operation. + Some platforms also have a limit on the maximum number of those blocks (`VkPhysicalDeviceLimits::maxMemoryAllocationCount`) + as low as 4096, so allocating a separate one for each resource is not an option. + Sub-allocating parts of a memory block requires implementing an allocation algorithm, + which is a non-trivial task. + VMA does that, using an advanced and efficient algorithm that works well in various use cases. +-# VMA offers a simple API that allows creating buffers and textures within one function call. + In Vulkan, the creation of a resource is a multi-step process. + You need to create a `VkBuffer` or `VkImage`, ask it for memory requirements, + allocate a `VkDeviceMemory` object, and finally bind the resource to the memory block. + VMA does that automatically under a simple API within one function call: vmaCreateBuffer(), vmaCreateImage(). + +The library is doing much more under the hood. +For example, it respects limits like `bufferImageGranularity`, `nonCoherentAtomSize`, +and `VkMemoryDedicatedRequirements` automatically, so you don't need to think about it. + +Which version should I pick? + +You can just pick [the latest version from the "master" branch](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator). +It is kept in a good shape most of the time, compiling and working correctly, +with no compatibility-breaking changes and no unfinished code. + +If you want an even more stable version, you can pick +[the latest official release](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/releases). +Current code from the master branch is occasionally tagged as a release, +with [CHANGELOG](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/blob/master/CHANGELOG.md) +carefully curated to enumerate all important changes since the previous version. + +The library uses [Semantic Versioning](https://semver.org/), +which means versions that only differ in the patch number are forward and backward compatible +(e.g., only fixing some bugs), while versions that differ in the minor number are backward compatible +(e.g., only adding new functions to the API, but not removing or changing existing ones). + +How to integrate it with my code? + +VMA is an STB-style single-header C++ library. + +You can pull the entire GitHub repository, e.g. using Git submodules. +The repository contains ancillary files like the Cmake script, Doxygen config file, +sample application, test suite, and others. +You can compile it as a library and link with your project. + +However, a simpler way is taking the single file "include/vk_mem_alloc.h" and including it in your project. +This extensive file contains all you need: a copyright notice, +declarations of the public library interface (API), its internal implementation, +and even the documentation in form of Doxygen-style comments. + +The "STB style" means not everything is implemented as inline functions in the header file. +You need to extract the internal implementation using a special macro. +This means that in every .cpp file where you need to use the library you should +`#include "vk_mem_alloc.h"` to include its public interface, +but additionally in exactly one .cpp file you should `#define VMA_IMPLEMENTATION` +before this `#include` to enable its internal implementation. +For more information, see [Project setup](@ref quick_start_project_setup). + +Does the library work with C or C++? + +The internal implementation of VMA is written in C++. +It is distributed in the source format, so you need a compiler supporting at least C++14 to build it. + +However, the public interface of the library is written in C - using only enums, structs, and global functions, +in the same style as Vulkan, so you can use the library in the C code. + +I am not a fan of modern C++. Can I still use it? + +Very likely yes. +We acknowledge that many C++ developers, especially in the games industry, +do not appreciate all the latest features that the language has to offer. + +- VMA doesn't throw or catch any C++ exceptions. + It reports errors by returning a `VkResult` value instead, just like Vulkan. + If you don't use exceptions in your project, your code is not exception-safe, + or even if you disable exception handling in the compiler options, you can still use VMA. +- VMA doesn't use C++ run-time type information like `typeid` or `dynamic_cast`, + so if you disable RTTI in the compiler options, you can still use the library. +- VMA uses only a limited subset of standard C and C++ library. + It doesn't use STL containers like `std::vector`, `map`, or `string`, + either in the public interface nor in the internal implementation. + It implements its own containers instead. +- If you don't use the default heap memory allocator through `malloc/free` or `new/delete` + but implement your own allocator instead, you can pass it to VMA and + the library will use your functions for every dynamic heap allocation made internally, + as well as passing it further to Vulkan functions. For details, see [Custom host memory allocator](@ref custom_memory_allocator). + +Is it available for other programming languages? + +VMA is a C++ library with C interface in similar style as Vulkan. +An object-oriented C++ wrapper or bindings to other programming languages are out of scope of this project, +but they are welcome as external projects. +Some of them are listed in [README.md, "See also" section](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator?tab=readme-ov-file#see-also), +including binding to C++, Python, Rust, and Haskell. +Before using any of them, please check if they are still maintained and updated to use a recent version of VMA. + +What platforms does it support? + +VMA relies only on Vulkan and some parts of the standard C and C++ library, +so it supports any platform where a C++ compiler and Vulkan are available. +It is developed mostly on Microsoft(R) Windows(R), +but it has been successfully used in Linux(R), MacOS, Android, and even FreeBSD and Raspberry Pi. + +Does it only work on AMD GPUs? + +No! While VMA is published by AMD, it works on any GPU that supports Vulkan, +whether a discrete PC graphics card, a processor integrated graphics, or a mobile SoC. +It doesn't give AMD GPUs any advantage over any other GPUs. + +What Vulkan versions and extensions are supported? + +VMA is updated to support the latest versions of Vulkan. +It currently supports Vulkan up to 1.4. +The library also supports older versions down to the first release of Vulkan 1.0. +Defining a higher minimum version support would help simplify the code, +but we acknowledge that developers on some platforms like Android still use older versions, +so the support is provided for all of them. + +Among many extensions available for Vulkan, only a few interact with memory management. +VMA can automatically take advantage of them. Some of them are: +VK_EXT_memory_budget, VK_EXT_memory_priority, VK_KHR_external_memory_win32, and VK_KHR_maintenance* +extensions that are later promoted to the new versions of the core Vulkan API. + +To use them, it is your responsibility to validate if they are available on the current system and if so, +enable them while creating the Vulkan device object. +You also need to pass appropriate #VmaAllocatorCreateFlagBits to inform VMA that they are enabled. +Then, the library will automatically take advantage of them. +For more information and the full list of supported extensions, see [Enabling extensions](@ref quick_start_initialization_enabling_extensions). + +Does it support other graphics APIs, like Microsoft DirectX(R) 12? + +No, but we offer an equivalent library for DirectX 12: +[D3D12 Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator). +It uses the same core allocation algorithm. +It also shares many features with VMA, like the support for custom pools and virtual allocator. +However, it is not identical in terms of the features supported. +Its API also looks different, because while the interface of VMA is similar in style to Vulkan, +the interface of D3D12MA is similar to DirectX 12. + +Is the library lightweight? + +It depends on how you define it. +VMA is implemented with high-performance and real-time applications like video games in mind. +The CPU performance overhead of using this library is low. +It uses a high-quality allocation algorithm called Two-Level Segregated Fit (TLSF), +which in most cases can find a free place for a new allocation in few steps. +The library also doesn't perform too many CPU heap allocations. +In many cases, the allocation happens with 0 new CPU heap allocations performed by the library. +Even the creation of a #VmaAllocation object doesn't typically feature an CPU allocation, +because these objects are returned out of a dedicated memory pool. + +On the other hand, however, VMA needs some extra memory and extra time +to maintain the metadata about the occupied and free regions of the memory blocks, +and the algorithms and data structures used must be generic enough to work well in most cases. +If you develop your program for a very resource-constrained platform, +a custom allocator simpler than VMA may be a better choice. + +Does it have a documentation? + +Yes! VMA comes with full documentation of all elements of the API (functions, structures, enums), +as well as many generic chapters that provide an introduction, +describe core concepts of the library, good practices, etc. +The entire documentation is written in form of code comments inside "vk_mem_alloc.h", in Doxygen format. +You can access it in multiple ways: + +- Browsable online: https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/ +- Local HTML pages available after you clone the repository and open file "docs/html/index.html". +- You can rebuild the documentation in HTML or some other format from the source code using Doxygen. + Configuration file "Doxyfile" is part of the repository. +- Finally, you can just read the comments preceding declarations of any public functions of the library. + +Is it a mature project? + +Yes! The library is in development since June 2017, has over 1000 commits, over 400 issue tickets +and pull requests (most of them resolved), and over 70 contributors. +It is distributed together with Vulkan SDK. +It is used by many software projects, including some large and popular ones like Qt or Blender, +as well as some AAA games. +According to the [LunarG 2024 Ecosystem Survey](https://www.lunarg.com/2024-ecosystem-survey-progress-report-released/), +it is used by over 50% of Vulkan developers. + +How can I contribute to the project? + +If you have an idea for improvement or a feature request, +you can go to [the library repository](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) +and create an Issue ticket, describing your idea. +You can also implement it yourself by forking the repository, making changes to the code, +and creating a Pull request. + +If you want to ask a question, you can also create a ticket the same way. +Before doing this, please make sure you read the relevant part of the Vulkan specification and VMA documentation, +where you may find the answers to your question. + +If you want to report a suspected bug, you can also create a ticket the same way. +Before doing this, please put some effort into the investigation of whether the bug is really +in the library and not in your code or in the Vulkan implementation (the GPU driver) on your platform: + +- Enable Vulkan validation layer and make sure it is free from any errors. +- Make sure `VMA_ASSERT` is defined to an implementation that can report a failure and not ignore it. +- Try making your allocation using pure Vulkan functions rather than VMA and see if the bug persists. + +I found some compilation warnings. How can we fix them? + +Seeing compiler warnings may be annoying to some developers, +but it is a design decision to not fix all of them. +Due to the nature of the C++ language, certain preprocessor macros can make some variables unused, +function parameters unreferenced, or conditional expressions constant in some configurations. +The code of this library should not be bigger or more complicated just to silence these warnings. +It is recommended to disable such warnings instead. +For more information, see [Features not supported](@ref general_considerations_features_not_supported). + +However, if you observe a warning that is really dangerous, e.g., +about an implicit conversion from a larger to a smaller integer type, please report it and it will be fixed ASAP. + + +\page quick_start Quick start + +\section quick_start_project_setup Project setup + +Vulkan Memory Allocator comes in form of a "stb-style" single header file. +While you can pull the entire repository e.g. as Git module, there is also Cmake script provided, +you don't need to build it as a separate library project. +You can add file "vk_mem_alloc.h" directly to your project and submit it to code repository next to your other source files. + +"Single header" doesn't mean that everything is contained in C/C++ declarations, +like it tends to be in case of inline functions or C++ templates. +It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro. +If you don't do it properly, it will result in linker errors. + +To do it properly: + +-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library. + This includes declarations of all members of the library. +-# In exactly one CPP file define following macro before this include. + It enables also internal definitions. + +\code +#define VMA_IMPLEMENTATION +#include "vk_mem_alloc.h" +\endcode + +It may be a good idea to create dedicated CPP file just for this purpose, e.g. "VmaUsage.cpp". + +This library includes header ``, which in turn +includes `` on Windows. If you need some specific macros defined +before including these headers (like `WIN32_LEAN_AND_MEAN` or +`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define +them before every `#include` of this library. +It may be a good idea to create a dedicate header file for this purpose, e.g. "VmaUsage.h", +that will be included in other source files instead of VMA header directly. + +This library is written in C++, but has C-compatible interface. +Thus, you can include and use "vk_mem_alloc.h" in C or C++ code, but full +implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C. +Some features of C++14 are used and required. Features of C++20 are used optionally when available. +Some headers of standard C and C++ library are used, but STL containers, RTTI, or C++ exceptions are not used. + + +\section quick_start_initialization Initialization + +VMA offers library interface in a style similar to Vulkan, with object handles like #VmaAllocation, +structures describing parameters of objects to be created like #VmaAllocationCreateInfo, +and errors codes returned from functions using `VkResult` type. + +The first and the main object that needs to be created is #VmaAllocator. +It represents the initialization of the entire library. +Only one such object should be created per `VkDevice`. +You should create it at program startup, after `VkDevice` was created, and before any device memory allocator needs to be made. +It must be destroyed before `VkDevice` is destroyed. + +At program startup: + +-# Initialize Vulkan to have `VkInstance`, `VkPhysicalDevice`, `VkDevice` object. +-# Fill VmaAllocatorCreateInfo structure and call vmaCreateAllocator() to create #VmaAllocator object. + +Only members `physicalDevice`, `device`, `instance` are required. +However, you should inform the library which Vulkan version do you use by setting +VmaAllocatorCreateInfo::vulkanApiVersion and which extensions did you enable +by setting VmaAllocatorCreateInfo::flags. +Otherwise, VMA would use only features of Vulkan 1.0 core with no extensions. +See below for details. + +\subsection quick_start_initialization_selecting_vulkan_version Selecting Vulkan version + +VMA supports Vulkan version down to 1.0, for backward compatibility. +If you want to use higher version, you need to inform the library about it. +This is a two-step process. + +Step 1: Compile time. By default, VMA compiles with code supporting the highest +Vulkan version found in the included `` that is also supported by the library. +If this is OK, you don't need to do anything. +However, if you want to compile VMA as if only some lower Vulkan version was available, +define macro `VMA_VULKAN_VERSION` before every `#include "vk_mem_alloc.h"`. +It should have decimal numeric value in form of ABBBCCC, where A = major, BBB = minor, CCC = patch Vulkan version. +For example, to compile against Vulkan 1.2: + +\code +#define VMA_VULKAN_VERSION 1002000 // Vulkan 1.2 +#include "vk_mem_alloc.h" +\endcode + +Step 2: Runtime. Even when compiled with higher Vulkan version available, +VMA can use only features of a lower version, which is configurable during creation of the #VmaAllocator object. +By default, only Vulkan 1.0 is used. +To initialize the allocator with support for higher Vulkan version, you need to set member +VmaAllocatorCreateInfo::vulkanApiVersion to an appropriate value, e.g. using constants like `VK_API_VERSION_1_2`. +See code sample below. + +\subsection quick_start_initialization_importing_vulkan_functions Importing Vulkan functions + +You may need to configure importing Vulkan functions. There are 4 ways to do this: + +-# **If you link with Vulkan static library** (e.g. "vulkan-1.lib" on Windows): + - You don't need to do anything. + - VMA will use these, as macro `VMA_STATIC_VULKAN_FUNCTIONS` is defined to 1 by default. +-# **If you want VMA to fetch pointers to Vulkan functions dynamically** using `vkGetInstanceProcAddr`, + `vkGetDeviceProcAddr` (this is the option presented in the example below): + - Define `VMA_STATIC_VULKAN_FUNCTIONS` to 0, `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 1. + - Provide pointers to these two functions via VmaVulkanFunctions::vkGetInstanceProcAddr, + VmaVulkanFunctions::vkGetDeviceProcAddr. + - The library will fetch pointers to all other functions it needs internally. +-# **If you fetch pointers to all Vulkan functions in a custom way**: + - Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0. + - Pass these pointers via structure #VmaVulkanFunctions. +-# **If you use [volk library](https://github.com/zeux/volk)**: + - Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0. + - Use function vmaImportVulkanFunctionsFromVolk() to fill in the structure #VmaVulkanFunctions. + For more information, see the description of this function. + +\subsection quick_start_initialization_enabling_extensions Enabling extensions + +VMA can automatically use following Vulkan extensions. +If you found them available on the selected physical device and you enabled them +while creating `VkInstance` / `VkDevice` object, inform VMA about their availability +by setting appropriate flags in VmaAllocatorCreateInfo::flags. + +Vulkan extension | VMA flag +------------------------------|----------------------------------------------------- +VK_KHR_dedicated_allocation | #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT +VK_KHR_bind_memory2 | #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT +VK_KHR_maintenance4 | #VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE4_BIT +VK_KHR_maintenance5 | #VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT +VK_EXT_memory_budget | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT +VK_KHR_buffer_device_address | #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT +VK_EXT_memory_priority | #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT +VK_AMD_device_coherent_memory | #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT +VK_KHR_external_memory_win32 | #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT + +Example with fetching pointers to Vulkan functions dynamically: + +\code +#define VMA_STATIC_VULKAN_FUNCTIONS 0 +#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 +#include "vk_mem_alloc.h" + +... + +VmaVulkanFunctions vulkanFunctions = {}; +vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; +vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; + +VmaAllocatorCreateInfo allocatorCreateInfo = {}; +allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; +allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2; +allocatorCreateInfo.physicalDevice = physicalDevice; +allocatorCreateInfo.device = device; +allocatorCreateInfo.instance = instance; +allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; + +VmaAllocator allocator; +vmaCreateAllocator(&allocatorCreateInfo, &allocator); + +// Entire program... + +// At the end, don't forget to: +vmaDestroyAllocator(allocator); +\endcode + + +\subsection quick_start_initialization_other_config Other configuration options + +There are additional configuration options available through preprocessor macros that you can define +before including VMA header and through parameters passed in #VmaAllocatorCreateInfo. +They include a possibility to use your own callbacks for host memory allocations (`VkAllocationCallbacks`), +callbacks for device memory allocations (instead of `vkAllocateMemory`, `vkFreeMemory`), +or your custom `VMA_ASSERT` macro, among others. +For more information, see: @ref configuration. + + +\section quick_start_resource_allocation Resource allocation + +When you want to create a buffer or image: + +-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure. +-# Fill VmaAllocationCreateInfo structure. +-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory + already allocated and bound to it, plus #VmaAllocation objects that represents its underlying memory. + +\code +VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufferInfo.size = 65536; +bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.usage = VMA_MEMORY_USAGE_AUTO; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +Don't forget to destroy your buffer and allocation objects when no longer needed: + +\code +vmaDestroyBuffer(allocator, buffer, allocation); +\endcode + +If you need to map the buffer, you must set flag +#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT +in VmaAllocationCreateInfo::flags. +There are many additional parameters that can control the choice of memory type to be used for the allocation +and other features. +For more information, see documentation chapters: @ref choosing_memory_type, @ref memory_mapping. + + +\page choosing_memory_type Choosing memory type + +Physical devices in Vulkan support various combinations of memory heaps and +types. Help with choosing correct and optimal memory type for your specific +resource is one of the key features of this library. You can use it by filling +appropriate members of VmaAllocationCreateInfo structure, as described below. +You can also combine multiple methods. + +-# If you just want to find memory type index that meets your requirements, you + can use function: vmaFindMemoryTypeIndexForBufferInfo(), + vmaFindMemoryTypeIndexForImageInfo(), vmaFindMemoryTypeIndex(). +-# If you want to allocate a region of device memory without association with any + specific image or buffer, you can use function vmaAllocateMemory(). Usage of + this function is not recommended and usually not needed. + vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once, + which may be useful for sparse binding. +-# If you already have a buffer or an image created, you want to allocate memory + for it and then you will bind it yourself, you can use function + vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(). + For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory() + or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2(). +-# If you want to create a buffer or an image, allocate memory for it, and bind + them together, all in one call, you can use function vmaCreateBuffer(), + vmaCreateImage(). + This is the easiest and recommended way to use this library! + +When using 3. or 4., the library internally queries Vulkan for memory types +supported for that buffer or image (function `vkGetBufferMemoryRequirements()`) +and uses only one of these types. + +If no memory type can be found that meets all the requirements, these functions +return `VK_ERROR_FEATURE_NOT_PRESENT`. + +You can leave VmaAllocationCreateInfo structure completely filled with zeros. +It means no requirements are specified for memory type. +It is valid, although not very useful. + +\section choosing_memory_type_usage Usage + +The easiest way to specify memory requirements is to fill member +VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage. +It defines high level, common usage types. +Since version 3 of the library, it is recommended to use #VMA_MEMORY_USAGE_AUTO to let it select best memory type for your resource automatically. + +For example, if you want to create a uniform buffer that will be filled using +transfer only once or infrequently and then used for rendering every frame as a uniform buffer, you can +do it using following code. The buffer will most likely end up in a memory type with +`VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT` to be fast to access by the GPU device. + +\code +VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufferInfo.size = 65536; +bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.usage = VMA_MEMORY_USAGE_AUTO; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +If you have a preference for putting the resource in GPU (device) memory or CPU (host) memory +on systems with discrete graphics card that have the memories separate, you can use +#VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST. + +When using `VMA_MEMORY_USAGE_AUTO*` while you want to map the allocated memory, +you also need to specify one of the host access flags: +#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. +This will help the library decide about preferred memory type to ensure it has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` +so you can map it. + +For example, a staging buffer that will be filled via mapped pointer and then +used as a source of transfer to the buffer described previously can be created like this. +It will likely end up in a memory type that is `HOST_VISIBLE` and `HOST_COHERENT` +but not `HOST_CACHED` (meaning uncached, write-combined) and not `DEVICE_LOCAL` (meaning system RAM). + +\code +VkBufferCreateInfo stagingBufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +stagingBufferInfo.size = 65536; +stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + +VmaAllocationCreateInfo stagingAllocInfo = {}; +stagingAllocInfo.usage = VMA_MEMORY_USAGE_AUTO; +stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + +VkBuffer stagingBuffer; +VmaAllocation stagingAllocation; +vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr); +\endcode + +For more examples of creating different kinds of resources, see chapter \ref usage_patterns. +See also: @ref memory_mapping. + +Usage values `VMA_MEMORY_USAGE_AUTO*` are legal to use only when the library knows +about the resource being created by having `VkBufferCreateInfo` / `VkImageCreateInfo` passed, +so they work with functions like: vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo() etc. +If you allocate raw memory using function vmaAllocateMemory(), you have to use other means of selecting +memory type, as described below. + +\note +Old usage values (`VMA_MEMORY_USAGE_GPU_ONLY`, `VMA_MEMORY_USAGE_CPU_ONLY`, +`VMA_MEMORY_USAGE_CPU_TO_GPU`, `VMA_MEMORY_USAGE_GPU_TO_CPU`, `VMA_MEMORY_USAGE_CPU_COPY`) +are still available and work same way as in previous versions of the library +for backward compatibility, but they are deprecated. + +\section choosing_memory_type_required_preferred_flags Required and preferred flags + +You can specify more detailed requirements by filling members +VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags +with a combination of bits from enum `VkMemoryPropertyFlags`. For example, +if you want to create a buffer that will be persistently mapped on host (so it +must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`, +use following code: + +\code +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; +allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; +allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +A memory type is chosen that has all the required flags and as many preferred +flags set as possible. + +Value passed in VmaAllocationCreateInfo::usage is internally converted to a set of required and preferred flags, +plus some extra "magic" (heuristics). + +\section choosing_memory_type_explicit_memory_types Explicit memory types + +If you inspected memory types available on the physical device and you have +a preference for memory types that you want to use, you can fill member +VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set +means that a memory type with that index is allowed to be used for the +allocation. Special value 0, just like `UINT32_MAX`, means there are no +restrictions to memory type index. + +Please note that this member is NOT just a memory type index. +Still you can use it to choose just one, specific memory type. +For example, if you already determined that your buffer should be created in +memory type 2, use following code: + +\code +uint32_t memoryTypeIndex = 2; + +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.memoryTypeBits = 1U << memoryTypeIndex; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr); +\endcode + +You can also use this parameter to exclude some memory types. +If you inspect memory heaps and types available on the current physical device and +you determine that for some reason you don't want to use a specific memory type for the allocation, +you can enable automatic memory type selection but exclude certain memory type or types +by setting all bits of `memoryTypeBits` to 1 except the ones you choose. + +\code +// ... +uint32_t excludedMemoryTypeIndex = 2; +VmaAllocationCreateInfo allocInfo = {}; +allocInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocInfo.memoryTypeBits = ~(1U << excludedMemoryTypeIndex); +// ... +\endcode + + +\section choosing_memory_type_custom_memory_pools Custom memory pools + +If you allocate from custom memory pool, all the ways of specifying memory +requirements described above are not applicable and the aforementioned members +of VmaAllocationCreateInfo structure are ignored. Memory type is selected +explicitly when creating the pool and then used to make all the allocations from +that pool. For further details, see \ref custom_memory_pools. + +\section choosing_memory_type_dedicated_allocations Dedicated allocations + +Memory for allocations is reserved out of larger block of `VkDeviceMemory` +allocated from Vulkan internally. That is the main feature of this whole library. +You can still request a separate memory block to be created for an allocation, +just like you would do in a trivial solution without using any allocator. +In that case, a buffer or image is always bound to that memory at offset 0. +This is called a "dedicated allocation". +You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +The library can also internally decide to use dedicated allocation in some cases, e.g.: + +- When the size of the allocation is large. +- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled + and it reports that dedicated allocation is required or recommended for the resource. +- When allocation of next big memory block fails due to not enough device memory, + but allocation with the exact requested size succeeds. + + +\page memory_mapping Memory mapping + +To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`, +to be able to read from it or write to it in CPU code. +Mapping is possible only of memory allocated from a memory type that has +`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag. +Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose. +You can use them directly with memory allocated by this library, +but it is not recommended because of following issue: +Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed. +This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. +It is also not thread-safe. +Because of this, Vulkan Memory Allocator provides following facilities: + +\note If you want to be able to map an allocation, you need to specify one of the flags +#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT +in VmaAllocationCreateInfo::flags. These flags are required for an allocation to be mappable +when using #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` enum values. +For other usage values they are ignored and every such allocation made in `HOST_VISIBLE` memory type is mappable, +but these flags can still be used for consistency. + +\section memory_mapping_copy_functions Copy functions + +The easiest way to copy data from a host pointer to an allocation is to use convenience function vmaCopyMemoryToAllocation(). +It automatically maps the Vulkan memory temporarily (if not already mapped), performs `memcpy`, +and calls `vkFlushMappedMemoryRanges` (if required - if memory type is not `HOST_COHERENT`). + +It is also the safest one, because using `memcpy` avoids a risk of accidentally introducing memory reads +(e.g. by doing `pMappedVectors[i] += v`), which may be very slow on memory types that are not `HOST_CACHED`. + +\code +struct ConstantBuffer +{ + ... +}; +ConstantBuffer constantBufferData = ... + +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = sizeof(ConstantBuffer); +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + +VkBuffer buf; +VmaAllocation alloc; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr); + +vmaCopyMemoryToAllocation(allocator, &constantBufferData, alloc, 0, sizeof(ConstantBuffer)); +\endcode + +Copy in the other direction - from an allocation to a host pointer can be performed the same way using function vmaCopyAllocationToMemory(). + +\section memory_mapping_mapping_functions Mapping functions + +The library provides following functions for mapping of a specific allocation: vmaMapMemory(), vmaUnmapMemory(). +They are safer and more convenient to use than standard Vulkan functions. +You can map an allocation multiple times simultaneously - mapping is reference-counted internally. +You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block. +The way it is implemented is that the library always maps entire memory block, not just region of the allocation. +For further details, see description of vmaMapMemory() function. +Example: + +\code +// Having these objects initialized: +struct ConstantBuffer +{ + ... +}; +ConstantBuffer constantBufferData = ... + +VmaAllocator allocator = ... +VkBuffer constantBuffer = ... +VmaAllocation constantBufferAllocation = ... + +// You can map and fill your buffer using following code: + +void* mappedData; +vmaMapMemory(allocator, constantBufferAllocation, &mappedData); +memcpy(mappedData, &constantBufferData, sizeof(constantBufferData)); +vmaUnmapMemory(allocator, constantBufferAllocation); +\endcode + +When mapping, you may see a warning from Vulkan validation layer similar to this one: + +Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used. + +It happens because the library maps entire `VkDeviceMemory` block, where different +types of images and buffers may end up together, especially on GPUs with unified memory like Intel. +You can safely ignore it if you are sure you access only memory of the intended +object that you wanted to map. + + +\section memory_mapping_persistently_mapped_memory Persistently mapped memory + +Keeping your memory persistently mapped is generally OK in Vulkan. +You don't need to unmap it before using its data on the GPU. +The library provides a special feature designed for that: +Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in +VmaAllocationCreateInfo::flags stay mapped all the time, +so you can just access CPU pointer to it any time +without a need to call any "map" or "unmap" function. +Example: + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = sizeof(ConstantBuffer); +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); + +// Buffer is already mapped. You can access its memory. +memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData)); +\endcode + +\note #VMA_ALLOCATION_CREATE_MAPPED_BIT by itself doesn't guarantee that the allocation will end up +in a mappable memory type. +For this, you need to also specify #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or +#VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. +#VMA_ALLOCATION_CREATE_MAPPED_BIT only guarantees that if the memory is `HOST_VISIBLE`, the allocation will be mapped on creation. +For an example of how to make use of this fact, see section \ref usage_patterns_advanced_data_uploading. + +\section memory_mapping_cache_control Cache flush and invalidate + +Memory in Vulkan doesn't need to be unmapped before using it on GPU, +but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set, +you need to manually **invalidate** cache before reading of mapped pointer +and **flush** cache after writing to mapped pointer. +Map/unmap operations don't do that automatically. +Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`, +`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient +functions that refer to given allocation object: vmaFlushAllocation(), +vmaInvalidateAllocation(), +or multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations(). + +Regions of memory specified for flush/invalidate must be aligned to +`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library. +In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations +within blocks are aligned to this value, so their offsets are always multiply of +`nonCoherentAtomSize` and two different allocations never share same "line" of this size. + +Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA) +currently provide `HOST_COHERENT` flag on all memory types that are +`HOST_VISIBLE`, so on PC you may not need to bother. + + +\page staying_within_budget Staying within budget + +When developing a graphics-intensive game or program, it is important to avoid allocating +more GPU memory than it is physically available. When the memory is over-committed, +various bad things can happen, depending on the specific GPU, graphics driver, and +operating system: + +- It may just work without any problems. +- The application may slow down because some memory blocks are moved to system RAM + and the GPU has to access them through PCI Express bus. +- A new allocation may take very long time to complete, even few seconds, and possibly + freeze entire system. +- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST` + returned somewhere later. + +\section staying_within_budget_querying_for_budget Querying for budget + +To query for current memory usage and available budget, use function vmaGetHeapBudgets(). +Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap. + +Please note that this function returns different information and works faster than +vmaCalculateStatistics(). vmaGetHeapBudgets() can be called every frame or even before every +allocation, while vmaCalculateStatistics() is intended to be used rarely, +only to obtain statistical information, e.g. for debugging purposes. + +It is recommended to use VK_EXT_memory_budget device extension to obtain information +about the budget from Vulkan device. VMA is able to use this extension automatically. +When not enabled, the allocator behaves same way, but then it estimates current usage +and available budget based on its internal information and Vulkan memory heap sizes, +which may be less precise. In order to use this extension: + +1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2 + required by it are available and enable them. Please note that the first is a device + extension and the second is instance extension! +2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object. +3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from + Vulkan inside of it to avoid overhead of querying it with every allocation. + +\section staying_within_budget_controlling_memory_usage Controlling memory usage + +There are many ways in which you can try to stay within the budget. + +First, when making new allocation requires allocating a new memory block, the library +tries not to exceed the budget automatically. If a block with default recommended size +(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even +dedicated memory for just this resource. + +If the size of the requested resource plus current memory usage is more than the +budget, by default the library still tries to create it, leaving it to the Vulkan +implementation whether the allocation succeeds or fails. You can change this behavior +by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is +not made if it would exceed the budget or if the budget is already exceeded. +VMA then tries to make the allocation from the next eligible Vulkan memory type. +If all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag +when creating resources that are not essential for the application (e.g. the texture +of a specific object) and not to pass it when creating critically important resources +(e.g. render targets). + +On AMD graphics cards there is a custom vendor extension available: VK_AMD_memory_overallocation_behavior +that allows to control the behavior of the Vulkan implementation in out-of-memory cases - +whether it should fail with an error code or still allow the allocation. +Usage of this extension involves only passing extra structure on Vulkan device creation, +so it is out of scope of this library. + +Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure +a new allocation is created only when it fits inside one of the existing memory blocks. +If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`. +This also ensures that the function call is very fast because it never goes to Vulkan +to obtain a new block. + +\note Creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount +set to more than 0 will currently try to allocate memory blocks without checking whether they +fit within budget. + + +\page resource_aliasing Resource aliasing (overlap) + +New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory +management, give an opportunity to alias (overlap) multiple resources in the +same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL). +It can be useful to save video memory, but it must be used with caution. + +For example, if you know the flow of your whole render frame in advance, you +are going to use some intermediate textures or buffers only during a small range of render passes, +and you know these ranges don't overlap in time, you can bind these resources to +the same place in memory, even if they have completely different parameters (width, height, format etc.). + +![Resource aliasing (overlap)](../gfx/Aliasing.png) + +Such scenario is possible using VMA, but you need to create your images manually. +Then you need to calculate parameters of an allocation to be made using formula: + +- allocation size = max(size of each image) +- allocation alignment = max(alignment of each image) +- allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image) + +Following example shows two different images bound to the same place in memory, +allocated to fit largest of them. + +\code +// A 512x512 texture to be sampled. +VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +img1CreateInfo.imageType = VK_IMAGE_TYPE_2D; +img1CreateInfo.extent.width = 512; +img1CreateInfo.extent.height = 512; +img1CreateInfo.extent.depth = 1; +img1CreateInfo.mipLevels = 10; +img1CreateInfo.arrayLayers = 1; +img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB; +img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; +img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +// A full screen texture to be used as color attachment. +VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +img2CreateInfo.imageType = VK_IMAGE_TYPE_2D; +img2CreateInfo.extent.width = 1920; +img2CreateInfo.extent.height = 1080; +img2CreateInfo.extent.depth = 1; +img2CreateInfo.mipLevels = 1; +img2CreateInfo.arrayLayers = 1; +img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; +img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; +img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +VkImage img1; +res = vkCreateImage(device, &img1CreateInfo, nullptr, &img1); +VkImage img2; +res = vkCreateImage(device, &img2CreateInfo, nullptr, &img2); + +VkMemoryRequirements img1MemReq; +vkGetImageMemoryRequirements(device, img1, &img1MemReq); +VkMemoryRequirements img2MemReq; +vkGetImageMemoryRequirements(device, img2, &img2MemReq); + +VkMemoryRequirements finalMemReq = {}; +finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size); +finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment); +finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits; +// Validate if(finalMemReq.memoryTypeBits != 0) + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + +VmaAllocation alloc; +res = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr); + +res = vmaBindImageMemory(allocator, alloc, img1); +res = vmaBindImageMemory(allocator, alloc, img2); + +// You can use img1, img2 here, but not at the same time! + +vmaFreeMemory(allocator, alloc); +vkDestroyImage(allocator, img2, nullptr); +vkDestroyImage(allocator, img1, nullptr); +\endcode + +VMA also provides convenience functions that create a buffer or image and bind it to memory +represented by an existing #VmaAllocation: +vmaCreateAliasingBuffer(), vmaCreateAliasingBuffer2(), +vmaCreateAliasingImage(), vmaCreateAliasingImage2(). +Versions with "2" offer additional parameter `allocationLocalOffset`. + +Remember that using resources that alias in memory requires proper synchronization. +You need to issue a memory barrier to make sure commands that use `img1` and `img2` +don't overlap on GPU timeline. +You also need to treat a resource after aliasing as uninitialized - containing garbage data. +For example, if you use `img1` and then want to use `img2`, you need to issue +an image memory barrier for `img2` with `oldLayout` = `VK_IMAGE_LAYOUT_UNDEFINED`. + +Additional considerations: + +- Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases. +See chapter 11.8. "Memory Aliasing" of Vulkan specification or `VK_IMAGE_CREATE_ALIAS_BIT` flag. +- You can create more complex layout where different images and buffers are bound +at different offsets inside one large allocation. For example, one can imagine +a big texture used in some render passes, aliasing with a set of many small buffers +used between in some further passes. To bind a resource at non-zero offset in an allocation, +use vmaBindBufferMemory2() / vmaBindImageMemory2(). +- Before allocating memory for the resources you want to alias, check `memoryTypeBits` +returned in memory requirements of each resource to make sure the bits overlap. +Some GPUs may expose multiple memory types suitable e.g. only for buffers or +images with `COLOR_ATTACHMENT` usage, so the sets of memory types supported by your +resources may be disjoint. Aliasing them is not possible in that case. + + +\page custom_memory_pools Custom memory pools + +A memory pool contains a number of `VkDeviceMemory` blocks. +The library automatically creates and manages default pool for each memory type available on the device. +Default memory pool automatically grows in size. +Size of allocated blocks is also variable and managed automatically. +You are using default pools whenever you leave VmaAllocationCreateInfo::pool = null. + +You can create custom pool and allocate memory out of it. +It can be useful if you want to: + +- Keep certain kind of allocations separate from others. +- Enforce particular, fixed size of Vulkan memory blocks. +- Limit maximum amount of Vulkan memory allocated for that pool. +- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool. +- Use extra parameters for a set of your allocations that are available in #VmaPoolCreateInfo but not in + #VmaAllocationCreateInfo - e.g., custom minimum alignment, custom `pNext` chain. +- Perform defragmentation on a specific subset of your allocations. + +To use custom memory pools: + +-# Fill VmaPoolCreateInfo structure. +-# Call vmaCreatePool() to obtain #VmaPool handle. +-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle. + You don't need to specify any other parameters of this structure, like `usage`. + +Example: + +\code +// Find memoryTypeIndex for the pool. +VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +sampleBufCreateInfo.size = 0x10000; // Doesn't matter. +sampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo sampleAllocCreateInfo = {}; +sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + +uint32_t memTypeIndex; +VkResult res = vmaFindMemoryTypeIndexForBufferInfo(allocator, + &sampleBufCreateInfo, &sampleAllocCreateInfo, &memTypeIndex); +// Check res... + +// Create a pool that can have at most 2 blocks, 128 MiB each. +VmaPoolCreateInfo poolCreateInfo = {}; +poolCreateInfo.memoryTypeIndex = memTypeIndex; +poolCreateInfo.blockSize = 128ULL * 1024 * 1024; +poolCreateInfo.maxBlockCount = 2; + +VmaPool pool; +res = vmaCreatePool(allocator, &poolCreateInfo, &pool); +// Check res... + +// Allocate a buffer out of it. +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = 1024; +bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.pool = pool; + +VkBuffer buf; +VmaAllocation alloc; +res = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr); +// Check res... +\endcode + +You have to free all allocations made from this pool before destroying it. + +\code +vmaDestroyBuffer(allocator, buf, alloc); +vmaDestroyPool(allocator, pool); +\endcode + +New versions of this library support creating dedicated allocations in custom pools. +It is supported only when VmaPoolCreateInfo::blockSize = 0. +To use this feature, set VmaAllocationCreateInfo::pool to the pointer to your custom pool and +VmaAllocationCreateInfo::flags to #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. + + +\section custom_memory_pools_MemTypeIndex Choosing memory type index + +When creating a pool, you must explicitly specify memory type index. +To find the one suitable for your buffers or images, you can use helper functions +vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo(). +You need to provide structures with example parameters of buffers or images +that you are going to create in that pool. + +\code +VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +exampleBufCreateInfo.size = 1024; // Doesn't matter +exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + +uint32_t memTypeIndex; +vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex); + +VmaPoolCreateInfo poolCreateInfo = {}; +poolCreateInfo.memoryTypeIndex = memTypeIndex; +// ... +\endcode + +When creating buffers/images allocated in that pool, provide following parameters: + +- `VkBufferCreateInfo`: Prefer to pass same parameters as above. + Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior. + Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers + or the other way around. +- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member. + Other members are ignored anyway. + + +\section custom_memory_pools_when_not_use When not to use custom pools + +Custom pools are commonly overused by VMA users. +While it may feel natural to keep some logical groups of resources separate in memory, +in most cases it does more harm than good. +Using custom pool shouldn't be your first choice. +Instead, please make all allocations from default pools first and only use custom pools +if you can prove and measure that it is beneficial in some way, +e.g. it results in lower memory usage, better performance, etc. + +Using custom pools has disadvantages: + +- Each pool has its own collection of `VkDeviceMemory` blocks. + Some of them may be partially or even completely empty. + Spreading allocations across multiple pools increases the amount of wasted (allocated but unbound) memory. +- You must manually choose specific memory type to be used by a custom pool (set as VmaPoolCreateInfo::memoryTypeIndex). + When using default pools, best memory type for each of your allocations can be selected automatically + using a carefully design algorithm that works across all kinds of GPUs. +- If an allocation from a custom pool at specific memory type fails, entire allocation operation returns failure. + When using default pools, VMA tries another compatible memory type. +- If you set VmaPoolCreateInfo::blockSize != 0, each memory block has the same size, + while default pools start from small blocks and only allocate next blocks larger and larger + up to the preferred block size. + +Many of the common concerns can be addressed in a different way than using custom pools: + +- If you want to keep your allocations of certain size (small versus large) or certain lifetime (transient versus long lived) + separate, you likely don't need to. + VMA uses a high quality allocation algorithm that manages memory well in various cases. + Please measure and check if using custom pools provides a benefit. +- If you want to keep your images and buffers separate, you don't need to. + VMA respects `bufferImageGranularity` limit automatically. +- If you want to keep your mapped and not mapped allocations separate, you don't need to. + VMA respects `nonCoherentAtomSize` limit automatically. + It also maps only those `VkDeviceMemory` blocks that need to map any allocation. + It even tries to keep mappable and non-mappable allocations in separate blocks to minimize the amount of mapped memory. +- If you want to choose a custom size for the default memory block, you can set it globally instead + using VmaAllocatorCreateInfo::preferredLargeHeapBlockSize. +- If you want to select specific memory type for your allocation, + you can set VmaAllocationCreateInfo::memoryTypeBits to `(1U << myMemoryTypeIndex)` instead. +- If you need to create a buffer with certain minimum alignment, you can still do it + using default pools with dedicated function vmaCreateBufferWithAlignment(). + + +\section linear_algorithm Linear allocation algorithm + +Each Vulkan memory block managed by this library has accompanying metadata that +keeps track of used and unused regions. By default, the metadata structure and +algorithm tries to find best place for new allocations among free regions to +optimize memory usage. This way you can allocate and free objects in any order. + +![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png) + +Sometimes there is a need to use simpler, linear allocation algorithm. You can +create custom pool that uses such algorithm by adding flag +#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating +#VmaPool object. Then an alternative metadata management is used. It always +creates new allocations after last one and doesn't reuse free regions after +allocations freed in the middle. It results in better allocation performance and +less memory consumed by metadata. + +![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png) + +With this one flag, you can create a custom pool that can be used in many ways: +free-at-once, stack, double stack, and ring buffer. See below for details. +You don't need to specify explicitly which of these options you are going to use - it is detected automatically. + +\subsection linear_algorithm_free_at_once Free-at-once + +In a pool that uses linear algorithm, you still need to free all the allocations +individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free +them in any order. New allocations are always made after last one - free space +in the middle is not reused. However, when you release all the allocation and +the pool becomes empty, allocation starts from the beginning again. This way you +can use linear algorithm to speed up creation of allocations that you are going +to release all at once. + +![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png) + +This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount +value that allows multiple memory blocks. + +\subsection linear_algorithm_stack Stack + +When you free an allocation that was created last, its space can be reused. +Thanks to this, if you always release allocations in the order opposite to their +creation (LIFO - Last In First Out), you can achieve behavior of a stack. + +![Stack](../gfx/Linear_allocator_4_stack.png) + +This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount +value that allows multiple memory blocks. + +\subsection linear_algorithm_double_stack Double stack + +The space reserved by a custom pool with linear algorithm may be used by two +stacks: + +- First, default one, growing up from offset 0. +- Second, "upper" one, growing down from the end towards lower offsets. + +To make allocation from the upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT +to VmaAllocationCreateInfo::flags. + +![Double stack](../gfx/Linear_allocator_7_double_stack.png) + +Double stack is available only in pools with one memory block - +VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined. + +When the two stacks' ends meet so there is not enough space between them for a +new allocation, such allocation fails with usual +`VK_ERROR_OUT_OF_DEVICE_MEMORY` error. + +\subsection linear_algorithm_ring_buffer Ring buffer + +When you free some allocations from the beginning and there is not enough free space +for a new one at the end of a pool, allocator's "cursor" wraps around to the +beginning and starts allocation there. Thanks to this, if you always release +allocations in the same order as you created them (FIFO - First In First Out), +you can achieve behavior of a ring buffer / queue. + +![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png) + +Ring buffer is available only in pools with one memory block - +VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined. + +\note \ref defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT. + + +\page defragmentation Defragmentation + +Interleaved allocations and deallocations of many objects of varying size can +cause fragmentation over time, which can lead to a situation where the library is unable +to find a continuous range of free memory for a new allocation despite there is +enough free space, just scattered across many small free ranges between existing +allocations. + +To mitigate this problem, you can use defragmentation feature. +It doesn't happen automatically though and needs your cooperation, +because VMA is a low level library that only allocates memory. +It cannot recreate buffers and images in a new place as it doesn't remember the contents of `VkBufferCreateInfo` / `VkImageCreateInfo` structures. +It cannot copy their contents as it doesn't record any commands to a command buffer. + +Example: + +\code +VmaDefragmentationInfo defragInfo = {}; +defragInfo.pool = myPool; +defragInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT; + +VmaDefragmentationContext defragCtx; +VkResult res = vmaBeginDefragmentation(allocator, &defragInfo, &defragCtx); +// Check res... + +for(;;) +{ + VmaDefragmentationPassMoveInfo pass; + res = vmaBeginDefragmentationPass(allocator, defragCtx, &pass); + if(res == VK_SUCCESS) + break; + else if(res != VK_INCOMPLETE) + // Handle error... + + for(uint32_t i = 0; i < pass.moveCount; ++i) + { + // Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents. + VmaAllocationInfo allocInfo; + vmaGetAllocationInfo(allocator, pass.pMoves[i].srcAllocation, &allocInfo); + MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData; + + // Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset. + VkImageCreateInfo imgCreateInfo = ... + VkImage newImg; + res = vkCreateImage(device, &imgCreateInfo, nullptr, &newImg); + // Check res... + res = vmaBindImageMemory(allocator, pass.pMoves[i].dstTmpAllocation, newImg); + // Check res... + + // Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place. + vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...); + } + + // Make sure the copy commands finished executing. + vkWaitForFences(...); + + // Destroy old buffers/images bound with pass.pMoves[i].srcAllocation. + for(uint32_t i = 0; i < pass.moveCount; ++i) + { + // ... + vkDestroyImage(device, resData->img, nullptr); + } + + // Update appropriate descriptors to point to the new places... + + res = vmaEndDefragmentationPass(allocator, defragCtx, &pass); + if(res == VK_SUCCESS) + break; + else if(res != VK_INCOMPLETE) + // Handle error... +} + +vmaEndDefragmentation(allocator, defragCtx, nullptr); +\endcode + +Although functions like vmaCreateBuffer(), vmaCreateImage(), vmaDestroyBuffer(), vmaDestroyImage() +create/destroy an allocation and a buffer/image at once, these are just a shortcut for +creating the resource, allocating memory, and binding them together. +Defragmentation works on memory allocations only. You must handle the rest manually. +Defragmentation is an iterative process that should repreat "passes" as long as related functions +return `VK_INCOMPLETE` not `VK_SUCCESS`. +In each pass: + +1. vmaBeginDefragmentationPass() function call: + - Calculates and returns the list of allocations to be moved in this pass. + Note this can be a time-consuming process. + - Reserves destination memory for them by creating temporary destination allocations + that you can query for their `VkDeviceMemory` + offset using vmaGetAllocationInfo(). +2. Inside the pass, **you should**: + - Inspect the returned list of allocations to be moved. + - Create new buffers/images and bind them at the returned destination temporary allocations. + - Copy data from source to destination resources if necessary. + - Destroy the source buffers/images, but NOT their allocations. +3. vmaEndDefragmentationPass() function call: + - Frees the source memory reserved for the allocations that are moved. + - Modifies source #VmaAllocation objects that are moved to point to the destination reserved memory. + - Frees `VkDeviceMemory` blocks that became empty. + +Unlike in previous iterations of the defragmentation API, there is no list of "movable" allocations passed as a parameter. +Defragmentation algorithm tries to move all suitable allocations. +You can, however, refuse to move some of them inside a defragmentation pass, by setting +`pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. +This is not recommended and may result in suboptimal packing of the allocations after defragmentation. +If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool. + +Inside a pass, for each allocation that should be moved: + +- You should copy its data from the source to the destination place by calling e.g. `vkCmdCopyBuffer()`, `vkCmdCopyImage()`. + - You need to make sure these commands finished executing before destroying the source buffers/images and before calling vmaEndDefragmentationPass(). +- If a resource doesn't contain any meaningful data, e.g. it is a transient color attachment image to be cleared, + filled, and used temporarily in each rendering frame, you can just recreate this image + without copying its data. +- If the resource is in `HOST_VISIBLE` and `HOST_CACHED` memory, you can copy its data on the CPU + using `memcpy()`. +- If you cannot move the allocation, you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE. + This will cancel the move. + - vmaEndDefragmentationPass() will then free the destination memory + not the source memory of the allocation, leaving it unchanged. +- If you decide the allocation is unimportant and can be destroyed instead of moved (e.g. it wasn't used for long time), + you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY. + - vmaEndDefragmentationPass() will then free both source and destination memory, and will destroy the source #VmaAllocation object. + +You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool +(like in the example above) or all the default pools by setting this member to null. + +Defragmentation is always performed in each pool separately. +Allocations are never moved between different Vulkan memory types. +The size of the destination memory reserved for a moved allocation is the same as the original one. +Alignment of an allocation as it was determined using `vkGetBufferMemoryRequirements()` etc. is also respected after defragmentation. +Buffers/images should be recreated with the same `VkBufferCreateInfo` / `VkImageCreateInfo` parameters as the original ones. + +You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved +in each pass, e.g. to call it in sync with render frames and not to experience too big hitches. +See members: VmaDefragmentationInfo::maxBytesPerPass, VmaDefragmentationInfo::maxAllocationsPerPass. + +It is also safe to perform the defragmentation asynchronously to render frames and other Vulkan and VMA +usage, possibly from multiple threads, with the exception that allocations +returned in VmaDefragmentationPassMoveInfo::pMoves shouldn't be destroyed until the defragmentation pass is ended. + +Mapping is preserved on allocations that are moved during defragmentation. +Whether through #VMA_ALLOCATION_CREATE_MAPPED_BIT or vmaMapMemory(), the allocations +are mapped at their new place. Of course, pointer to the mapped data changes, so it needs to be queried +using VmaAllocationInfo::pMappedData. + +\note Defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT. + + +\page statistics Statistics + +This library contains several functions that return information about its internal state, +especially the amount of memory allocated from Vulkan. + +\section statistics_numeric_statistics Numeric statistics + +If you need to obtain basic statistics about memory usage per heap, together with current budget, +you can call function vmaGetHeapBudgets() and inspect structure #VmaBudget. +This is useful to keep track of memory usage and stay within budget +(see also \ref staying_within_budget). +Example: + +\code +uint32_t heapIndex = ... + +VmaBudget budgets[VK_MAX_MEMORY_HEAPS]; +vmaGetHeapBudgets(allocator, budgets); + +printf("My heap currently has %u allocations taking %llu B,\n", + budgets[heapIndex].statistics.allocationCount, + budgets[heapIndex].statistics.allocationBytes); +printf("allocated out of %u Vulkan device memory blocks taking %llu B,\n", + budgets[heapIndex].statistics.blockCount, + budgets[heapIndex].statistics.blockBytes); +printf("Vulkan reports total usage %llu B with budget %llu B.\n", + budgets[heapIndex].usage, + budgets[heapIndex].budget); +\endcode + +You can query for more detailed statistics per memory heap, type, and totals, +including minimum and maximum allocation size and unused range size, +by calling function vmaCalculateStatistics() and inspecting structure #VmaTotalStatistics. +This function is slower though, as it has to traverse all the internal data structures, +so it should be used only for debugging purposes. + +You can query for statistics of a custom pool using function vmaGetPoolStatistics() +or vmaCalculatePoolStatistics(). + +You can query for information about a specific allocation using function vmaGetAllocationInfo(). +It fill structure #VmaAllocationInfo. + +\section statistics_json_dump JSON dump + +You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString(). +The result is guaranteed to be correct JSON. +It uses ANSI encoding. +Any strings provided by user (see [Allocation names](@ref allocation_names)) +are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding, +this JSON string can be treated as using this encoding. +It must be freed using function vmaFreeStatsString(). + +The format of this JSON string is not part of official documentation of the library, +but it will not change in backward-incompatible way without increasing library major version number +and appropriate mention in changelog. + +The JSON string contains all the data that can be obtained using vmaCalculateStatistics(). +It can also contain detailed map of allocated memory blocks and their regions - +free and occupied by allocations. +This allows e.g. to visualize the memory or assess fragmentation. + + +\page allocation_annotation Allocation names and user data + +\section allocation_user_data Allocation user data + +You can annotate allocations with your own information, e.g. for debugging purposes. +To do that, fill VmaAllocationCreateInfo::pUserData field when creating +an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer, +some handle, index, key, ordinal number or any other value that would associate +the allocation with your custom metadata. +It is useful to identify appropriate data structures in your engine given #VmaAllocation, +e.g. when doing \ref defragmentation. + +\code +VkBufferCreateInfo bufCreateInfo = ... + +MyBufferMetadata* pMetadata = CreateBufferMetadata(); + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.pUserData = pMetadata; + +VkBuffer buffer; +VmaAllocation allocation; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buffer, &allocation, nullptr); +\endcode + +The pointer may be later retrieved as VmaAllocationInfo::pUserData: + +\code +VmaAllocationInfo allocInfo; +vmaGetAllocationInfo(allocator, allocation, &allocInfo); +MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData; +\endcode + +It can also be changed using function vmaSetAllocationUserData(). + +Values of (non-zero) allocations' `pUserData` are printed in JSON report created by +vmaBuildStatsString() in hexadecimal form. + +\section allocation_names Allocation names + +An allocation can also carry a null-terminated string, giving a name to the allocation. +To set it, call vmaSetAllocationName(). +The library creates internal copy of the string, so the pointer you pass doesn't need +to be valid for whole lifetime of the allocation. You can free it after the call. + +\code +std::string imageName = "Texture: "; +imageName += fileName; +vmaSetAllocationName(allocator, allocation, imageName.c_str()); +\endcode + +The string can be later retrieved by inspecting VmaAllocationInfo::pName. +It is also printed in JSON report created by vmaBuildStatsString(). + +\note Setting string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. +You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library. + + +\page virtual_allocator Virtual allocator + +As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator". +It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block". +You can use it to allocate your own memory or other objects, even completely unrelated to Vulkan. +A common use case is sub-allocation of pieces of one large GPU buffer. + +\section virtual_allocator_creating_virtual_block Creating virtual block + +To use this functionality, there is no main "allocator" object. +You don't need to have #VmaAllocator object created. +All you need to do is to create a separate #VmaVirtualBlock object for each block of memory you want to be managed by the allocator: + +-# Fill in #VmaVirtualBlockCreateInfo structure. +-# Call vmaCreateVirtualBlock(). Get new #VmaVirtualBlock object. + +Example: + +\code +VmaVirtualBlockCreateInfo blockCreateInfo = {}; +blockCreateInfo.size = 1048576; // 1 MB + +VmaVirtualBlock block; +VkResult res = vmaCreateVirtualBlock(&blockCreateInfo, &block); +\endcode + +\section virtual_allocator_making_virtual_allocations Making virtual allocations + +#VmaVirtualBlock object contains internal data structure that keeps track of free and occupied regions +using the same code as the main Vulkan memory allocator. +Similarly to #VmaAllocation for standard GPU allocations, there is #VmaVirtualAllocation type +that represents an opaque handle to an allocation within the virtual block. + +In order to make such allocation: + +-# Fill in #VmaVirtualAllocationCreateInfo structure. +-# Call vmaVirtualAllocate(). Get new #VmaVirtualAllocation object that represents the allocation. + You can also receive `VkDeviceSize offset` that was assigned to the allocation. + +Example: + +\code +VmaVirtualAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.size = 4096; // 4 KB + +VmaVirtualAllocation alloc; +VkDeviceSize offset; +res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, &offset); +if(res == VK_SUCCESS) +{ + // Use the 4 KB of your memory starting at offset. +} +else +{ + // Allocation failed - no space for it could be found. Handle this error! +} +\endcode + +\section virtual_allocator_deallocation Deallocation + +When no longer needed, an allocation can be freed by calling vmaVirtualFree(). +You can only pass to this function an allocation that was previously returned by vmaVirtualAllocate() +called for the same #VmaVirtualBlock. + +When whole block is no longer needed, the block object can be released by calling vmaDestroyVirtualBlock(). +All allocations must be freed before the block is destroyed, which is checked internally by an assert. +However, if you don't want to call vmaVirtualFree() for each allocation, you can use vmaClearVirtualBlock() to free them all at once - +a feature not available in normal Vulkan memory allocator. Example: + +\code +vmaVirtualFree(block, alloc); +vmaDestroyVirtualBlock(block); +\endcode + +\section virtual_allocator_allocation_parameters Allocation parameters + +You can attach a custom pointer to each allocation by using vmaSetVirtualAllocationUserData(). +Its default value is null. +It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some +larger data structure containing more information. Example: + +\code +struct CustomAllocData +{ + std::string m_AllocName; +}; +CustomAllocData* allocData = new CustomAllocData(); +allocData->m_AllocName = "My allocation 1"; +vmaSetVirtualAllocationUserData(block, alloc, allocData); +\endcode + +The pointer can later be fetched, along with allocation offset and size, by passing the allocation handle to function +vmaGetVirtualAllocationInfo() and inspecting returned structure #VmaVirtualAllocationInfo. +If you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation! +Example: + +\code +VmaVirtualAllocationInfo allocInfo; +vmaGetVirtualAllocationInfo(block, alloc, &allocInfo); +delete (CustomAllocData*)allocInfo.pUserData; + +vmaVirtualFree(block, alloc); +\endcode + +\section virtual_allocator_alignment_and_units Alignment and units + +It feels natural to express sizes and offsets in bytes. +If an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member +VmaVirtualAllocationCreateInfo::alignment to request it. Example: + +\code +VmaVirtualAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.size = 4096; // 4 KB +allocCreateInfo.alignment = 4; // Returned offset must be a multiply of 4 B + +VmaVirtualAllocation alloc; +res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, nullptr); +\endcode + +Alignments of different allocations made from one block may vary. +However, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`, +you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes. +It might be more convenient, but you need to make sure to use this new unit consistently in all the places: + +- VmaVirtualBlockCreateInfo::size +- VmaVirtualAllocationCreateInfo::size and VmaVirtualAllocationCreateInfo::alignment +- Using offset returned by vmaVirtualAllocate() or in VmaVirtualAllocationInfo::offset + +\section virtual_allocator_statistics Statistics + +You can obtain statistics of a virtual block using vmaGetVirtualBlockStatistics() +(to get brief statistics that are fast to calculate) +or vmaCalculateVirtualBlockStatistics() (to get more detailed statistics, slower to calculate). +The functions fill structures #VmaStatistics, #VmaDetailedStatistics respectively - same as used by the normal Vulkan memory allocator. +Example: + +\code +VmaStatistics stats; +vmaGetVirtualBlockStatistics(block, &stats); +printf("My virtual block has %llu bytes used by %u virtual allocations\n", + stats.allocationBytes, stats.allocationCount); +\endcode + +You can also request a full list of allocations and free regions as a string in JSON format by calling +vmaBuildVirtualBlockStatsString(). +Returned string must be later freed using vmaFreeVirtualBlockStatsString(). +The format of this string differs from the one returned by the main Vulkan allocator, but it is similar. + +\section virtual_allocator_additional_considerations Additional considerations + +The "virtual allocator" functionality is implemented on a level of individual memory blocks. +Keeping track of a whole collection of blocks, allocating new ones when out of free space, +deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user. + +Alternative allocation algorithms are supported, just like in custom pools of the real GPU memory. +See enum #VmaVirtualBlockCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT). +You can find their description in chapter \ref custom_memory_pools. +Allocation strategies are also supported. +See enum #VmaVirtualAllocationCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT). + +Following features are supported only by the allocator of the real GPU memory and not by virtual allocations: +buffer-image granularity, `VMA_DEBUG_MARGIN`, `VMA_MIN_ALIGNMENT`. + + +\page debugging_memory_usage Debugging incorrect memory usage + +If you suspect a bug with memory usage, like usage of uninitialized memory or +memory being overwritten out of bounds of an allocation, +you can use debug features of this library to verify this. + +\section debugging_memory_usage_initialization Memory initialization + +If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used, +you can enable automatic memory initialization to verify this. +To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1. + +\code +#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1 +#include "vk_mem_alloc.h" +\endcode + +It makes memory of new allocations initialized to bit pattern `0xDCDCDCDC`. +Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`. +Memory is automatically mapped and unmapped if necessary. + +If you find these values while debugging your program, good chances are that you incorrectly +read Vulkan memory that is allocated but not initialized, or already freed, respectively. + +Memory initialization works only with memory types that are `HOST_VISIBLE` and with allocations that can be mapped. +It works also with dedicated allocations. + +\section debugging_memory_usage_margins Margins + +By default, allocations are laid out in memory blocks next to each other if possible +(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`). + +![Allocations without margin](../gfx/Margins_1.png) + +Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified +number of bytes as a margin after every allocation. + +\code +#define VMA_DEBUG_MARGIN 16 +#include "vk_mem_alloc.h" +\endcode + +![Allocations with margin](../gfx/Margins_2.png) + +If your bug goes away after enabling margins, it means it may be caused by memory +being overwritten outside of allocation boundaries. It is not 100% certain though. +Change in application behavior may also be caused by different order and distribution +of allocations across memory blocks after margins are applied. + +Margins work with all types of memory. + +Margin is applied only to allocations made out of memory blocks and not to dedicated +allocations, which have their own memory block of specific size. +It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag +or those automatically decided to put into dedicated allocations, e.g. due to its +large size or recommended by VK_KHR_dedicated_allocation extension. + +Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space. + +Note that enabling margins increases memory usage and fragmentation. + +Margins do not apply to \ref virtual_allocator. + +\section debugging_memory_usage_corruption_detection Corruption detection + +You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation +of contents of the margins. + +\code +#define VMA_DEBUG_MARGIN 16 +#define VMA_DEBUG_DETECT_CORRUPTION 1 +#include "vk_mem_alloc.h" +\endcode + +When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN` +(it must be multiply of 4) after every allocation is filled with a magic number. +This idea is also know as "canary". +Memory is automatically mapped and unmapped if necessary. + +This number is validated automatically when the allocation is destroyed. +If it is not equal to the expected value, `VMA_ASSERT()` is executed. +It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, +which indicates a serious bug. + +You can also explicitly request checking margins of all allocations in all memory blocks +that belong to specified memory types by using function vmaCheckCorruption(), +or in memory blocks that belong to specified custom pool, by using function +vmaCheckPoolCorruption(). + +Margin validation (corruption detection) works only for memory types that are +`HOST_VISIBLE` and `HOST_COHERENT`. + + +\section debugging_memory_usage_leak_detection Leak detection features + +At allocation and allocator destruction time VMA checks for unfreed and unmapped blocks using +`VMA_ASSERT_LEAK()`. This macro defaults to an assertion, triggering a typically fatal error in Debug +builds, and doing nothing in Release builds. You can provide your own definition of `VMA_ASSERT_LEAK()` +to change this behavior. + +At memory block destruction time VMA lists out all unfreed allocations using the `VMA_LEAK_LOG_FORMAT()` +macro, which defaults to `VMA_DEBUG_LOG_FORMAT`, which in turn defaults to a no-op. +If you're having trouble with leaks - for example, the aforementioned assertion triggers, but you don't +quite know \em why -, overriding this macro to print out the the leaking blocks, combined with assigning +individual names to allocations using vmaSetAllocationName(), can greatly aid in fixing them. + +\page other_api_interop Interop with other graphics APIs + +VMA provides some features that help with interoperability with other graphics APIs, e.g. OpenGL. + +\section opengl_interop_exporting_memory Exporting memory + +If you want to attach `VkExportMemoryAllocateInfoKHR` or other structure to `pNext` chain of memory allocations made by the library: + +You can create \ref custom_memory_pools for such allocations. +Define and fill in your `VkExportMemoryAllocateInfoKHR` structure and attach it to VmaPoolCreateInfo::pMemoryAllocateNext +while creating the custom pool. +Please note that the structure must remain alive and unchanged for the whole lifetime of the #VmaPool, +not only while creating it, as no copy of the structure is made, +but its original pointer is used for each allocation instead. + +If you want to export all memory allocated by VMA from certain memory types, +also dedicated allocations or other allocations made from default pools, +an alternative solution is to fill in VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes. +It should point to an array with `VkExternalMemoryHandleTypeFlagsKHR` to be automatically passed by the library +through `VkExportMemoryAllocateInfoKHR` on each allocation made from a specific memory type. +Please note that new versions of the library also support dedicated allocations created in custom pools. + +You should not mix these two methods in a way that allows to apply both to the same memory type. +Otherwise, `VkExportMemoryAllocateInfoKHR` structure would be attached twice to the `pNext` chain of `VkMemoryAllocateInfo`. + + +\section opengl_interop_custom_alignment Custom alignment + +Buffers or images exported to a different API like OpenGL may require a different alignment, +higher than the one used by the library automatically, queried from functions like `vkGetBufferMemoryRequirements`. +To impose such alignment: + +You can create \ref custom_memory_pools for such allocations. +Set VmaPoolCreateInfo::minAllocationAlignment member to the minimum alignment required for each allocation +to be made out of this pool. +The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image +from a function like `vkGetBufferMemoryRequirements`, which is called by VMA automatically. + +If you want to create a buffer with a specific minimum alignment out of default pools, +use special function vmaCreateBufferWithAlignment(), which takes additional parameter `minAlignment`. + +Note the problem of alignment affects only resources placed inside bigger `VkDeviceMemory` blocks and not dedicated +allocations, as these, by definition, always have alignment = 0 because the resource is bound to the beginning of its dedicated block. +You can ensure that an allocation is created as dedicated by using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +Contrary to Direct3D 12, Vulkan doesn't have a concept of alignment of the entire memory block passed on its allocation. + +\section opengl_interop_extended_allocation_information Extended allocation information + +If you want to rely on VMA to allocate your buffers and images inside larger memory blocks, +but you need to know the size of the entire block and whether the allocation was made +with its own dedicated memory, use function vmaGetAllocationInfo2() to retrieve +extended allocation information in structure #VmaAllocationInfo2. + + + +\page usage_patterns Recommended usage patterns + +Vulkan gives great flexibility in memory allocation. +This chapter shows the most common patterns. + +See also slides from talk: +[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New) + + +\section usage_patterns_gpu_only GPU-only resource + +When: +Any resources that you frequently write and read on GPU, +e.g. images used as color attachments (aka "render targets"), depth-stencil attachments, +images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)"). + +What to do: +Let the library select the optimal memory type, which will likely have `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`. + +\code +VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +imgCreateInfo.imageType = VK_IMAGE_TYPE_2D; +imgCreateInfo.extent.width = 3840; +imgCreateInfo.extent.height = 2160; +imgCreateInfo.extent.depth = 1; +imgCreateInfo.mipLevels = 1; +imgCreateInfo.arrayLayers = 1; +imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; +imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; +imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; +allocCreateInfo.priority = 1.0f; + +VkImage img; +VmaAllocation alloc; +vmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr); +\endcode + +Also consider: +Consider creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, +especially if they are large or if you plan to destroy and recreate them with different sizes +e.g. when display resolution changes. +Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later. +When VK_EXT_memory_priority extension is enabled, it is also worth setting high priority to such allocation +to decrease chances to be evicted to system memory by the operating system. + +\section usage_patterns_staging_copy_upload Staging copy for upload + +When: +A "staging" buffer than you want to map and fill from CPU code, then use as a source of transfer +to some GPU resource. + +What to do: +Use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT. +Let the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`. + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = 65536; +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); + +... + +memcpy(allocInfo.pMappedData, myData, myDataSize); +\endcode + +Also consider: +You can map the allocation using vmaMapMemory() or you can create it as persistenly mapped +using #VMA_ALLOCATION_CREATE_MAPPED_BIT, as in the example above. + + +\section usage_patterns_readback Readback + +When: +Buffers for data written by or transferred from the GPU that you want to read back on the CPU, +e.g. results of some computations. + +What to do: +Use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. +Let the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` +and `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`. + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = 65536; +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); + +... + +const float* downloadedData = (const float*)allocInfo.pMappedData; +\endcode + + +\section usage_patterns_advanced_data_uploading Advanced data uploading + +For resources that you frequently write on CPU via mapped pointer and +frequently read on GPU e.g. as a uniform buffer (also called "dynamic"), multiple options are possible: + +-# Easiest solution is to have one copy of the resource in `HOST_VISIBLE` memory, + even if it means system RAM (not `DEVICE_LOCAL`) on systems with a discrete graphics card, + and make the device reach out to that resource directly. + - Reads performed by the device will then go through PCI Express bus. + The performance of this access may be limited, but it may be fine depending on the size + of this resource (whether it is small enough to quickly end up in GPU cache) and the sparsity + of access. +-# On systems with unified memory (e.g. AMD APU or Intel integrated graphics, mobile chips), + a memory type may be available that is both `HOST_VISIBLE` (available for mapping) and `DEVICE_LOCAL` + (fast to access from the GPU). Then, it is likely the best choice for such type of resource. +-# Systems with a discrete graphics card and separate video memory may or may not expose + a memory type that is both `HOST_VISIBLE` and `DEVICE_LOCAL`, also known as Base Address Register (BAR). + If they do, it represents a piece of VRAM (or entire VRAM, if ReBAR is enabled in the motherboard BIOS) + that is available to CPU for mapping. + - Writes performed by the host to that memory go through PCI Express bus. + The performance of these writes may be limited, but it may be fine, especially on PCIe 4.0, + as long as rules of using uncached and write-combined memory are followed - only sequential writes and no reads. +-# Finally, you may need or prefer to create a separate copy of the resource in `DEVICE_LOCAL` memory, + a separate "staging" copy in `HOST_VISIBLE` memory and perform an explicit transfer command between them. + +Thankfully, VMA offers an aid to create and use such resources in the the way optimal +for the current Vulkan device. To help the library make the best choice, +use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT together with +#VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT. +It will then prefer a memory type that is both `DEVICE_LOCAL` and `HOST_VISIBLE` (integrated memory or BAR), +but if no such memory type is available or allocation from it fails +(PC graphics cards have only 256 MB of BAR by default, unless ReBAR is supported and enabled in BIOS), +it will fall back to `DEVICE_LOCAL` memory for fast GPU access. +It is then up to you to detect that the allocation ended up in a memory type that is not `HOST_VISIBLE`, +so you need to create another "staging" allocation and perform explicit transfers. + +\code +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = 65536; +bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + +VkBuffer buf; +VmaAllocation alloc; +VmaAllocationInfo allocInfo; +VkResult result = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo); +// Check result... + +VkMemoryPropertyFlags memPropFlags; +vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags); + +if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) +{ + // Allocation ended up in a mappable memory and is already mapped - write to it directly. + + // [Executed in runtime]: + memcpy(allocInfo.pMappedData, myData, myDataSize); + result = vmaFlushAllocation(allocator, alloc, 0, VK_WHOLE_SIZE); + // Check result... + + VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER }; + bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; + bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier.buffer = buf; + bufMemBarrier.offset = 0; + bufMemBarrier.size = VK_WHOLE_SIZE; + + vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr); +} +else +{ + // Allocation ended up in a non-mappable memory - a transfer using a staging buffer is required. + VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + stagingBufCreateInfo.size = 65536; + stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + VmaAllocationCreateInfo stagingAllocCreateInfo = {}; + stagingAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + stagingAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | + VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VkBuffer stagingBuf; + VmaAllocation stagingAlloc; + VmaAllocationInfo stagingAllocInfo; + result = vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo, + &stagingBuf, &stagingAlloc, &stagingAllocInfo); + // Check result... + + // [Executed in runtime]: + memcpy(stagingAllocInfo.pMappedData, myData, myDataSize); + result = vmaFlushAllocation(allocator, stagingAlloc, 0, VK_WHOLE_SIZE); + // Check result... + + VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER }; + bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + bufMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier.buffer = stagingBuf; + bufMemBarrier.offset = 0; + bufMemBarrier.size = VK_WHOLE_SIZE; + + vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr); + + VkBufferCopy bufCopy = { + 0, // srcOffset + 0, // dstOffset, + myDataSize, // size + }; + + vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy); + + VkBufferMemoryBarrier bufMemBarrier2 = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER }; + bufMemBarrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + bufMemBarrier2.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT; // We created a uniform buffer + bufMemBarrier2.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier2.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufMemBarrier2.buffer = buf; + bufMemBarrier2.offset = 0; + bufMemBarrier2.size = VK_WHOLE_SIZE; + + vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + 0, 0, nullptr, 1, &bufMemBarrier2, 0, nullptr); +} +\endcode + +\section usage_patterns_other_use_cases Other use cases + +Here are some other, less obvious use cases and their recommended settings: + +- An image that is used only as transfer source and destination, but it should stay on the device, + as it is used to temporarily store a copy of some texture, e.g. from the current to the next frame, + for temporal antialiasing or other temporal effects. + - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT` + - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO +- An image that is used only as transfer source and destination, but it should be placed + in the system RAM despite it doesn't need to be mapped, because it serves as a "swap" copy to evict + least recently used textures from VRAM. + - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT` + - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_HOST, + as VMA needs a hint here to differentiate from the previous case. +- A buffer that you want to map and write from the CPU, directly read from the GPU + (e.g. as a uniform or vertex buffer), but you have a clear preference to place it in device or + host memory due to its large size. + - Use `VkBufferCreateInfo::usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT` + - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST + - Use VmaAllocationCreateInfo::flags = #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT + + +\page configuration Configuration + +Please check "CONFIGURATION SECTION" in the code to find macros that you can define +before each include of this file or change directly in this file to provide +your own implementation of basic facilities like assert, `min()` and `max()` functions, +mutex, atomic etc. + +For example, define `VMA_ASSERT(expr)` before including the library to provide +custom implementation of the assertion, compatible with your project. +By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration +and empty otherwise. + +Similarly, you can define `VMA_LEAK_LOG_FORMAT` macro to enable printing of leaked (unfreed) allocations, +including their names and other parameters. Example: + +\code +#define VMA_LEAK_LOG_FORMAT(format, ...) do { \ + printf((format), __VA_ARGS__); \ + printf("\n"); \ + } while(false) +\endcode + +\section config_Vulkan_functions Pointers to Vulkan functions + +There are multiple ways to import pointers to Vulkan functions in the library. +In the simplest case you don't need to do anything. +If the compilation or linking of your program or the initialization of the #VmaAllocator +doesn't work for you, you can try to reconfigure it. + +First, the allocator tries to fetch pointers to Vulkan functions linked statically, +like this: + +\code +m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory; +\endcode + +If you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`. + +Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions. +You can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or +by using a helper library like [volk](https://github.com/zeux/volk). + +Third, VMA tries to fetch remaining pointers that are still null by calling +`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own. +You need to only fill in VmaVulkanFunctions::vkGetInstanceProcAddr and VmaVulkanFunctions::vkGetDeviceProcAddr. +Other pointers will be fetched automatically. +If you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`. + +Finally, all the function pointers required by the library (considering selected +Vulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null. + + +\section custom_memory_allocator Custom host memory allocator + +If you use custom allocator for CPU memory rather than default operator `new` +and `delete` from C++, you can make this library using your allocator as well +by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These +functions will be passed to Vulkan, as well as used by the library itself to +make any CPU-side allocations. + +\section allocation_callbacks Device memory allocation callbacks + +The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally. +You can setup callbacks to be informed about these calls, e.g. for the purpose +of gathering some statistics. To do it, fill optional member +VmaAllocatorCreateInfo::pDeviceMemoryCallbacks. + +\section heap_memory_limit Device heap memory limit + +When device memory of certain heap runs out of free space, new allocations may +fail (returning error code) or they may succeed, silently pushing some existing_ +memory blocks from GPU VRAM to system RAM (which degrades performance). This +behavior is implementation-dependent - it depends on GPU vendor and graphics +driver. + +On AMD cards it can be controlled while creating Vulkan device object by using +VK_AMD_memory_overallocation_behavior extension, if available. + +Alternatively, if you want to test how your program behaves with limited amount of Vulkan device +memory available without switching your graphics card to one that really has +smaller VRAM, you can use a feature of this library intended for this purpose. +To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit. + + + +\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation + +VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve +performance on some GPUs. It augments Vulkan API with possibility to query +driver whether it prefers particular buffer or image to have its own, dedicated +allocation (separate `VkDeviceMemory` block) for better efficiency - to be able +to do some internal optimizations. The extension is supported by this library. +It will be used automatically when enabled. + +It has been promoted to core Vulkan 1.1, so if you use eligible Vulkan version +and inform VMA about it by setting VmaAllocatorCreateInfo::vulkanApiVersion, +you are all set. + +Otherwise, if you want to use it as an extension: + +1 . When creating Vulkan device, check if following 2 device extensions are +supported (call `vkEnumerateDeviceExtensionProperties()`). +If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`). + +- VK_KHR_get_memory_requirements2 +- VK_KHR_dedicated_allocation + +If you enabled these extensions: + +2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating +your #VmaAllocator to inform the library that you enabled required extensions +and you want the library to use them. + +\code +allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + +vmaCreateAllocator(&allocatorInfo, &allocator); +\endcode + +That is all. The extension will be automatically used whenever you create a +buffer using vmaCreateBuffer() or image using vmaCreateImage(). + +When using the extension together with Vulkan Validation Layer, you will receive +warnings like this: + +_vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer._ + +It is OK, you should just ignore it. It happens because you use function +`vkGetBufferMemoryRequirements2KHR()` instead of standard +`vkGetBufferMemoryRequirements()`, while the validation layer seems to be +unaware of it. + +To learn more about this extension, see: + +- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap50.html#VK_KHR_dedicated_allocation) +- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5) + + + +\page vk_ext_memory_priority VK_EXT_memory_priority + +VK_EXT_memory_priority is a device extension that allows to pass additional "priority" +value to Vulkan memory allocations that the implementation may use prefer certain +buffers and images that are critical for performance to stay in device-local memory +in cases when the memory is over-subscribed, while some others may be moved to the system memory. + +VMA offers convenient usage of this extension. +If you enable it, you can pass "priority" parameter when creating allocations or custom pools +and the library automatically passes the value to Vulkan using this extension. + +If you want to use this extension in connection with VMA, follow these steps: + +\section vk_ext_memory_priority_initialization Initialization + +1) Call `vkEnumerateDeviceExtensionProperties` for the physical device. +Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_EXT_memory_priority". + +2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`. +Attach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to `VkPhysicalDeviceFeatures2::pNext` to be returned. +Check if the device feature is really supported - check if `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority` is true. + +3) While creating device with `vkCreateDevice`, enable this extension - add "VK_EXT_memory_priority" +to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`. + +4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`. +Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`. +Enable this device feature - attach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to +`VkPhysicalDeviceFeatures2::pNext` chain and set its member `memoryPriority` to `VK_TRUE`. + +5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you +have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT +to VmaAllocatorCreateInfo::flags. + +\section vk_ext_memory_priority_usage Usage + +When using this extension, you should initialize following member: + +- VmaAllocationCreateInfo::priority when creating a dedicated allocation with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +- VmaPoolCreateInfo::priority when creating a custom pool. + +It should be a floating-point value between `0.0f` and `1.0f`, where recommended default is `0.5F`. +Memory allocated with higher value can be treated by the Vulkan implementation as higher priority +and so it can have lower chances of being pushed out to system memory, experiencing degraded performance. + +It might be a good idea to create performance-critical resources like color-attachment or depth-stencil images +as dedicated and set high priority to them. For example: + +\code +VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; +imgCreateInfo.imageType = VK_IMAGE_TYPE_2D; +imgCreateInfo.extent.width = 3840; +imgCreateInfo.extent.height = 2160; +imgCreateInfo.extent.depth = 1; +imgCreateInfo.mipLevels = 1; +imgCreateInfo.arrayLayers = 1; +imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; +imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; +imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; +imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; +allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; +allocCreateInfo.priority = 1.0f; + +VkImage img; +VmaAllocation alloc; +vmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr); +\endcode + +`priority` member is ignored in the following situations: + +- Allocations created in custom pools: They inherit the priority, along with all other allocation parameters + from the parameters passed in #VmaPoolCreateInfo when the pool was created. +- Allocations created in default pools: They inherit the priority from the parameters + VMA used when creating default pools, which means `priority == 0.5F`. + + +\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory + +VK_AMD_device_coherent_memory is a device extension that enables access to +additional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and +`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for +allocation of buffers intended for writing "breadcrumb markers" in between passes +or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases. + +When the extension is available but has not been enabled, Vulkan physical device +still exposes those memory types, but their usage is forbidden. VMA automatically +takes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt +to allocate memory of such type is made. + +If you want to use this extension in connection with VMA, follow these steps: + +\section vk_amd_device_coherent_memory_initialization Initialization + +1) Call `vkEnumerateDeviceExtensionProperties` for the physical device. +Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_AMD_device_coherent_memory". + +2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`. +Attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned. +Check if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true. + +3) While creating device with `vkCreateDevice`, enable this extension - add "VK_AMD_device_coherent_memory" +to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`. + +4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`. +Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`. +Enable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to +`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`. + +5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you +have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT +to VmaAllocatorCreateInfo::flags. + +\section vk_amd_device_coherent_memory_usage Usage + +After following steps described above, you can create VMA allocations and custom pools +out of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible +devices. There are multiple ways to do it, for example: + +- You can request or prefer to allocate out of such memory types by adding + `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags + or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with + other ways of \ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage. +- If you manually found memory type index to use for this purpose, force allocation + from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1U << index`. + +\section vk_amd_device_coherent_memory_more_information More information + +To learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_AMD_device_coherent_memory.html) + +Example use of this extension can be found in the code of the sample and test suite +accompanying this library. + + +\page vk_khr_external_memory_win32 VK_KHR_external_memory_win32 + +On Windows, the VK_KHR_external_memory_win32 device extension allows exporting a Win32 `HANDLE` +of a `VkDeviceMemory` block, to be able to reference the memory on other Vulkan logical devices or instances, +in multiple processes, and/or in multiple APIs. +VMA offers support for it. + +\section vk_khr_external_memory_win32_initialization Initialization + +1) Make sure the extension is defined in the code by including following header before including VMA: + +\code +#include +\endcode + +2) Check if "VK_KHR_external_memory_win32" is available among device extensions. +Enable it when creating the `VkDevice` object. + +3) Enable the usage of this extension in VMA by setting flag #VMA_ALLOCATOR_CREATE_KHR_EXTERNAL_MEMORY_WIN32_BIT +when calling vmaCreateAllocator(). + +4) Make sure that VMA has access to the `vkGetMemoryWin32HandleKHR` function by either enabling `VMA_DYNAMIC_VULKAN_FUNCTIONS` macro +or setting VmaVulkanFunctions::vkGetMemoryWin32HandleKHR explicitly. +For more information, see \ref quick_start_initialization_importing_vulkan_functions. + +\section vk_khr_external_memory_win32_preparations Preparations + +You can find example usage among tests, in file "Tests.cpp", function `TestWin32Handles()`. + +To use the extenion, buffers need to be created with `VkExternalMemoryBufferCreateInfoKHR` attached to their `pNext` chain, +and memory allocations need to be made with `VkExportMemoryAllocateInfoKHR` attached to their `pNext` chain. +To make use of them, you need to use \ref custom_memory_pools. Example: + +\code +// Define an example buffer and allocation parameters. +VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = { + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, + nullptr, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT +}; +VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +exampleBufCreateInfo.size = 0x10000; // Doesn't matter here. +exampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; +exampleBufCreateInfo.pNext = &externalMemBufCreateInfo; + +VmaAllocationCreateInfo exampleAllocCreateInfo = {}; +exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + +// Find memory type index to use for the custom pool. +uint32_t memTypeIndex; +VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_Allocator, + &exampleBufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex); +// Check res... + +// Create a custom pool. +constexpr static VkExportMemoryAllocateInfoKHR exportMemAllocInfo = { + VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, + nullptr, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT +}; +VmaPoolCreateInfo poolCreateInfo = {}; +poolCreateInfo.memoryTypeIndex = memTypeIndex; +poolCreateInfo.pMemoryAllocateNext = (void*)&exportMemAllocInfo; + +VmaPool pool; +res = vmaCreatePool(g_Allocator, &poolCreateInfo, &pool); +// Check res... + +// YOUR OTHER CODE COMES HERE.... + +// At the end, don't forget to destroy it! +vmaDestroyPool(g_Allocator, pool); +\endcode + +Note that the structure passed as VmaPoolCreateInfo::pMemoryAllocateNext must remain alive and unchanged +for the whole lifetime of the custom pool, because it will be used when the pool allocates a new device memory block. +No copy is made internally. This is why variable `exportMemAllocInfo` is defined as `static`. + +\section vk_khr_external_memory_win32_memory_allocation Memory allocation + +Finally, you can create a buffer with an allocation out of the custom pool. +The buffer should use same flags as the sample buffer used to find the memory type. +It should also specify `VkExternalMemoryBufferCreateInfoKHR` in its `pNext` chain. + +\code +VkExternalMemoryBufferCreateInfoKHR externalMemBufCreateInfo = { + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, + nullptr, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT +}; +VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; +bufCreateInfo.size = // Your desired buffer size. +bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; +bufCreateInfo.pNext = &externalMemBufCreateInfo; + +VmaAllocationCreateInfo allocCreateInfo = {}; +allocCreateInfo.pool = pool; // It is enough to set this one member. + +VkBuffer buf; +VmaAllocation alloc; +res = vmaCreateBuffer(g_Allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr); +// Check res... + +// YOUR OTHER CODE COMES HERE.... + +// At the end, don't forget to destroy it! +vmaDestroyBuffer(g_Allocator, buf, alloc); +\endcode + +If you need each allocation to have its own device memory block and start at offset 0, you can still do +by using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag. It works also with custom pools. + +\section vk_khr_external_memory_win32_exporting_win32_handle Exporting Win32 handle + +After the allocation is created, you can acquire a Win32 `HANDLE` to the `VkDeviceMemory` block it belongs to. +VMA function vmaGetMemoryWin32Handle() is a replacement of the Vulkan function `vkGetMemoryWin32HandleKHR`. + +\code +HANDLE handle; +res = vmaGetMemoryWin32Handle(g_Allocator, alloc, nullptr, &handle); +// Check res... + +// YOUR OTHER CODE COMES HERE.... + +// At the end, you must close the handle. +CloseHandle(handle); +\endcode + +Documentation of the VK_KHR_external_memory_win32 extension states that: + +> If handleType is defined as an NT handle, vkGetMemoryWin32HandleKHR must be called no more than once for each valid unique combination of memory and handleType. + +This is ensured automatically inside VMA. +The library fetches the handle on first use, remembers it internally, and closes it when the memory block or dedicated allocation is destroyed. +Every time you call vmaGetMemoryWin32Handle(), VMA calls `DuplicateHandle` and returns a new handle that you need to close. + +For further information, please check documentation of the vmaGetMemoryWin32Handle() function. + + +\page enabling_buffer_device_address Enabling buffer device address + +Device extension VK_KHR_buffer_device_address +allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code. +It has been promoted to core Vulkan 1.2. + +If you want to use this feature in connection with VMA, follow these steps: + +\section enabling_buffer_device_address_initialization Initialization + +1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device. +Check if the extension is supported - if returned array of `VkExtensionProperties` contains +"VK_KHR_buffer_device_address". + +2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`. +Attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned. +Check if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress` is true. + +3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add +"VK_KHR_buffer_device_address" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`. + +4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`. +Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`. +Enable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to +`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`. + +5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you +have enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT +to VmaAllocatorCreateInfo::flags. + +\section enabling_buffer_device_address_usage Usage + +After following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA. +The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to +allocated memory blocks wherever it might be needed. + +Please note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`. +The second part of this functionality related to "capture and replay" is not supported, +as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage. + +\section enabling_buffer_device_address_more_information More information + +To learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address) + +Example use of this extension can be found in the code of the sample and test suite +accompanying this library. + +\page general_considerations General considerations + +\section general_considerations_thread_safety Thread safety + +- The library has no global state, so separate #VmaAllocator objects can be used + independently. + There should be no need to create multiple such objects though - one per `VkDevice` is enough. +- By default, all calls to functions that take #VmaAllocator as first parameter + are safe to call from multiple threads simultaneously because they are + synchronized internally when needed. + This includes allocation and deallocation from default memory pool, as well as custom #VmaPool. +- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT + flag, calls to functions that take such #VmaAllocator object must be + synchronized externally. +- Access to a #VmaAllocation object must be externally synchronized. For example, + you must not call vmaGetAllocationInfo() and vmaMapMemory() from different + threads at the same time if you pass the same #VmaAllocation object to these + functions. +- #VmaVirtualBlock is not safe to be used from multiple threads simultaneously. + +\section general_considerations_versioning_and_compatibility Versioning and compatibility + +The library uses [**Semantic Versioning**](https://semver.org/), +which means version numbers follow convention: Major.Minor.Patch (e.g. 2.3.0), where: + +- Incremented Patch version means a release is backward- and forward-compatible, + introducing only some internal improvements, bug fixes, optimizations etc. + or changes that are out of scope of the official API described in this documentation. +- Incremented Minor version means a release is backward-compatible, + so existing code that uses the library should continue to work, while some new + symbols could have been added: new structures, functions, new values in existing + enums and bit flags, new structure members, but not new function parameters. +- Incrementing Major version means a release could break some backward compatibility. + +All changes between official releases are documented in file "CHANGELOG.md". + +\warning Backward compatibility is considered on the level of C++ source code, not binary linkage. +Adding new members to existing structures is treated as backward compatible if initializing +the new members to binary zero results in the old behavior. +You should always fully initialize all library structures to zeros and not rely on their +exact binary size. + +\section general_considerations_validation_layer_warnings Validation layer warnings + +When using this library, you can meet following types of warnings issued by +Vulkan validation layer. They don't necessarily indicate a bug, so you may need +to just ignore them. + +- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.* + - It happens when VK_KHR_dedicated_allocation extension is enabled. + `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it. +- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.* + - It happens when you map a buffer or image, because the library maps entire + `VkDeviceMemory` block, where different types of images and buffers may end + up together, especially on GPUs with unified memory like Intel. +- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.* + - It may happen when you use [defragmentation](@ref defragmentation). + +\section general_considerations_allocation_algorithm Allocation algorithm + +The library uses following algorithm for allocation, in order: + +-# Try to find free range of memory in existing blocks. +-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size. +-# If failed, try to create such block with size / 2, size / 4, size / 8. +-# If failed, try to allocate separate `VkDeviceMemory` for this allocation, + just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. +-# If failed, choose other memory type that meets the requirements specified in + VmaAllocationCreateInfo and go to point 1. +-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. + +\section general_considerations_features_not_supported Features not supported + +Features deliberately excluded from the scope of this library: + +-# **Data transfer.** Uploading (streaming) and downloading data of buffers and images + between CPU and GPU memory and related synchronization is responsibility of the user. + Defining some "texture" object that would automatically stream its data from a + staging copy in CPU memory to GPU memory would rather be a feature of another, + higher-level library implemented on top of VMA. + VMA doesn't record any commands to a `VkCommandBuffer`. It just allocates memory. +-# **Recreation of buffers and images.** Although the library has functions for + buffer and image creation: vmaCreateBuffer(), vmaCreateImage(), you need to + recreate these objects yourself after defragmentation. That is because the big + structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in + #VmaAllocation object. +-# **Handling CPU memory allocation failures.** When dynamically creating small C++ + objects in CPU memory (not Vulkan memory), allocation failures are not checked + and handled gracefully, because that would complicate code significantly and + is usually not needed in desktop PC applications anyway. + Success of an allocation is just checked with an assert. +-# **Code free of any compiler warnings.** Maintaining the library to compile and + work correctly on so many different platforms is hard enough. Being free of + any warnings, on any version of any compiler, is simply not feasible. + There are many preprocessor macros that make some variables unused, function parameters unreferenced, + or conditional expressions constant in some configurations. + The code of this library should not be bigger or more complicated just to silence these warnings. + It is recommended to disable such warnings instead. +-# This is a C++ library with C interface. **Bindings or ports to any other programming languages** are welcome as external projects but + are not going to be included into this repository. +*/ diff --git a/lib/All/slang/LICENSE b/lib/All/slang/LICENSE new file mode 100644 index 0000000..b6918ff --- /dev/null +++ b/lib/All/slang/LICENSE @@ -0,0 +1,29 @@ +SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +LLVM Exceptions to the Apache 2.0 License + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. diff --git a/lib/All/slang/README.md b/lib/All/slang/README.md new file mode 100644 index 0000000..4139db6 --- /dev/null +++ b/lib/All/slang/README.md @@ -0,0 +1,156 @@ +Slang +===== +![CI Status](https://github.com/shader-slang/slang/actions/workflows/ci.yml/badge.svg?branch=master) +![CTS Status](https://github.com/shader-slang/slang/actions/workflows/vk-gl-cts-nightly.yml/badge.svg) + +Slang is a shading language that makes it easier to build and maintain large shader codebases in a modular and extensible fashion, while also maintaining the highest possible performance on modern GPUs and graphics APIs. +Slang is based on years of collaboration between researchers at NVIDIA, Carnegie Mellon University, Stanford, MIT, UCSD and the University of Washington. + + +Why Slang? +--------------- + +The Slang shading language is designed to enable real-time graphics developers to work with large-scale, high-performance shader code. + +### Write Shaders Once, Run Anywhere + +The Slang compiler can generate code for a wide variety of targets: D3D12, Vulkan, Metal, D3D11, CUDA, and even generate code to run on a CPU. For textual targets, such as Metal Shading Language (MSL) and CUDA, Slang produces readable code that preserves original identifier names, as well as the type and call structure, making it easier to debug. + +### Access the Latest GPU Features + +Slang code is highly portable, but can still leverage unique platform capabilities, including the latest features in Direct3D and Vulkan. For example, developers can make full use of [pointers](https://shader-slang.com/slang/user-guide/convenience-features.html#pointers-limited) when generating SPIR-V. +Slang's [capability system](https://shader-slang.com/slang/user-guide/capabilities.html) helps applications manage feature set differences across target platforms by ensuring code only uses available features during the type-checking step, before generating final code. Additionally, Slang provides [flexible interop](https://shader-slang.com/slang/user-guide/a1-04-interop.html) features to enable directly embedding target code or SPIR-V into generated shaders. + +### Leverage Neural Graphics with Automatic Differentiation + +Slang can [automatically generate both forward and backward derivative propagation code](https://shader-slang.com/slang/user-guide/autodiff.html) for complex functions that involve arbitrary control flow and dynamic dispatch. This allows existing rendering codebases to easily become differentiable, or for Slang to serve as the kernel language in a PyTorch-driven machine learning framework via [`slangtorch`](https://shader-slang.com/slang/user-guide/a1-02-slangpy.html). + +### Scalable Software Development with Modules + +Slang provides a [module system](https://shader-slang.com/slang/user-guide/modules.html) that enables logical organization of code for separate compilation. Slang modules can be independently compiled offline to a custom IR (with optional obfuscation) and then linked at runtime to generate code in formats such as DXIL or SPIR-V. + +### Code Specialization that Works with Modules + +Slang supports [generics and interfaces](https://shader-slang.com/slang/user-guide/interfaces-generics.html) (a.k.a. type traits/protocols), allowing for clear expression of shader specialization without the need for preprocessor techniques or string-pasting. Unlike C++ templates, Slang's generics are pre-checked and don't produce cascading error messages that are difficult to diagnose. The same generic shader can be specialized for a variety of different types to produce specialized code ahead of time, or on the fly, entirely under application control. + +### Easy On-ramp for HLSL and GLSL Codebases + +Slang's syntax is similar to HLSL, and most existing HLSL code can be compiled with the Slang compiler out-of-the-box, or with just minor modifications. This allows existing shader codebases to immediately benefit from Slang without requiring a complete rewrite or port. + +Slang provides a compatibility module that enables the use of most GLSL intrinsic functions and GLSL's parameter binding syntax. + +### Comprehensive Tooling Support + +Slang comes with full support of IntelliSense editing features in Visual Studio Code and Visual Studio through the Language Server Protocol. +Full debugging capabilities are also available through RenderDoc and SPIR-V based tools. + +Getting Started +--------------- + +The fastest way to get started using Slang in your own development is to use a pre-built binary package, available through GitHub [releases](https://github.com/shader-slang/slang/releases). +Slang binaries are also included in the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home) since version 1.3.296.0. + +There are packages built for x86_64 and aarch64 Windows, Linux and macOS. +Each binary release includes the command-line `slangc` compiler, a shared library for the compiler, and the `slang.h` header. + +See the user-guide for info on using the `slangc` command-line tool: [Slang Command Line Usage]( +https://shader-slang.com/slang/user-guide/compiling.html#command-line-compilation-with-slangc). + +If you want to try out the Slang language without installing anything, a fast and simple way is to use the [Slang Playground](https://shader-slang.com/slang-playground). The playground allows you to compile Slang code to a variety of targets, and even run some simple shaders directly within the browser. The playground loads Slang compiler to your browser and runs all compilation locally. No data will be sent to any servers. + +If you would like to build Slang from source, please consult the [build instructions](docs/building.md). + +Documentation +------------- + +The Slang project provides a variety of different [documentation](docs/), but most users would be well served starting with the [User's Guide](https://shader-slang.github.io/slang/user-guide/). + +For developers writing Slang code, the [Slang Core Module Reference](https://shader-slang.com/stdlib-reference/) provides detailed documentation on Slang's built-in types and functions. + +We also provide a few [examples](examples/) of how to integrate Slang into a rendering application. + +These examples use a graphics layer that we include with Slang called "GFX" which is an abstraction library of various graphics APIs (D3D11, D2D12, OpenGL, Vulkan, CUDA, and the CPU) to support cross-platform applications using GPU graphics and compute capabilities. +GFX is being deprecated in favor of [slang-rhi](https://github.com/shader-slang/slang-rhi). + +Additionally, we recommend checking out [Vulkan Mini Examples](https://github.com/nvpro-samples/vk_mini_samples/) for more examples of using Slang's language features available on Vulkan, such as pointers and the ray tracing intrinsics. + +Contributing +------------ + +If you'd like to contribute to the project, we are excited to have your input. +The following guidelines should be observed by contributors: + +* Please follow the contributor [Code of Conduct](CODE_OF_CONDUCT.md). +* Bugs reports and feature requests should go through the GitHub issue tracker +* Changes should ideally come in as small pull requests on top of `master`, coming from your own personal fork of the project +* Large features that will involve multiple contributors or a long development time should be discussed in issues, and broken down into smaller pieces that can be implemented and checked in in stages + +[Contribution guide](CONTRIBUTING.md) describes the workflow for contributors at more detail. + +Limitations and Support +----------------------- + +### Platform support + +The Slang compiler and libraries can be built on the following platforms: + +| Windows | Linux | MacOS | WebAssembly | +|:---------:|:---------:|:---------:|:------------:| +| supported | supported | supported | experimental | + +Both `x86_64` and `aarch64` architectures are supported on Windows, Linux and MacOS platforms. + +### Target support + +Slang can compile shader code to the following targets: + +| Target | Status | Output Formats | +|:-----------:|:-------------------------------------------------------------------------------------:|:----------------------------------------------------------------:| +| Direct3D 11 | [supported](https://shader-slang.com/slang/user-guide/targets.html#direct3d-11) | HLSL | +| Direct3D 12 | [supported](https://shader-slang.com/slang/user-guide/targets.html#direct3d-12) | HLSL | +| Vulkan | [supported](https://shader-slang.com/slang/user-guide/targets.html#vulkan) | SPIRV, GLSL | +| Metal | [experimental*](https://shader-slang.com/slang/user-guide/targets.html#metal) | Metal Shading Language | +| WebGPU | experimental** | WGSL | +| CUDA | [supported](https://shader-slang.com/slang/user-guide/targets.html#cuda-and-optix) | C++ (compute only) | +| Optix | [experimental](https://shader-slang.com/slang/user-guide/targets.html#cuda-and-optix) | C++ (WIP) | +| CPU | [experimental](https://shader-slang.com/slang/user-guide/targets.html#cpu-compute) | C++ (kernel), C++ (host), standalone executable, dynamic library | + +> *Slang currently supports generating vertex, fragment, compute, task and mesh +> shaders for Metal. + +> **WGSL support is still work in-progress. + +For greater detail, see the [Supported Compilation +Targets](https://shader-slang.com/slang/user-guide/targets.html) section of the +[User Guide](https://shader-slang.github.io/slang/user-guide/) + +The Slang project has been used for production applications and large shader +codebases, but it is still under active development. Support is currently +focused on the platforms (Windows, Linux) and target APIs (Direct3D 12, Vulkan) +where Slang is used most heavily. Users who are looking for support on other +platforms or APIs should coordinate with the development team via the issue +tracker to make sure that their use cases can be supported. + +License +------- + +The Slang code itself is under the Apache 2.0 with LLVM Exception license (see [LICENSE](LICENSE)). + +Builds of the core Slang tools depend on the following projects, either automatically or optionally, which may have their own licenses: + +* [`glslang`](https://github.com/KhronosGroup/glslang) (BSD) +* [`lz4`](https://github.com/lz4/lz4) (BSD) +* [`miniz`](https://github.com/richgel999/miniz) (MIT) +* [`spirv-headers`](https://github.com/KhronosGroup/SPIRV-Headers) (Modified MIT) +* [`spirv-tools`](https://github.com/KhronosGroup/SPIRV-Tools) (Apache 2.0) +* [`ankerl::unordered_dense::{map, set}`](https://github.com/martinus/unordered_dense) (MIT) + +Slang releases may include [LLVM](https://github.com/llvm/llvm-project) under the license: + +* [`llvm`](https://llvm.org/docs/DeveloperPolicy.html#new-llvm-project-license-framework) (Apache 2.0 License with LLVM exceptions) + +Some of the tests and example programs that build with Slang use the following projects, which may have their own licenses: + +* [`glm`](https://github.com/g-truc/glm) (MIT) +* `stb_image` and `stb_image_write` from the [`stb`](https://github.com/nothings/stb) collection of single-file libraries (Public Domain) +* [`tinyobjloader`](https://github.com/tinyobjloader/tinyobjloader) (MIT) diff --git a/lib/All/slang/bin/gfx.slang b/lib/All/slang/bin/gfx.slang new file mode 100644 index 0000000..f901fbe --- /dev/null +++ b/lib/All/slang/bin/gfx.slang @@ -0,0 +1,1991 @@ +import slang; + +public namespace gfx +{ +public typedef slang.Result Result; + +public typedef intptr_t Int; +public typedef uintptr_t UInt; +public typedef uint64_t DeviceAddress; +public typedef int GfxIndex; +public typedef int GfxCount; +public typedef intptr_t Size; +public typedef intptr_t Offset; + +public static const uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF; + +public enum class StructType +{ + D3D12ExtendedDesc, +}; + +public enum class StageType +{ + Unknown, + Vertex, + Hull, + Domain, + Geometry, + Fragment, + Compute, + RayGeneration, + Intersection, + AnyHit, + ClosestHit, + Miss, + Callable, + Amplification, + Mesh, + CountOf, +}; + +public enum class DeviceType +{ + Unknown, + Default, + DirectX11, + DirectX12, + OpenGl, + Vulkan, + Metal, + CPU, + CUDA, + CountOf, +}; + +public enum class ProjectionStyle +{ + Unknown, + OpenGl, + DirectX, + Vulkan, + Metal, + CountOf, +}; + +public enum class BindingStyle +{ + Unknown, + DirectX, + OpenGl, + Vulkan, + Metal, + CPU, + CUDA, + CountOf, +}; + +public enum class AccessFlag +{ + None, + Read, + Write, +}; + +public static const GfxCount kMaxRenderTargetCount = 8; + +// Defines how linking should be performed for a shader program. +public 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. + SingleProgram, + + // Link and compile each entry-point individually, potentially with different specializations. + SeparateEntryPointCompilation +}; + +public enum class ShaderModuleSourceType +{ + 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. +}; + +public struct ShaderProgramDesc2 +{ + public ShaderModuleSourceType sourceType = ShaderModuleSourceType::SlangSource; + public void *sourceData = nullptr; + public Size sourceDataSize = 0; + + // Number of entry points to include in the shader program. 0 means include all entry points + // defined in the module. + public GfxCount entryPointCount = 0; + // Names of entry points to include in the shader program. The size of the array must be + // `entryPointCount`. + public NativeString* entryPointNames = nullptr; +}; + +[COM("9d32d0ad-915c-4ffd-91e2-508554a04a76")] +public interface IShaderProgram +{ + public slang::TypeReflection* findTypeByName(NativeString name); +}; + +public 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. + Unknown, + + R32G32B32A32_TYPELESS, + R32G32B32_TYPELESS, + R32G32_TYPELESS, + R32_TYPELESS, + + R16G16B16A16_TYPELESS, + R16G16_TYPELESS, + R16_TYPELESS, + + R8G8B8A8_TYPELESS, + R8G8_TYPELESS, + R8_TYPELESS, + B8G8R8A8_TYPELESS, + + R32G32B32A32_FLOAT, + R32G32B32_FLOAT, + R32G32_FLOAT, + R32_FLOAT, + + R16G16B16A16_FLOAT, + R16G16_FLOAT, + R16_FLOAT, + + R64_UINT, + + R32G32B32A32_UINT, + R32G32B32_UINT, + R32G32_UINT, + R32_UINT, + + R16G16B16A16_UINT, + R16G16_UINT, + R16_UINT, + + R8G8B8A8_UINT, + R8G8_UINT, + R8_UINT, + + R64_SINT, + + R32G32B32A32_SINT, + R32G32B32_SINT, + R32G32_SINT, + R32_SINT, + + R16G16B16A16_SINT, + R16G16_SINT, + R16_SINT, + + R8G8B8A8_SINT, + R8G8_SINT, + R8_SINT, + + R16G16B16A16_UNORM, + R16G16_UNORM, + R16_UNORM, + + R8G8B8A8_UNORM, + R8G8B8A8_UNORM_SRGB, + R8G8_UNORM, + R8_UNORM, + B8G8R8A8_UNORM, + B8G8R8A8_UNORM_SRGB, + B8G8R8X8_UNORM, + B8G8R8X8_UNORM_SRGB, + + R16G16B16A16_SNORM, + R16G16_SNORM, + R16_SNORM, + + R8G8B8A8_SNORM, + R8G8_SNORM, + R8_SNORM, + + D32_FLOAT, + D16_UNORM, + + B4G4R4A4_UNORM, + B5G6R5_UNORM, + B5G5R5A1_UNORM, + + R9G9B9E5_SHAREDEXP, + R10G10B10A2_TYPELESS, + R10G10B10A2_UNORM, + R10G10B10A2_UINT, + R11G11B10_FLOAT, + + BC1_UNORM, + BC1_UNORM_SRGB, + BC2_UNORM, + BC2_UNORM_SRGB, + BC3_UNORM, + BC3_UNORM_SRGB, + BC4_UNORM, + BC4_SNORM, + BC5_UNORM, + BC5_SNORM, + BC6H_UF16, + BC6H_SF16, + BC7_UNORM, + BC7_UNORM_SRGB, + + _Count, +}; + +public struct FormatInfo +{ + public GfxCount channelCount; ///< The amount of channels in the format. Only set if the channelType is set + public uint8_t channelType; ///< One of SlangScalarType None if type isn't made up of elements of type. TODO: Change to uint32_t? + + public Size blockSizeInBytes; ///< The size of a block in bytes. + public GfxCount pixelsPerBlock; ///< The number of pixels contained in a block. + public GfxCount blockWidth; ///< The width of a block in pixels. + public GfxCount blockHeight; ///< The height of a block in pixels. +}; + +public enum class InputSlotClass +{ + PerVertex, PerInstance +}; + +public struct InputElementDesc +{ + public NativeString semanticName; ///< The name of the corresponding parameter in shader code. + public GfxIndex semanticIndex; ///< The index of the corresponding parameter in shader code. Only needed if multiple parameters share a semantic name. + public Format format; ///< The format of the data being fetched for this element. + public Offset offset; ///< The offset in bytes of this element from the start of the corresponding chunk of vertex stream data. + public GfxIndex bufferSlotIndex; ///< The index of the vertex stream to fetch this element's data from. +}; + +public struct VertexStreamDesc +{ + public Size stride; ///< The stride in bytes for this vertex stream. + public InputSlotClass slotClass; ///< Whether the stream contains per-vertex or per-instance data. + public GfxCount instanceDataStepRate; ///< How many instances to draw per chunk of data. +}; + +public enum class PrimitiveType +{ + Point, Line, Triangle, Patch +}; + +public enum class PrimitiveTopology +{ + TriangleList, TriangleStrip, PointList, LineList, LineStrip +}; + +public enum class ResourceState +{ + Undefined, + General, + PreInitialized, + VertexBuffer, + IndexBuffer, + ConstantBuffer, + StreamOutput, + ShaderResource, + UnorderedAccess, + RenderTarget, + DepthRead, + DepthWrite, + Present, + IndirectArgument, + CopySource, + CopyDestination, + ResolveSource, + ResolveDestination, + AccelerationStructure, + AccelerationStructureBuildInput, + _Count +}; + +public struct ResourceStateSet +{ + public uint64_t m_bitFields; + + [mutating] + public void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); } + + public bool contains(ResourceState state) { return (m_bitFields & (1LL << (uint32_t)state)) != 0; } + public __init() { m_bitFields = 0; } + public __init(ResourceState state) { add(state); } +}; + +public ResourceStateSet operator &(ResourceStateSet val, ResourceStateSet that) +{ + ResourceStateSet result; + result.m_bitFields = val.m_bitFields & that.m_bitFields; + return result; +} + +/// Describes how memory for the resource should be allocated for CPU access. +public enum class MemoryType +{ + DeviceLocal, + Upload, + ReadBack, +}; + +public 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. + D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value. + Metal, // A general Metal object handle. +}; + +public struct InteropHandle +{ + public InteropHandleAPI api = InteropHandleAPI::Unknown; + public uint64_t handleValue = 0LLU; +}; + +// Declare opaque type +public struct InputLayoutDesc +{ + public InputElementDesc *inputElements; + public GfxCount inputElementCount; + public VertexStreamDesc *vertexStreams; + public GfxCount vertexStreamCount; +}; + +[COM("45223711-a84b-455c-befa-4937421e8e2e")] +public interface IInputLayout +{ +}; + +/// 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) +public enum class ResourceType +{ + 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 +public struct ResourceDescBase +{ + public ResourceType type = ResourceType::Unknown; + public ResourceState defaultState = ResourceState::Undefined; + public ResourceStateSet allowedStates = {}; + public MemoryType memoryType = MemoryType::DeviceLocal; + public InteropHandle existingHandle = {}; + public bool isShared = false; +}; + +[COM("a0e39f34-8398-4522-95c2-ebc0f984ef3f")] +public interface IResource +{ + public ResourceType getType(); + public Result getNativeResourceHandle(out InteropHandle outHandle); + public Result getSharedHandle(out InteropHandle outHandle); + public Result setDebugName(NativeString name); + public NativeString getDebugName(); +}; + +public struct MemoryRange +{ + // TODO: Change to Offset/Size? + public uint64_t offset; + public uint64_t size; +}; + +public struct BufferResourceDesc : ResourceDescBase +{ + public Size sizeInBytes = 0; ///< Total size in bytes + public Size elementSize = 0; ///< Get the element stride. If > 0, this is a structured buffer + public Format format = Format::Unknown; +}; + +[COM("1b274efe-5e37-492b-826e-7ee7e8f5a49b")] +public interface IBufferResource : IResource +{ + public BufferResourceDesc *getDesc(); + public DeviceAddress getDeviceAddress(); + public Result map(MemoryRange *rangeToRead, void **outPointer); + public Result unmap(MemoryRange* writtenRange); +}; + +public struct DepthStencilClearValue +{ + public float depth = 1.0f; + public uint32_t stencil = 0; +}; + +public struct ColorClearValue +{ + public float4 values; + + [mutating] + public void setValue(uint4 uintVal) + { + values = reinterpret(uintVal); + } + + [mutating] + public void setValue(float4 floatVal) + { + values = floatVal; + } +}; + +public struct ClearValue +{ + public ColorClearValue color; + public DepthStencilClearValue depthStencil; +}; + +public struct BufferRange +{ + public Offset offset; ///< Offset in bytes. + public Size size; ///< Size in bytes. +}; + +public enum class TextureAspect : uint32_t +{ + Default = 0, + Color = 0x00000001, + Depth = 0x00000002, + Stencil = 0x00000004, + MetaData = 0x00000008, + Plane0 = 0x00000010, + Plane1 = 0x00000020, + Plane2 = 0x00000040, + + DepthStencil = 0x6, +}; + +public struct SubresourceRange +{ + public TextureAspect aspectMask; + public GfxIndex mipLevel; + public GfxCount mipLevelCount; + public GfxIndex baseArrayLayer; // For Texture3D, this is WSlice. + public GfxCount layerCount; // For cube maps, this is a multiple of 6. +}; + +public static const Size kRemainingTextureSize = 0xFFFFFFFF; +public struct TextureResourceSampleDesc +{ + public GfxCount numSamples; ///< Number of samples per pixel + public int quality; ///< The quality measure for the samples +}; + +public struct TextureResourceDesc : ResourceDescBase +{ + public int3 size; + + public GfxCount arraySize = 0; ///< Array size + + public GfxCount numMipLevels = 0; ///< Number of mip levels - if 0 will create all mip levels + public Format format; ///< The resources format + public TextureResourceSampleDesc sampleDesc; ///< How the resource is sampled + public ClearValue* optimalClearValue; +}; + +/// 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`. +/// +public struct SubresourceData +{ + /// Pointer to texel data for the subresource tensor. + public void *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. + /// + public 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. + /// + public gfx::Size strideZ; +}; + +[COM("cf88a31c-6187-46c5-a4b7-eb-58-c7-33-40-17")] +public interface ITextureResource : IResource +{ + public TextureResourceDesc* getDesc(); +}; + +public enum class ComparisonFunc : uint8_t +{ + Never = 0x0, + Less = 0x1, + Equal = 0x2, + LessEqual = 0x3, + Greater = 0x4, + NotEqual = 0x5, + GreaterEqual = 0x6, + Always = 0x7, +}; + +public enum class TextureFilteringMode +{ + Point, + Linear, +}; + +public enum class TextureAddressingMode +{ + Wrap, + ClampToEdge, + ClampToBorder, + MirrorRepeat, + MirrorOnce, +}; + +public enum class TextureReductionOp +{ + Average, + Comparison, + Minimum, + Maximum, +}; + +public struct SamplerStateDesc +{ + public TextureFilteringMode minFilter; + public TextureFilteringMode magFilter; + public TextureFilteringMode mipFilter; + public TextureReductionOp reductionOp; + public TextureAddressingMode addressU; + public TextureAddressingMode addressV; + public TextureAddressingMode addressW; + public float mipLODBias; + public uint32_t maxAnisotropy; + public ComparisonFunc comparisonFunc; + public float4 borderColor; + public float minLOD; + public float maxLOD; + public __init() + { + minFilter = TextureFilteringMode::Linear; + magFilter = TextureFilteringMode::Linear; + mipFilter = TextureFilteringMode::Linear; + reductionOp = TextureReductionOp::Average; + addressU = TextureAddressingMode::Wrap; + addressV = TextureAddressingMode::Wrap; + addressW = TextureAddressingMode::Wrap; + mipLODBias = 0.0f; + maxAnisotropy = 1; + comparisonFunc = ComparisonFunc::Never; + borderColor = float4(1.0f, 1.0f, 1.0f, 1.0f); + minLOD = -float.maxValue; + maxLOD = float.maxValue; + } +}; + +[COM("8b8055df-9377-401d-91ff-3f-a3-bf-66-64-f4")] +public interface ISamplerState +{ + /// Returns a native API handle representing this sampler state object. + /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE. + /// When using Vulkan, this will be a VkSampler. + public Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +public enum class ResourceViewType +{ + Unknown, + + RenderTarget, + DepthStencil, + ShaderResource, + UnorderedAccess, + AccelerationStructure, + + CountOf_, +}; + +public struct RenderTargetDesc +{ + // The resource shape of this render target view. + public ResourceType shape; +}; + +public struct ResourceViewDesc +{ + public ResourceViewType type; + public Format format; + + // Required fields for `RenderTarget` and `DepthStencil` views. + public RenderTargetDesc renderTarget; + // Specifies the range of a texture resource for a ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view. + public SubresourceRange subresourceRange; + // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view. + public BufferRange bufferRange; +}; + +[COM("7b6c4926-0884-408c-ad8a-50-3a-8e-23-98-a4")] +public interface IResourceView +{ + public ResourceViewDesc* getViewDesc(); + + /// 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. + public Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +public enum class AccelerationStructureKind +{ + TopLevel, + BottomLevel +}; + +// The public enum values are intentionally consistent with +// D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS. +public enum AccelerationStructureBuildFlags +{ + None, + AllowUpdate = 1, + AllowCompaction = 2, + PreferFastTrace = 4, + PreferFastBuild = 8, + MinimizeMemory = 16, + PerformUpdate = 32 +}; + +public enum class GeometryType +{ + Triangles, ProcedurePrimitives +}; + +public struct GeometryFlags +{ + // The public enum values are intentionally consistent with + // D3D12_RAYTRACING_GEOMETRY_FLAGS. + public enum Enum + { + None, + Opaque = 1, + NoDuplicateAnyHitInvocation = 2 + }; +}; + +public struct TriangleDesc +{ + public DeviceAddress transform3x4; + public Format indexFormat; + public Format vertexFormat; + public GfxCount indexCount; + public GfxCount vertexCount; + public DeviceAddress indexData; + public DeviceAddress vertexData; + public Size vertexStride; +}; + +public struct ProceduralAABB +{ + public float minX; + public float minY; + public float minZ; + public float maxX; + public float maxY; + public float maxZ; +}; + +public struct ProceduralAABBDesc +{ + /// Number of AABBs. + public GfxCount count; + + /// Pointer to an array of `ProceduralAABB` values in device memory. + public DeviceAddress data; + + /// Stride in bytes of the AABB values array. + public Size stride; +}; + +public struct GeometryDesc +{ + public GeometryType type; + public GeometryFlags::Enum flags; + public TriangleDesc triangles; + public property ProceduralAABBDesc proceduralAABBs + { + get { return reinterpret(triangles); } + set { triangles = reinterpret(newValue); } + } +}; + +// The public enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS +// and VkGeometryInstanceFlagBitsKHR. +public enum GeometryInstanceFlags +{ + None = 0, + TriangleFacingCullDisable = 0x00000001, + TriangleFrontCounterClockwise = 0x00000002, + ForceOpaque = 0x00000004, + NoOpaque = 0x00000008 +}; + +// TODO: Should any of these be changed? +// The layout of this public struct is intentionally consistent with D3D12_RAYTRACING_INSTANCE_DESC +// and VkAccelerationStructureInstanceKHR. +public struct InstanceDesc +{ + public float transform[3][4]; + public uint32_t instanceID24_mask8; + public property uint32_t instanceID { get { return instanceID24_mask8 & 0xFFFFFF; } set { instanceID24_mask8 = (instanceID24_mask8 & 0xFF000000) | (newValue & 0xFFFFFF); } } + public property uint32_t instanceMask { get { return instanceID24_mask8 >> 24; } set { instanceID24_mask8 = (newValue << 24) | (instanceID24_mask8 & 0x00FFFFFF); } } + + public uint32_t instanceContributionToHitGroupIndex24_flags8; + public property uint32_t instanceContributionToHitGroupIndex + { + get { return instanceContributionToHitGroupIndex24_flags8 & 0xFFFFFF; } + set { instanceContributionToHitGroupIndex24_flags8 = (instanceContributionToHitGroupIndex24_flags8 & 0xFF000000) | (newValue & 0xFFFFFF); } + } + public property GeometryInstanceFlags flags + { + get { return (GeometryInstanceFlags)(instanceContributionToHitGroupIndex24_flags8 >> 24); } + set { instanceContributionToHitGroupIndex24_flags8 = ((uint32_t)newValue << 24) | (instanceContributionToHitGroupIndex24_flags8 & 0x00FFFFFF); } + } + public DeviceAddress accelerationStructure; +}; + +public struct AccelerationStructurePrebuildInfo +{ + public Size resultDataMaxSize; + public Size scratchDataSize; + public Size updateScratchDataSize; +}; + +public struct AccelerationStructureBuildInputs +{ + public AccelerationStructureKind kind; + + public AccelerationStructureBuildFlags flags; + + public GfxCount descCount; + + /// Array of `InstanceDesc` values in device memory. + /// Used when `kind` is `TopLevel`. + public DeviceAddress instanceDescs; + + /// Array of `GeometryDesc` values. + /// Used when `kind` is `BottomLevel`. + public GeometryDesc *geometryDescs; +}; + +public struct AccelerationStructureCreateDesc +{ + public AccelerationStructureKind kind; + public NativeRef buffer; + public Offset offset; + public Size size; +}; + +public struct AccelerationStructureBuildDesc +{ + public AccelerationStructureBuildInputs inputs; + public NativeRef source; + public NativeRef dest; + public DeviceAddress scratchData; +}; + +[COM("a5cdda3c-1d4e-4df7-8ef2-b7-3f-ce-04-de-3b")] +public interface IAccelerationStructure : IResourceView +{ + public DeviceAddress getDeviceAddress(); +}; + +public struct FenceDesc +{ + public uint64_t initialValue; + public bool isShared; +}; + +[COM("7fe1c283-d3f4-48ed-aaf3-01-51-96-4e-7c-b5")] +public interface IFence +{ + /// Returns the currently signaled value on the device. + public Result getCurrentValue(uint64_t *outValue); + + /// Signals the fence from the host with the specified value. + public Result setCurrentValue(uint64_t value); + + public Result getSharedHandle(InteropHandle *outHandle); + public Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +public struct ShaderOffset +{ + public Int uniformOffset = 0; // TODO: Change to Offset? + public GfxIndex bindingRangeIndex = 0; + public GfxIndex bindingArrayIndex = 0; +} + +public enum class ShaderObjectContainerType +{ + None, Array, StructuredBuffer +}; + +[COM("c1fa997e-5ca2-45ae-9bcb-c4-35-9e-85-05-85")] +public interface IShaderObject +{ + public slang::TypeLayoutReflection* getElementTypeLayout(); + public ShaderObjectContainerType getContainerType(); + public GfxCount getEntryPointCount(); + public Result getEntryPoint(GfxIndex index, out Optional entryPoint); + public Result setData(ShaderOffset *offset, void *data, Size size); + public Result getObject(ShaderOffset *offset, out Optional object); + public Result setObject(ShaderOffset* offset, IShaderObject object); + public Result setResource(ShaderOffset* offset, IResourceView resourceView); + public Result setSampler(ShaderOffset* offset, ISamplerState sampler); + public Result setCombinedTextureSampler(ShaderOffset* offset, IResourceView textureView, ISamplerState sampler); + + /// 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. + public Result setSpecializationArgs( + ShaderOffset* offset, + slang::SpecializationArg *args, + GfxCount count); + + public Result getCurrentVersion( + ITransientResourceHeap transientHeap, + out IShaderObject outObject); + + public void* getRawData(); + + public Size getSize(); + + /// Use the provided constant buffer instead of the internally created one. + public Result setConstantBufferOverride(IBufferResource constantBuffer); +}; + +public enum class StencilOp : uint8_t +{ + Keep, + Zero, + Replace, + IncrementSaturate, + DecrementSaturate, + Invert, + IncrementWrap, + DecrementWrap, +}; + +public enum class FillMode : uint8_t +{ + Solid, + Wireframe, +}; + +public enum class CullMode : uint8_t +{ + None, + Front, + Back, +}; + +public enum class FrontFaceMode : uint8_t +{ + CounterClockwise, + Clockwise, +}; + +public struct DepthStencilOpDesc +{ + public StencilOp stencilFailOp = StencilOp::Keep; + public StencilOp stencilDepthFailOp = StencilOp::Keep; + public StencilOp stencilPassOp = StencilOp::Keep; + public ComparisonFunc stencilFunc = ComparisonFunc::Always; + public __init() + { + stencilFailOp = StencilOp::Keep; + stencilDepthFailOp = StencilOp::Keep; + stencilPassOp = StencilOp::Keep; + stencilFunc = ComparisonFunc::Always; + } +}; + +public struct DepthStencilDesc +{ + public bool depthTestEnable = false; + public bool depthWriteEnable = true; + public ComparisonFunc depthFunc = ComparisonFunc::Less; + + public bool stencilEnable = false; + public uint32_t stencilReadMask = 0xFFFFFFFF; + public uint32_t stencilWriteMask = 0xFFFFFFFF; + public DepthStencilOpDesc frontFace; + public DepthStencilOpDesc backFace; + + public uint32_t stencilRef = 0; + + public __init() + { + depthTestEnable = false; + depthWriteEnable = true; + depthFunc = ComparisonFunc::Less; + stencilEnable = false; + stencilReadMask = 0xFFFFFFFF; + stencilWriteMask = 0xFFFFFFFF; + stencilRef = 0; + } +}; + +public struct RasterizerDesc +{ + public FillMode fillMode = FillMode::Solid; + public CullMode cullMode = CullMode::None; + public FrontFaceMode frontFace = FrontFaceMode::CounterClockwise; + public int32_t depthBias = 0; + public float depthBiasClamp = 0.0f; + public float slopeScaledDepthBias = 0.0f; + public bool depthClipEnable = true; + public bool scissorEnable = false; + public bool multisampleEnable = false; + public bool antialiasedLineEnable = false; + public bool enableConservativeRasterization = false; + public uint32_t forcedSampleCount = 0; + + public __init() + { + fillMode = FillMode::Solid; + cullMode = CullMode::None; + frontFace = FrontFaceMode::CounterClockwise; + depthBias = 0; + depthBiasClamp = 0.0f; + slopeScaledDepthBias = 0.0f; + depthClipEnable = true; + scissorEnable = false; + multisampleEnable = false; + antialiasedLineEnable = false; + enableConservativeRasterization = false; + forcedSampleCount = 0; + } +}; + +public enum class LogicOp +{ + NoOp, +}; + +public enum class BlendOp +{ + Add, + Subtract, + ReverseSubtract, + Min, + Max, +}; + +public enum class BlendFactor +{ + Zero, + One, + SrcColor, + InvSrcColor, + SrcAlpha, + InvSrcAlpha, + DestAlpha, + InvDestAlpha, + DestColor, + InvDestColor, + SrcAlphaSaturate, + BlendColor, + InvBlendColor, + SecondarySrcColor, + InvSecondarySrcColor, + SecondarySrcAlpha, + InvSecondarySrcAlpha, +}; + +public enum RenderTargetWriteMask +{ + EnableNone = 0, + EnableRed = 0x01, + EnableGreen = 0x02, + EnableBlue = 0x04, + EnableAlpha = 0x08, + EnableAll = 0x0F, +}; + +public struct AspectBlendDesc +{ + public BlendFactor srcFactor = BlendFactor::One; + public BlendFactor dstFactor = BlendFactor::Zero; + public BlendOp op = BlendOp::Add; + + __init() + { + srcFactor = BlendFactor::One; + dstFactor = BlendFactor::Zero; + op = BlendOp::Add; + } +}; + +public struct TargetBlendDesc +{ + public AspectBlendDesc color; + public AspectBlendDesc alpha; + public bool enableBlend; + public LogicOp logicOp; + public RenderTargetWriteMask writeMask; + public __init() + { + enableBlend = false; + logicOp = LogicOp::NoOp; + writeMask = RenderTargetWriteMask::EnableAll; + } +}; + +public struct BlendDesc +{ + public TargetBlendDesc targets[kMaxRenderTargetCount] = {}; + public GfxCount targetCount = 0; + + public bool alphaToCoverageEnable = false; +}; + +public struct FramebufferTargetLayout +{ + public Format format; + public GfxCount sampleCount; +}; + +public struct FramebufferLayoutDesc +{ + public GfxCount renderTargetCount; + public FramebufferTargetLayout *renderTargets; + public FramebufferTargetLayout *depthStencil; +}; + +[COM("0a838785-c13a-4832-ad88-64-06-b5-4b-5e-ba")] +public interface IFramebufferLayout +{ +}; + +public struct GraphicsPipelineStateDesc +{ + public NativeRef program; + + public NativeRef inputLayout; + public NativeRef framebufferLayout; + public PrimitiveType primitiveType; + public DepthStencilDesc depthStencil; + public RasterizerDesc rasterizer; + public BlendDesc blend; + + public __init() + { + program = {IShaderProgram()}; + inputLayout = {IInputLayout()}; + framebufferLayout = {IFramebufferLayout()}; + primitiveType = PrimitiveType::Triangle; + depthStencil = {}; + rasterizer = {}; + blend = {}; + } +}; + +public struct ComputePipelineStateDesc +{ + public NativeRef program; + public void *d3d12RootSignatureOverride; +}; + +public enum RayTracingPipelineFlags +{ + None = 0, + SkipTriangles = 1, + SkipProcedurals = 2, +}; + +public struct HitGroupDesc +{ + public NativeString hitGroupName; + public NativeString closestHitEntryPoint; + public NativeString anyHitEntryPoint; + public NativeString intersectionEntryPoint; +}; + +public struct RayTracingPipelineStateDesc +{ + public NativeRef program; + public GfxCount hitGroupCount = 0; + public HitGroupDesc *hitGroups; + public int maxRecursion = 0; + public Size maxRayPayloadSize = 0; + public Size maxAttributeSizeInBytes = 8; + public RayTracingPipelineFlags flags = RayTracingPipelineFlags::None; +}; + +// Specifies the bytes to overwrite into a record in the shader table. +public struct ShaderRecordOverwrite +{ + public Offset offset; // Offset within the shader record. + public Size size; // Number of bytes to overwrite. + public uint8_t data[8]; // Content to overwrite. +}; + +public struct ShaderTableDesc +{ + public GfxCount rayGenShaderCount; + public NativeString* rayGenShaderEntryPointNames; + public ShaderRecordOverwrite *rayGenShaderRecordOverwrites; + + public GfxCount missShaderCount; + public NativeString *missShaderEntryPointNames; + public ShaderRecordOverwrite *missShaderRecordOverwrites; + + public GfxCount hitGroupCount; + public NativeString *hitGroupNames; + public ShaderRecordOverwrite *hitGroupRecordOverwrites; + + NativeRef program; +}; + +[COM("a721522c-df31-4c2f-a5e7-3b-e0-12-4b-31-78")] +public interface IShaderTable +{ + +}; + +[COM("0ca7e57d-8a90-44f3-bdb1-fe-9b-35-3f-5a-72")] +public interface IPipelineState +{ + Result getNativeHandle(InteropHandle *outHandle); +}; + +public struct ScissorRect +{ + public int32_t minX; + public int32_t minY; + public int32_t maxX; + public int32_t maxY; +}; + +public struct Viewport +{ + public float originX = 0.0f; + public float originY = 0.0f; + public float extentX = 0.0f; + public float extentY = 0.0f; + public float minZ = 0.0f; + public float maxZ = 1.0f; +}; + +public struct FramebufferDesc +{ + public GfxCount renderTargetCount; + public NativeRef *renderTargetViews; + public NativeRef depthStencilView; + public NativeRef layout; +}; + +[COM("0f0c0d9a-4ef3-4e18-9ba9-34-60-ea-69-87-95")] +public interface IFramebuffer +{ +}; + +public enum class WindowHandleType +{ + Unknown, + Win32Handle, + XLibHandle, +}; + +public struct WindowHandle +{ + public WindowHandleType type; + public void* handleValues[2]; + public static WindowHandle fromHwnd(void *hwnd) + { + WindowHandle handle = {WindowHandleType::Unknown, {nullptr, nullptr}}; + handle.type = WindowHandleType::Win32Handle; + handle.handleValues[0] = hwnd; + return handle; + } + public static WindowHandle fromXWindow(void *xdisplay, uint32_t xwindow) + { + WindowHandle handle = {WindowHandleType::Unknown, {nullptr, nullptr}}; + handle.type = WindowHandleType::XLibHandle; + handle.handleValues[0] = xdisplay; + handle.handleValues[1] = (void*)xwindow; + return handle; + } +}; + +public enum FaceMask +{ + Front = 1, Back = 2 +}; + +public enum class TargetLoadOp +{ + Load, Clear, DontCare +}; +public enum class TargetStoreOp +{ + Store, DontCare +}; +public struct TargetAccessDesc +{ + public TargetLoadOp loadOp; + public TargetLoadOp stencilLoadOp; + public TargetStoreOp storeOp; + public TargetStoreOp stencilStoreOp; + public ResourceState initialState; + public ResourceState finalState; +}; +public struct RenderPassLayoutDesc +{ + public NativeRef framebufferLayout; + public GfxCount renderTargetCount; + public TargetAccessDesc *renderTargetAccess; + public TargetAccessDesc *depthStencilAccess; +}; + +[COM("daab0b1a-f45d-4ae9-bf2c-e0-bb-76-7d-fa-d1")] +public interface IRenderPassLayout +{ +}; + +public enum class QueryType +{ + Timestamp, + AccelerationStructureCompactedSize, + AccelerationStructureSerializedSize, + AccelerationStructureCurrentSize, +}; + +public struct QueryPoolDesc +{ + public QueryType type; + public GfxCount count; +}; + +[COM("c2cc3784-12da-480a-a874-8b-31-96-1c-a4-36")] +public interface IQueryPool +{ + public Result getResult(GfxIndex queryIndex, GfxCount count, uint64_t *data); + public Result reset(); +}; + +[COM("77ea6383-be3d-40aa-8b45-fd-f0-d7-5b-fa-34")] +public interface ICommandEncoder +{ + public void endEncoding(); + public void writeTimestamp(IQueryPool queryPool, GfxIndex queryIndex); +}; + +public struct IndirectDispatchArguments +{ + public GfxCount ThreadGroupCountX; + public GfxCount ThreadGroupCountY; + public GfxCount ThreadGroupCountZ; +}; + +public struct IndirectDrawArguments +{ + public GfxCount VertexCountPerInstance; + public GfxCount InstanceCount; + public GfxIndex StartVertexLocation; + public GfxIndex StartInstanceLocation; +}; + +public struct IndirectDrawIndexedArguments +{ + public GfxCount IndexCountPerInstance; + public GfxCount InstanceCount; + public GfxIndex StartIndexLocation; + public GfxIndex BaseVertexLocation; + public GfxIndex StartInstanceLocation; +}; + +public struct SamplePosition +{ + public int8_t x; + public int8_t y; +}; + +public enum ClearResourceViewFlags +{ + None = 0, + ClearDepth = 1, + ClearStencil = 2, + FloatClearValues = 4 +}; + +[COM("F99A00E9-ED50-4088-8A0E-3B26755031EA")] +public interface IResourceCommandEncoder : ICommandEncoder +{ + public void copyBuffer( + IBufferResource dst, + Offset dstOffset, + IBufferResource src, + Offset srcOffset, + Size size); + /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0 + /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent + /// arguments are ignored. + public void copyTexture( + ITextureResource dst, + ResourceState dstState, + SubresourceRange dstSubresource, + int3 dstOffset, + NativeRef src, + ResourceState srcState, + SubresourceRange srcSubresource, + int3 srcOffset, + int3 extent); + + /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment. + public void copyTextureToBuffer( + IBufferResource dst, + Offset dstOffset, + Size dstSize, + Size dstRowStride, + ITextureResource src, + ResourceState srcState, + SubresourceRange srcSubresource, + int3 srcOffset, + int3 extent); + public void uploadTextureData( + ITextureResource dst, + SubresourceRange subResourceRange, + int3 offset, + int3 extent, + SubresourceData *subResourceData, + GfxCount subResourceDataCount); + public void uploadBufferData(IBufferResource dst, Offset offset, Size size, void *data); + public void textureBarrier( + GfxCount count, NativeRef *textures, ResourceState src, ResourceState dst); + public void textureSubresourceBarrier( + ITextureResource texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst); + public void bufferBarrier( + GfxCount count, NativeRef *buffers, ResourceState src, ResourceState dst); + public void clearResourceView( + IResourceView view, ClearValue *clearValue, ClearResourceViewFlags flags); + public void resolveResource( + ITextureResource source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource dest, + ResourceState destState, + SubresourceRange destRange); + public void resolveQuery( + IQueryPool queryPool, + GfxIndex index, + GfxCount count, + IBufferResource buffer, + Offset offset); + public void beginDebugEvent(NativeString name, float rgbColor[3]); + public void endDebugEvent(); +}; + +[COM("7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE")] +public interface IRenderCommandEncoder : IResourceCommandEncoder +{ + // 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 + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // resources or shader objects that is set into `outRootShaderObject` stays alive during + // the execution of the command buffer. + public Result bindPipeline(IPipelineState state, out IShaderObject outRootShaderObject); + + // Sets the current pipeline state along with a pre-created mutable root shader object. + public Result bindPipelineWithRootObject(IPipelineState state, NativeRef rootObject); + + public void setViewports(GfxCount count, Viewport *viewports); + public void setScissorRects(GfxCount count, ScissorRect *scissors); + + public void setPrimitiveTopology(PrimitiveTopology topology); + public void setVertexBuffers( + GfxIndex startSlot, + GfxCount slotCount, + NativeRef* buffers, + Offset *offsets); + + public void setIndexBuffer(IBufferResource buffer, Format indexFormat, Offset offset); + public void draw(GfxCount vertexCount, GfxIndex startVertex); + public void drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0); + public void drawIndirect( + GfxCount maxDrawCount, + IBufferResource argBuffer, + Offset argOffset, + NativeRef countBuffer, + Offset countOffset = 0); + public void drawIndexedIndirect( + GfxCount maxDrawCount, + IBufferResource argBuffer, + Offset argOffset, + NativeRef countBuffer, + Offset countOffset = 0); + public void setStencilReference(uint32_t referenceValue); + public Result setSamplePositions( + GfxCount samplesPerPixel, GfxCount pixelCount, SamplePosition *samplePositions); + public void drawInstanced( + GfxCount vertexCount, + GfxCount instanceCount, + GfxIndex startVertex, + GfxIndex startInstanceLocation); + public void drawIndexedInstanced( + GfxCount indexCount, + GfxCount instanceCount, + GfxIndex startIndexLocation, + GfxIndex baseVertexLocation, + GfxIndex startInstanceLocation); +}; + +[COM("88AA9322-82F7-4FE6-A68A-29C7FE798737")] +public interface IComputeCommandEncoder : IResourceCommandEncoder +{ + // 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 + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // resources or shader objects that is set into `outRooShaderObject` stays alive during + // the execution of the command buffer. + public Result bindPipeline(IPipelineState state, out Optional outRootShaderObject); + + // Sets the current pipeline state along with a pre-created mutable root shader object. + public Result bindPipelineWithRootObject(IPipelineState state, IShaderObject rootObject); + + public void dispatchCompute(int x, int y, int z); + public void dispatchComputeIndirect(IBufferResource cmdBuffer, Offset offset); +}; + +public enum class AccelerationStructureCopyMode +{ + Clone, Compact +}; + +public struct AccelerationStructureQueryDesc +{ + public QueryType queryType; + + public NativeRef queryPool; + + public GfxIndex firstQueryIndex; +}; + +[COM("9a672b87-5035-45e3-967c-1f-85-cd-b3-63-4f")] +public interface IRayTracingCommandEncoder : IResourceCommandEncoder +{ + public void buildAccelerationStructure( + AccelerationStructureBuildDesc *desc, + GfxCount propertyQueryCount, + AccelerationStructureQueryDesc *queryDescs); + public void copyAccelerationStructure( + NativeRef dest, + NativeRef src, + AccelerationStructureCopyMode mode); + public void queryAccelerationStructureProperties( + GfxCount accelerationStructureCount, + NativeRef *accelerationStructures, + GfxCount queryCount, + AccelerationStructureQueryDesc *queryDescs); + public void serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure source); + public void deserializeAccelerationStructure(IAccelerationStructure dest, DeviceAddress source); + + public Result bindPipeline(IPipelineState state, out IShaderObject rootObject); + // Sets the current pipeline state along with a pre-created mutable root shader object. + public Result bindPipelineWithRootObject(IPipelineState state, IShaderObject rootObject); + + /// 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. + public void dispatchRays( + GfxIndex rayGenShaderIndex, + NativeRef shaderTable, + GfxCount width, + GfxCount height, + GfxCount depth); +}; + +[COM("5d56063f-91d4-4723-a7a7-7a-15-af-93-eb-48")] +public interface ICommandBuffer +{ + // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding` + // before calling other `encode*Commands` methods. + // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is + // invalid for further use. To continue recording, the user must request a new encoder + // object by calling one of the `encode*Commands` methods again. + public void encodeRenderCommands( + IRenderPassLayout renderPass, + IFramebuffer framebuffer, + out IRenderCommandEncoder outEncoder); + + public void encodeComputeCommands(out Optional encoder); + + public void encodeResourceCommands(out Optional outEncoder); + + public void encodeRayTracingCommands(out Optional outEncoder); + + public void close(); + + public Result getNativeHandle(out InteropHandle outHandle); +}; + +public enum class QueueType +{ + Graphics +}; +public struct CommandQueueDesc +{ + public QueueType type; +}; + +[COM("14e2bed0-0ad0-4dc8-b341-06-3f-e7-2d-bf-0e")] +public interface ICommandQueue +{ + public const CommandQueueDesc* getDesc(); + + public void executeCommandBuffers( + GfxCount count, + NativeRef *commandBuffers, + Optional fenceToSignal, + uint64_t newFenceValue); + + public Result getNativeHandle(out InteropHandle outHandle); + + public void waitOnHost(); + + /// Queues a device side wait for the given fences. + public Result waitForFenceValuesOnDevice(GfxCount fenceCount, NativeRef *fences, uint64_t *waitValues); +}; + +public enum TransientResourceHeapFlags +{ + None = 0, + AllowResizing = 0x1, +}; + +public struct TransientResourceHeapDesc +{ + public TransientResourceHeapFlags flags; + public Size constantBufferSize; + public GfxCount samplerDescriptorCount; + public GfxCount uavDescriptorCount; + public GfxCount srvDescriptorCount; + public GfxCount constantBufferDescriptorCount; + public GfxCount accelerationStructureDescriptorCount; +}; + +[COM("cd48bd29-ee72-41b8-bcff-0a-2b-3a-aa-6d-0b")] +public interface ITransientResourceHeap +{ + // Waits until GPU commands issued before last call to `finish()` has been completed, and resets + // all transient resources holds by the heap. + // This method must be called before using the transient heap to issue new GPU commands. + // In most situations this method should be called at the beginning of each frame. + public Result synchronizeAndReset(); + + // 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. + public Result finish(); + + // Command buffers are one-time use. Once it is submitted to the queue via + // `executeCommandBuffers` a command buffer is no longer valid to be used any more. Command + // buffers must be closed before submission. The current D3D12 implementation has a limitation + // that only one command buffer maybe recorded at a time. User must finish recording a command + // buffer before creating another command buffer. + public Result createCommandBuffer(out Optional outCommandBuffer); +}; + +public struct SwapchainDesc +{ + public Format format; + public GfxCount width, height; + public GfxCount imageCount; + public NativeRef queue; + public bool enableVSync; +}; + +[COM("be91ba6c-0784-4308-a1-00-19-c3-66-83-44-b2")] +public interface ISwapchain +{ + public const SwapchainDesc* getDesc(); + + /// Returns the back buffer image at `index`. + public Result getImage(GfxIndex index, out ITextureResource outResource); + + /// Present the next image in the swapchain. + public Result present(); + + /// Returns the index of next back buffer image that will be presented in the next + /// `present` call. If the swapchain is invalid/out-of-date, this method returns -1. + public int acquireNextImage(); + + /// Resizes the back buffers of this swapchain. All render target views and framebuffers + /// referencing the back buffer images must be freed before calling this method. + public Result resize(GfxCount width, GfxCount height); + + // Check if the window is occluded. + public bool isOccluded(); + + // Toggle full screen mode. + public Result setFullScreenMode(bool mode); +}; + +public struct DeviceInfo +{ + public DeviceType deviceType; + + public BindingStyle bindingStyle; + + public ProjectionStyle projectionStyle; + + /// An projection matrix that ensures x, y mapping to pixels + /// is the same on all targets + public float identityProjectionMatrix[16]; + + /// The name of the graphics API being used by this device. + public NativeString apiName; + + /// The name of the graphics adapter. + public NativeString adapterName; + + /// The clock frequency used in timestamp queries. + public uint64_t timestampFrequency; +}; + +public enum class DebugMessageType +{ + Info, Warning, Error +}; +public enum class DebugMessageSource +{ + Layer, Driver, Slang +}; + +[COM("B219D7E8-255A-2572-D46C-A0E5D99CEB90")] +public interface IDebugCallback +{ + public void handleMessage(DebugMessageType type, DebugMessageSource source, NativeString message); +}; + +public struct SlangDesc +{ + public NativeRef slangGlobalSession = {slang::IGlobalSession()}; // (optional) A slang global session object. If null will create automatically. + + public slang::SlangMatrixLayoutMode defaultMatrixLayoutMode = slang::SlangMatrixLayoutMode::SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + public NativeString *searchPaths = nullptr; + public GfxCount searchPathCount = 0; + + public slang::PreprocessorMacroDesc *preprocessorMacros = nullptr; + public GfxCount preprocessorMacroCount = 0; + + public NativeString targetProfile = ""; // (optional) Target shader profile. If null this will be set to platform dependent default. + public slang::SlangFloatingPointMode floatingPointMode = slang::SlangFloatingPointMode::SLANG_FLOATING_POINT_MODE_DEFAULT; + public slang::SlangOptimizationLevel optimizationLevel = slang::SlangOptimizationLevel::SLANG_OPTIMIZATION_LEVEL_DEFAULT; + public slang::SlangTargetFlags targetFlags = slang::SlangTargetFlags.None; + public slang::SlangLineDirectiveMode lineDirectiveMode = slang::SlangLineDirectiveMode::SLANG_LINE_DIRECTIVE_MODE_DEFAULT; +}; + +public struct ShaderCacheDesc +{ + // The root directory for the shader cache. If not set, shader cache is disabled. + public NativeString shaderCachePath = ""; + // The maximum number of entries stored in the cache. + public GfxCount maxEntryCount = 0; +}; + +public struct DeviceInteropHandles +{ + public InteropHandle handles[3] = {}; +}; + +public struct DeviceDesc +{ + // The underlying API/Platform of the device. + public 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. + public DeviceInteropHandles existingDeviceHandles = {}; + // Name to identify the adapter to use + public NativeString adapter = ""; + // Number of required features. + public GfxCount requiredFeatureCount = 0; + // Array of required feature names, whose size is `requiredFeatureCount`. + public NativeString *requiredFeatures = nullptr; + // A command dispatcher object that intercepts and handles actual low-level API call. + void *apiCommandDispatcher = nullptr; + // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required. + public GfxIndex nvapiExtnSlot = -1; + // Configurations for the shader cache. + public ShaderCacheDesc shaderCache = {}; + // Configurations for Slang compiler. + public SlangDesc slang = {}; + + public GfxCount extendedDescCount = 0; + public void **extendedDescs = nullptr; +}; + +[COM("715bdf26-5135-11eb-AE93-02-42-AC-13-00-02")] +public interface IDevice +{ + public Result getNativeDeviceHandles(out DeviceInteropHandles outHandles); + + public bool hasFeature(NativeString feature); + + /// Returns a list of features supported by the renderer. + public Result getFeatures(NativeString *outFeatures, Size bufferSize, GfxCount *outFeatureCount); + + public Result getFormatSupportedResourceStates(Format format, ResourceStateSet *outStates); + + public Result getSlangSession(NativeRef* outSlangSession); + + public Result createTransientResourceHeap( + TransientResourceHeapDesc *desc, + out Optional outHeap); + + /// 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); + /// + public Result createTextureResource( + TextureResourceDesc* desc, + SubresourceData *initData, + out ITextureResource outResource); + + public Result createTextureFromNativeHandle( + InteropHandle handle, + TextureResourceDesc* srcDesc, + out ITextureResource outResource); + + public Result createTextureFromSharedHandle( + InteropHandle handle, + TextureResourceDesc *srcDesc, + Size size, + out ITextureResource outResource); + + /// Create a buffer resource + public Result createBufferResource( + BufferResourceDesc* desc, + void *initData, + out Optional outResource); + + public Result createBufferFromNativeHandle( + InteropHandle handle, + BufferResourceDesc* srcDesc, + out IBufferResource outResource); + + public Result createBufferFromSharedHandle( + InteropHandle handle, + BufferResourceDesc* srcDesc, + out IBufferResource outResource); + + public Result createSamplerState(SamplerStateDesc* desc, out ISamplerState outSampler); + + public Result createTextureView( + ITextureResource texture, ResourceViewDesc* desc, out IResourceView outView); + + public Result createBufferView( + IBufferResource buffer, + Optional counterBuffer, + ResourceViewDesc* desc, + out Optional outView); + + public Result createFramebufferLayout(FramebufferLayoutDesc* desc, out IFramebufferLayout outFrameBuffer); + + public Result createFramebuffer(FramebufferDesc* desc, out IFramebuffer outFrameBuffer); + + public Result createRenderPassLayout( + RenderPassLayoutDesc* desc, + out IRenderPassLayout outRenderPassLayout); + + public Result createSwapchain( + SwapchainDesc* desc, WindowHandle window, out ISwapchain outSwapchain); + + public Result createInputLayout( + InputLayoutDesc* desc, out IInputLayout outLayout); + + public Result createCommandQueue(CommandQueueDesc* desc, out Optional outQueue); + + public Result createShaderObject( + slang::TypeReflection *type, + ShaderObjectContainerType container, + out IShaderObject outObject); + + public Result createMutableShaderObject( + slang::TypeReflection *type, + ShaderObjectContainerType container, + out IShaderObject outObject); + + public Result createShaderObjectFromTypeLayout( + slang::TypeLayoutReflection *typeLayout, out IShaderObject outObject); + + public Result createMutableShaderObjectFromTypeLayout( + slang::TypeLayoutReflection *typeLayout, out IShaderObject outObject); + + public Result createMutableRootShaderObject( + IShaderProgram program, + out IShaderObject outObject); + + public Result createShaderTable(ShaderTableDesc* desc, out IShaderTable outTable); + + public Result createProgram( + void *desc, + out IShaderProgram outProgram, + out slang::ISlangBlob outDiagnosticBlob); + + public Result createProgram2( + ShaderProgramDesc2 *desc, + out Optional outProgram, + out Optional outDiagnosticBlob); + + public Result createGraphicsPipelineState( + GraphicsPipelineStateDesc *desc, + out Optional outState); + + public Result createComputePipelineState( + ComputePipelineStateDesc* desc, + out Optional outState); + + public Result createRayTracingPipelineState( + RayTracingPipelineStateDesc *desc, out Optional outState); + + /// Read back texture resource and stores the result in `outBlob`. + public Result readTextureResource( + ITextureResource resource, + ResourceState state, + out slang::ISlangBlob outBlob, + out Size outRowPitch, + out Size outPixelSize); + + public Result readBufferResource( + IBufferResource buffer, + Offset offset, + Size size, + out Optional outBlob); + + /// Get the type of this renderer + public DeviceInfo* getDeviceInfo(); + + public Result createQueryPool( + QueryPoolDesc* desc, out IQueryPool outPool); + + public Result getAccelerationStructurePrebuildInfo( + AccelerationStructureBuildInputs* buildInputs, + out AccelerationStructurePrebuildInfo outPrebuildInfo); + + public Result createAccelerationStructure( + AccelerationStructureCreateDesc* desc, + out IAccelerationStructure outView); + + public Result createFence(FenceDesc* desc, out IFence outFence); + + /// Wait on the host for the fences to signals. + /// `timeout` is in nanoseconds, can be set to `kTimeoutInfinite`. + public Result waitForFences( + GfxCount fenceCount, + NativeRef* fences, + uint64_t *values, + bool waitForAll, + uint64_t timeout); + + public Result getTextureAllocationInfo( + TextureResourceDesc* desc, out Size outSize, out Size outAlignment); + + public Result getTextureRowAlignment(out Size outAlignment); +}; + +public struct ShaderCacheStats +{ + public GfxCount hitCount; + public GfxCount missCount; + public GfxCount entryCount; +}; + +[COM("715bdf26-5135-11eb-AE93-02-42-AC-13-00-02")] +public interface IShaderCache +{ + public Result clearShaderCache(); + public Result getShaderCacheStats(out ShaderCacheStats outStats); + public Result resetShaderCacheStats(); +}; + +#define SLANG_GFX_IMPORT [DllImport("gfx")] +/// Checks if format is compressed +SLANG_GFX_IMPORT public bool gfxIsCompressedFormat(Format format); + +/// Checks if format is typeless +SLANG_GFX_IMPORT public bool gfxIsTypelessFormat(Format format); + +/// Gets information about the format +SLANG_GFX_IMPORT public Result gfxGetFormatInfo(Format format, FormatInfo *outInfo); + +/// Given a type returns a function that can conpublic struct it, or nullptr if there isn't one +SLANG_GFX_IMPORT public Result gfxCreateDevice(const Ptr desc, out Optional outDevice); + +/// Reports current set of live objects in gfx. +/// Currently this only calls D3D's ReportLiveObjects. +SLANG_GFX_IMPORT public Result gfxReportLiveObjects(); + +/// 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_IMPORT public Result gfxSetDebugCallback(IDebugCallback callback); + +/// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are valid. +SLANG_GFX_IMPORT public void gfxEnableDebugLayer(); + +SLANG_GFX_IMPORT public NativeString gfxGetDeviceTypeName(DeviceType type); + +public bool succeeded(Result code) +{ + return code >= 0; +} + +} diff --git a/lib/All/slang/bin/slang.slang b/lib/All/slang/bin/slang.slang new file mode 100644 index 0000000..75fa8a0 --- /dev/null +++ b/lib/All/slang/bin/slang.slang @@ -0,0 +1,446 @@ +public namespace slang +{ + +public typedef int32_t Result; +public typedef uint64_t Size; +public typedef int64_t Int; +public typedef uint64_t UInt; + +/*! +@brief Severity of a diagnostic generated by the compiler. +Values come from the enum below, with higher values representing more severe +conditions, and all values >= SLANG_SEVERITY_ERROR indicating compilation +failure. +*/ +public enum SlangSeverity +{ + SLANG_SEVERITY_DISABLED = 0, /**< A message that is disabled, filtered out. */ + 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. */ +}; + +public enum SlangDiagnosticFlags +{ + SLANG_DIAGNOSTIC_FLAG_VERBOSE_PATHS = 0x01, + SLANG_DIAGNOSTIC_FLAG_TREAT_WARNINGS_AS_ERRORS = 0x02 +}; + +public enum SlangBindableResourceType +{ + SLANG_NON_BINDABLE = 0, + SLANG_TEXTURE, + SLANG_SAMPLER, + SLANG_UNIFORM_BUFFER, + SLANG_STORAGE_BUFFER, +}; + +public enum SlangCompileTarget +{ + SLANG_TARGET_UNKNOWN, + SLANG_TARGET_NONE, + SLANG_GLSL, + SLANG_GLSL_VULKAN, //< deprecated: just use `SLANG_GLSL` + SLANG_GLSL_VULKAN_ONE_DESC, //< deprecated + SLANG_HLSL, + SLANG_SPIRV, + SLANG_SPIRV_ASM, + SLANG_DXBC, + SLANG_DXBC_ASM, + SLANG_DXIL, + SLANG_DXIL_ASM, + SLANG_C_SOURCE, ///< The C language + SLANG_CPP_SOURCE, ///< C++ code for shader kernels. + SLANG_CPP_PYTORCH_BINDING, + 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_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, ///< + SLANG_CPP_HEADER, ///< C++ header for shader kernels. + SLANG_CUDA_HEADER, ///< Cuda header + SLANG_TARGET_COUNT_OF, +}; + +/* A "container format" describes the way that the outputs +for multiple files, entry points, targets, etc. should be +combined into a single artifact for output. */ +public enum SlangContainerFormat +{ + /* Don't generate a container. */ + SLANG_CONTAINER_FORMAT_NONE, + + /* Generate a container in the `.slang-module` format, + which includes reflection information, compiled kernels, etc. */ + SLANG_CONTAINER_FORMAT_SLANG_MODULE, +}; + +public enum SlangPassThrough : int +{ + SLANG_PASS_THROUGH_NONE, + SLANG_PASS_THROUGH_FXC, + 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, + SLANG_PASS_THROUGH_COUNT_OF, +}; + +/* Defines an archive type used to holds a 'file system' type structure. */ +public enum SlangArchiveType : int +{ + SLANG_ARCHIVE_TYPE_UNDEFINED, + SLANG_ARCHIVE_TYPE_ZIP, + SLANG_ARCHIVE_TYPE_RIFF, ///< Riff container with no compression + SLANG_ARCHIVE_TYPE_RIFF_DEFLATE, + SLANG_ARCHIVE_TYPE_RIFF_LZ4, + SLANG_ARCHIVE_TYPE_COUNT_OF, +}; + +/*! +Flags to control compilation behavior. +*/ +public enum SlangCompileFlags +{ + /* Do as little mangling of names as possible, to try to preserve original names */ + 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, + + /* Obfuscate shader names on release products */ + SLANG_COMPILE_FLAG_OBFUSCATE = 1 << 5, + + /* 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, +}; + +/*! +@brief Flags to control code generation behavior of a compilation target */ +public enum SlangTargetFlags +{ + None = 0, + + /* When compiling for a D3D Shader Model 5.1 or higher target, allocate + distinct register spaces for parameter blocks. + + @deprecated This behavior is now enabled unconditionally. + */ + SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES = 1 << 4, + + /* When set, will generate target code that contains all entrypoints defined + in the input source or specified via the `spAddEntryPoint` function in a + single output module (library/source file). + */ + SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM = 1 << 8, + + /* When set, will dump out the IR between intermediate compilation steps.*/ + SLANG_TARGET_FLAG_DUMP_IR = 1 << 9, + + /* When set, will generate SPIRV directly instead of going through glslang. */ + SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY = 1 << 10, +}; + +/*! +@brief Options to control floating-point precision guarantees for a target. +*/ +public enum SlangFloatingPointMode +{ + SLANG_FLOATING_POINT_MODE_DEFAULT = 0, + SLANG_FLOATING_POINT_MODE_FAST, + SLANG_FLOATING_POINT_MODE_PRECISE, +}; + +/*! +@brief Options to control emission of `#line` directives +*/ +public enum SlangLineDirectiveMode +{ + 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 */ +}; + +public enum SlangSourceLanguage : int +{ + SLANG_SOURCE_LANGUAGE_UNKNOWN, + SLANG_SOURCE_LANGUAGE_SLANG, + SLANG_SOURCE_LANGUAGE_HLSL, + SLANG_SOURCE_LANGUAGE_GLSL, + SLANG_SOURCE_LANGUAGE_C, + SLANG_SOURCE_LANGUAGE_CPP, + SLANG_SOURCE_LANGUAGE_CUDA, + SLANG_SOURCE_LANGUAGE_COUNT_OF, +}; + +public enum SlangProfileID +{ + SLANG_PROFILE_UNKNOWN, +}; + +public enum SlangCapabilityID +{ + SLANG_CAPABILITY_UNKNOWN = 0, +}; + +public enum SlangMatrixLayoutMode +{ + SLANG_MATRIX_LAYOUT_MODE_UNKNOWN = 0, + SLANG_MATRIX_LAYOUT_ROW_MAJOR, + SLANG_MATRIX_LAYOUT_COLUMN_MAJOR, +}; + +public enum SlangStage +{ + SLANG_STAGE_NONE, + SLANG_STAGE_VERTEX, + SLANG_STAGE_HULL, + SLANG_STAGE_DOMAIN, + SLANG_STAGE_GEOMETRY, + SLANG_STAGE_FRAGMENT, + SLANG_STAGE_COMPUTE, + SLANG_STAGE_RAY_GENERATION, + SLANG_STAGE_INTERSECTION, + SLANG_STAGE_ANY_HIT, + SLANG_STAGE_CLOSEST_HIT, + SLANG_STAGE_MISS, + SLANG_STAGE_CALLABLE, + SLANG_STAGE_MESH, + SLANG_STAGE_AMPLIFICATION, +}; + +public enum SlangDebugInfoLevel +{ + 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. */ +}; + +public enum SlangOptimizationLevel +{ + 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 */ +}; +public enum SlangTypeKind +{ + NONE, + STRUCT, + ARRAY, + MATRIX, + VECTOR, + SCALAR, + CONSTANT_BUFFER, + RESOURCE, + SAMPLER_STATE, + TEXTURE_BUFFER, + SHADER_STORAGE_BUFFER, + PARAMETER_BLOCK, + GENERIC_TYPE_PARAMETER, + INTERFACE, + OUTPUT_STREAM, + SPECIALIZED, + FEEDBACK, + COUNT, +}; + +public enum SlangScalarType +{ + NONE, + VOID, + BOOL, + INT32, + UINT32, + INT64, + UINT64, + FLOAT16, + FLOAT32, + FLOAT64, + INT8, + UINT8, + INT16, + UINT16, +}; + +public struct TypeReflection +{ +}; + +public enum CompileStdLibFlags +{ + WriteDocumentation = 0x1, +}; + +[COM("8BA5FB08-5195-40e2-AC58-0D-98-9C-3A-01-02")] +public interface ISlangBlob +{ + public void *getBufferPointer(); + public Size getBufferSize(); +}; + +/** Description of a code generation target. + */ +public struct TargetDesc +{ + /** The size of this structure, in bytes. + */ + public Size structureSize = 40; + + /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.) + */ + public SlangCompileTarget format = SlangCompileTarget.SLANG_TARGET_UNKNOWN; + + /** The compilation profile supported by the target (e.g., "Shader Model 5.1") + */ + public SlangProfileID profile = SlangProfileID.SLANG_PROFILE_UNKNOWN; + + /** Flags for the code generation target. Currently unused. */ + public SlangTargetFlags flags = SlangTargetFlags.None; + + /** Default mode to use for floating-point operations on the target. + */ + public SlangFloatingPointMode floatingPointMode = SlangFloatingPointMode.SLANG_FLOATING_POINT_MODE_DEFAULT; + + /** Optimization level to use for the target. + */ + public SlangOptimizationLevel optimizationLevel = SlangOptimizationLevel.SLANG_OPTIMIZATION_LEVEL_DEFAULT; + + /** The line directive mode for output source code. + */ + public SlangLineDirectiveMode lineDirectiveMode = SlangLineDirectiveMode.SLANG_LINE_DIRECTIVE_MODE_DEFAULT; + + /** Whether to force `scalar` layout for glsl shader storage buffers. + */ + public bool forceGLSLScalarBufferLayout = false; +}; + +public enum SessionFlags +{ + kSessionFlags_None = 0 +}; + +public struct PreprocessorMacroDesc +{ + public NativeString name; + public NativeString value; +}; + +public struct SessionDesc +{ + /** The size of this structure, in bytes. + */ + public Size structureSize = 72; + + /** Code generation targets to include in the session. + */ + public TargetDesc *targets = nullptr; + public Int targetCount = 0; + + /** Flags to configure the session. + */ + public SessionFlags flags = SessionFlags.kSessionFlags_None; + + /** Default layout to assume for variables with matrix types. + */ + public SlangMatrixLayoutMode defaultMatrixLayoutMode = SlangMatrixLayoutMode.SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + /** Paths to use when searching for `#include`d or `import`ed files. + */ + public NativeString *searchPaths = nullptr; + public Int searchPathCount = 0; + + public PreprocessorMacroDesc *preprocessorMacros = nullptr; + public Int preprocessorMacroCount = 0; + + public void *fileSystem = nullptr; +}; + +/** A global session for interaction with the Slang library. + +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). + +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. +*/ +[COM("c140b5fd-0c78-452e-ba7c-1a-1e-70-c7-f7-1c")] +public interface IGlobalSession +{ +}; + +public 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. +*/ +[COM("67618701-d116-468f-ab3b-47-4b-ed-ce-0e-3d")] +public interface ISession +{ +}; + +[COM("5bc42be8-5c50-4929-9e5e-d15e7c24015f")] +public interface IComponentType +{ +} + +public struct TypeLayoutReflection { } + +/** The kind of specialization argument. */ +public enum class SpecializationArgKind : int32_t +{ + Unknown, /**< An invalid specialization argument. */ + Type, /**< Specialize to a type. */ +}; + +public struct SpecializationArg +{ + public SpecializationArgKind kind; + /** A type specialization argument, used for `Kind::Type`. */ + public TypeReflection *type; +} + +} diff --git a/lib/All/slang/bin/slangc b/lib/All/slang/bin/slangc new file mode 100755 index 0000000..cf3ab53 Binary files /dev/null and b/lib/All/slang/bin/slangc differ diff --git a/lib/All/slang/bin/slangd b/lib/All/slang/bin/slangd new file mode 100755 index 0000000..90f1930 Binary files /dev/null and b/lib/All/slang/bin/slangd differ diff --git a/lib/All/slang/bin/slangi b/lib/All/slang/bin/slangi new file mode 100755 index 0000000..21766d7 Binary files /dev/null and b/lib/All/slang/bin/slangi differ diff --git a/lib/All/slang/include/slang-com-helper.h b/lib/All/slang/include/slang-com-helper.h new file mode 100644 index 0000000..fa3c27f --- /dev/null +++ b/lib/All/slang/include/slang-com-helper.h @@ -0,0 +1,191 @@ +#ifndef SLANG_COM_HELPER_H +#define SLANG_COM_HELPER_H + +/** \file slang-com-helper.h + */ + +#include "slang.h" + +#include +#include +#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 */ +#ifndef SLANG_HANDLE_RESULT_FAIL + #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 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; \ + } \ + } +//! 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; \ + } \ + } + +/* !!!!!!!!!!!!!!!!!!!!!!! C++ helpers !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ + +#if defined(__cplusplus) +namespace Slang +{ + +// Alias SlangResult to Slang::Result +typedef SlangResult Result; +// Alias SlangUUID to Slang::Guid +typedef SlangUUID Guid; + +} // namespace Slang + +// Operator == and != for Guid/SlangUUID + +SLANG_FORCE_INLINE bool operator==(const Slang::Guid& aIn, const Slang::Guid& bIn) +{ + return aIn.data1 == bIn.data1 && aIn.data2 == bIn.data2 && aIn.data3 == bIn.data3 && + std::equal(aIn.data4, aIn.data4 + std::size(aIn.data4), bIn.data4); +} + +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() SLANG_OVERRIDE \ + { \ + return ++m_refCount; \ + } + + #define SLANG_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \ + { \ + --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 + +#endif // defined(__cplusplus) + +#endif diff --git a/lib/All/slang/include/slang-com-ptr.h b/lib/All/slang/include/slang-com-ptr.h new file mode 100644 index 0000000..e9d211d --- /dev/null +++ b/lib/All/slang/include/slang-com-ptr.h @@ -0,0 +1,210 @@ +#ifndef SLANG_COM_PTR_H +#define SLANG_COM_PTR_H + +#include "slang-com-helper.h" + +#include +#include + +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 + +\code +Void doSomething(ID3D12Resource** resources, IndexT numResources); +// ... +ComPtr resources[3]; +doSomething(resources[0].readRef(), SLANG_COUNT_OF(resource)); +\endcode + +A more common scenario writing to the pointer + +\code +IUnknown* unk = ...; + +ComPtr resource; +Result res = unk->QueryInterface(resource.writeRef()); +\endcode +*/ + +// Enum to force initializing as an attach (without adding a reference) +enum InitAttach +{ + INIT_ATTACH +}; + +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) + { + } + +#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; + } +#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); + +protected: + /// 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; +#endif + + T* m_ptr; +}; + +//---------------------------------------------------------------------------- +template +void ComPtr::setNull() +{ + if (m_ptr) + { + ((Ptr)m_ptr)->release(); + m_ptr = nullptr; + } +} +//---------------------------------------------------------------------------- +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; +} +//---------------------------------------------------------------------------- +template +T* ComPtr::operator=(T* ptr) +{ + if (ptr) + ((Ptr)ptr)->addRef(); + if (m_ptr) + ((Ptr)m_ptr)->release(); + m_ptr = ptr; + return m_ptr; +} +//---------------------------------------------------------------------------- +template +void ComPtr::swap(ThisType& rhs) +{ + T* tmp = m_ptr; + m_ptr = rhs.m_ptr; + rhs.m_ptr = tmp; +} + +} // namespace Slang + +#endif // SLANG_COM_PTR_H diff --git a/lib/All/slang/include/slang-cpp-host-prelude.h b/lib/All/slang/include/slang-cpp-host-prelude.h new file mode 100644 index 0000000..66f7405 --- /dev/null +++ b/lib/All/slang/include/slang-cpp-host-prelude.h @@ -0,0 +1,65 @@ +#ifndef SLANG_CPP_HOST_PRELUDE_H +#define SLANG_CPP_HOST_PRELUDE_H + +#include +#include +#include + +#define SLANG_COM_PTR_ENABLE_REF_OPERATOR 1 + +#include "../source/slang-rt/slang-rt.h" +#include "slang-com-ptr.h" +#include "slang-cpp-types.h" + +#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 +#endif // SLANG_LLVM + +// Is intptr_t not equal to equal-width sized integer type? +#if defined(__APPLE__) +#define SLANG_INTPTR_TYPE_IS_DISTINCT 1 +#else +#define SLANG_INTPTR_TYPE_IS_DISTINCT 0 +#endif + +#if defined(_MSC_VER) +#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 } +#else +#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...); + +#endif diff --git a/lib/All/slang/include/slang-cpp-prelude.h b/lib/All/slang/include/slang-cpp-prelude.h new file mode 100644 index 0000000..8a90f4a --- /dev/null +++ b/lib/All/slang/include/slang-cpp-prelude.h @@ -0,0 +1,333 @@ +#ifndef SLANG_CPP_PRELUDE_H +#define SLANG_CPP_PRELUDE_H + +// Because the signature of isnan, isfinite, and is isinf changed in C++, we use the macro +// 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 +#endif // SLANG_LLVM + +// Is intptr_t not equal to equal-width sized integer type? +#if defined(__APPLE__) +#define SLANG_INTPTR_TYPE_IS_DISTINCT 1 +#else +#define SLANG_INTPTR_TYPE_IS_DISTINCT 0 +#endif + +#if defined(_MSC_VER) +#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 } +#else +#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 +#define SLANG_PRELUDE_EXPORT_END SLANG_PRELUDE_EXTERN_C_END + +#ifndef INFINITY +// Must overflow for double +#define INFINITY float(1e+300 * 1e+300) +#endif + +#ifndef SLANG_INFINITY +#define SLANG_INFINITY INFINITY +#endif + +// Detect the compiler type + +#ifndef 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 +#endif /* SLANG_COMPILER */ + +/* +The following section attempts to detect the target platform being compiled for. + +If an application defines `SLANG_PLATFORM` before including this header, +they take responsibility for setting any compiler-dependent macros +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__) && !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 +#endif /* SLANG_PLATFORM */ + +/* Shorthands for "families" of compilers/platforms */ +#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC) +#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 */ + +// GCC Specific +#if SLANG_GCC_FAMILY + +#if INTPTR_MAX == INT64_MAX +#define SLANG_64BIT 1 +#else +#define SLANG_64BIT 0 +#endif + +#define SLANG_BREAKPOINT(id) __builtin_trap() + +// 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) +#endif // SLANG_GCC_FAMILY + +// Microsoft VC specific +#if SLANG_VC + +#define SLANG_BREAKPOINT(id) __debugbreak(); + +#endif // SLANG_VC + +// Default impls + +#ifndef SLANG_OFFSET_OF +#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)); +#endif + +// If slang.h has been included we don't need any of these definitions +#ifndef SLANG_H + +/* 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 +#endif +#ifndef 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 +#endif +#ifndef SLANG_MCALL +#define SLANG_MCALL SLANG_STDCALL +#endif + +#ifndef SLANG_FORCE_INLINE +#define SLANG_FORCE_INLINE inline +#endif + +// TODO(JS): Should these be in slang-cpp-types.h? +// They are more likely to clash with slang.h + +struct SlangUUID +{ + uint32_t data1; + uint16_t data2; + uint16_t data3; + 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 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; \ + } +#endif // SLANG_H + +// Includes + +#include "slang-cpp-scalar-intrinsics.h" +#include "slang-cpp-types.h" + +// TODO(JS): Hack! Output C++ code from slang can copy uninitialized variables. +#if defined(_MSC_VER) +#pragma warning(disable : 4700) +#endif + +#ifndef SLANG_UNROLL +#define SLANG_UNROLL +#endif + +#endif diff --git a/lib/All/slang/include/slang-cpp-scalar-intrinsics.h b/lib/All/slang/include/slang-cpp-scalar-intrinsics.h new file mode 100644 index 0000000..7f87796 --- /dev/null +++ b/lib/All/slang/include/slang-cpp-scalar-intrinsics.h @@ -0,0 +1,1354 @@ +#ifndef SLANG_PRELUDE_SCALAR_INTRINSICS_H +#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 +#endif + +#ifndef SLANG_FORCE_INLINE +#define SLANG_FORCE_INLINE inline +#endif + +#ifdef SLANG_PRELUDE_NAMESPACE +namespace SLANG_PRELUDE_NAMESPACE +{ +#endif + +#ifndef SLANG_PRELUDE_PI +#define SLANG_PRELUDE_PI 3.14159265358979323846 +#endif + +union Union32 +{ + uint32_t u; + int32_t i; + float f; +}; + +union Union64 +{ + uint64_t u; + int64_t i; + double d; +}; + +// 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; +} + +// ----------------------------- F32 ----------------------------------------- + +// Helpers +SLANG_FORCE_INLINE float F32_calcSafeRadians(float radians); + +#ifdef SLANG_LLVM + +SLANG_PRELUDE_EXTERN_C_START + +// Unary +float F32_ceil(float f); +float F32_floor(float f); +float F32_round(float f); +float F32_sin(float f); +float F32_cos(float f); +float F32_tan(float f); +float F32_asin(float f); +float F32_acos(float f); +float F32_atan(float f); +float F32_sinh(float f); +float F32_cosh(float f); +float F32_tanh(float f); +float F32_asinh(float f); +float F32_acosh(float f); +float F32_atanh(float f); +float F32_log2(float f); +float F32_log(float f); +float F32_log10(float f); +float F32_exp2(float f); +float F32_exp(float f); +float F32_abs(float f); +float F32_trunc(float f); +float F32_sqrt(float f); + +bool F32_isnan(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; +} +float F32_pow(float a, float b); +float F32_fmod(float a, float b); +float F32_remainder(float a, float b); +float F32_atan2(float a, float b); + +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_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_asinh(float f) +{ + return ::asinhf(f); +} +SLANG_FORCE_INLINE float F32_acosh(float f) +{ + return ::acoshf(f); +} +SLANG_FORCE_INLINE float F32_atanh(float f) +{ + return ::atanhf(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_frexp(float x, int* e) +{ + return ::frexpf(x, e); +} + +SLANG_FORCE_INLINE float F32_modf(float x, float* ip) +{ + return ::modff(x, ip); +} + +// Ternary +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)); + // 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)); +} + +SLANG_FORCE_INLINE float F32_rsqrt(float f) +{ + return 1.0f / F32_sqrt(f); +} +SLANG_FORCE_INLINE int F32_sign(float f) +{ + return (f == 0.0f) ? 0 : ((f < 0.0f) ? -1 : 1); +} +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; +} + +// ----------------------------- F64 ----------------------------------------- + +SLANG_FORCE_INLINE double F64_calcSafeRadians(double radians); + +#ifdef SLANG_LLVM + +SLANG_PRELUDE_EXTERN_C_START + +// Unary +double F64_ceil(double f); +double F64_floor(double f); +double F64_round(double f); +double F64_sin(double f); +double F64_cos(double f); +double F64_tan(double f); +double F64_asin(double f); +double F64_acos(double f); +double F64_atan(double f); +double F64_sinh(double f); +double F64_cosh(double f); +double F64_tanh(double f); +double F64_asinh(double f); +double F64_acosh(double f); +double F64_atanh(double f); +double F64_log2(double f); +double F64_log(double f); +double F64_log10(double f); +double F64_exp2(double f); +double F64_exp(double f); +double F64_abs(double f); +double F64_trunc(double f); +double F64_sqrt(double f); + +bool F64_isnan(double f); +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; +} +double F64_pow(double a, double b); +double F64_fmod(double a, double b); +double F64_remainder(double a, double b); +double F64_atan2(double a, double b); + +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_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); +} + +// 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_frexp(double x, int* e) +{ + return ::frexp(x, e); +} + +SLANG_FORCE_INLINE double F64_modf(double x, double* ip) +{ + return ::modf(x, ip); +} + +// Ternary +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 int F64_sign(double f) +{ + return (f == 0.0) ? 0 : ((f < 0.0) ? -1 : 1); +} +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) +{ + Union64 u; + u.d = d; + *low = uint32_t(u.u); + *hi = uint32_t(u.u >> 32); +} + +SLANG_FORCE_INLINE void F64_asint(double d, int32_t* low, int32_t* hi) +{ + Union64 u; + u.d = d; + *low = int32_t(u.u); + *hi = int32_t(u.u >> 32); +} + +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)); + // 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)); +} + +// ----------------------------- F16 ----------------------------------------- + +// This impl is based on FloatToHalf that is in Slang codebase +SLANG_FORCE_INLINE uint32_t f32tof16(const float value) +{ + const uint32_t inBits = _bitCastFloatToUInt(value); + + // bits initially set to just the sign bit + uint32_t bits = (inBits >> 16) & 0x8000; + // Mantissa can't be used as is, as it holds last bit, for rounding. + uint32_t m = (inBits >> 12) & 0x07ff; + uint32_t e = (inBits >> 23) & 0xff; + + if (e < 103) + { + // It's zero + return bits; + } + 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. + + // 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. + return bits | 0x7c00u; + } + if (e < 113) + { + m |= 0x0800u; + bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1); + return bits; + } + bits |= ((e - 112) << 10) | (m >> 1); + bits += m & 1; + return bits; +} + +static const float g_f16tof32Magic = _bitCastIntToFloat((127 + (127 - 15)) << 23); + +SLANG_FORCE_INLINE float f16tof32(const uint32_t value) +{ + const uint32_t sign = (value & 0x8000) << 16; + uint32_t exponent = (value & 0x7c00) >> 10; + uint32_t mantissa = (value & 0x03ff); + + if (exponent == 0) + { + // If mantissa is 0 we are done, as output is 0. + // If it's not zero we must have a denormal. + if (mantissa) + { + // We have a denormal so use the magic to do exponent adjust + return _bitCastIntToFloat(sign | ((value & 0x7fff) << 13)) * g_f16tof32Magic; + } + } + else + { + // 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 + // + // 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)); +} + +#ifndef SLANG_LLVM +#if __cplusplus >= 202302L +#include // C++23 +#else +// Define __STDC_WANT_IEC_60559_TYPES_EXT__ for compilers with reliable _Float16 support: +// - Clang 15+ +// - GCC 12+ +#if (defined(__clang__) && __clang_major__ >= 15) || (defined(__GNUC__) && __GNUC__ >= 12) +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +#include +#endif // __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif // (defined(__clang__) && __clang_major__ >= 15) || (defined(__GNUC__) && __GNUC__ >= 12) +#endif // C++23 + +#ifdef FLT16_MIN +typedef _Float16 half; +#elif __STDCPP_FLOAT16_T__ == 1 +typedef std::float16_t half; +#else +uint32_t f32tof16(const float value); +float f16tof32(const uint32_t value); +struct half +{ + uint16_t data; + + half() = default; + explicit half(float f) { store(f); } + + SLANG_FORCE_INLINE void store(float f) { data = f32tof16(f); } + SLANG_FORCE_INLINE float load() const { return f16tof32(data); } + + half operator+(half other) const { return half(load() + other.load()); } + half operator-(half other) const { return half(load() - other.load()); } + half operator*(half other) const { return half(load() * other.load()); } + half operator/(half other) const { return half(load() / other.load()); } + half& operator+=(half other) + { + store(load() + other.load()); + return *this; + } + half& operator-=(half other) + { + store(load() - other.load()); + return *this; + } + half& operator*=(half other) + { + store(load() * other.load()); + return *this; + } + half& operator/=(half other) + { + store(load() / other.load()); + return *this; + } + + bool operator<(half other) const { return load() < other.load(); } + bool operator>(half other) const { return load() > other.load(); } + bool operator<=(half other) const { return load() <= other.load(); } + bool operator>=(half other) const { return load() >= other.load(); } + bool operator==(half other) const { return load() == other.load(); } + bool operator!=(half other) const { return load() != other.load(); } + + explicit operator float() const { return load(); } +}; +#endif + +half U16_ashalf(uint16_t x); + +union Union16 +{ + uint16_t u; + int16_t i; + half h; +}; + +SLANG_FORCE_INLINE uint16_t F16_asuint(half h) +{ + Union16 u; + u.h = h; + return u.u; +} + +SLANG_FORCE_INLINE int16_t F16_asint(half h) +{ + Union16 u; + u.h = h; + return u.i; +} + +SLANG_FORCE_INLINE half F16_ceil(half f) +{ + return half(F32_ceil(float(f))); +} + +SLANG_FORCE_INLINE half F16_floor(half f) +{ + return half(F32_floor(float(f))); +} + +SLANG_FORCE_INLINE half F16_round(half f) +{ + return half(F32_round(float(f))); +} + +SLANG_FORCE_INLINE half F16_sin(half f) +{ + return half(F32_sin(float(f))); +} + +SLANG_FORCE_INLINE half F16_cos(half f) +{ + return half(F32_cos(float(f))); +} + +SLANG_FORCE_INLINE half F16_tan(half f) +{ + return half(F32_tan(float(f))); +} + +SLANG_FORCE_INLINE half F16_asin(half f) +{ + return half(F32_asin(float(f))); +} + +SLANG_FORCE_INLINE half F16_acos(half f) +{ + return half(F32_acos(float(f))); +} + +SLANG_FORCE_INLINE half F16_atan(half f) +{ + return half(F32_atan(float(f))); +} + +SLANG_FORCE_INLINE half F16_sinh(half f) +{ + return half(F32_sinh(float(f))); +} + +SLANG_FORCE_INLINE half F16_cosh(half f) +{ + return half(F32_cosh(float(f))); +} + +SLANG_FORCE_INLINE half F16_tanh(half f) +{ + return half(F32_tanh(float(f))); +} + +SLANG_FORCE_INLINE half F16_asinh(half f) +{ + return half(F32_asinh(float(f))); +} + +SLANG_FORCE_INLINE half F16_acosh(half f) +{ + return half(F32_acosh(float(f))); +} + +SLANG_FORCE_INLINE half F16_atanh(half f) +{ + return half(F32_atanh(float(f))); +} + +SLANG_FORCE_INLINE half F16_log2(half f) +{ + return half(F32_log2(float(f))); +} + +SLANG_FORCE_INLINE half F16_log(half f) +{ + return half(F32_log(float(f))); +} + +SLANG_FORCE_INLINE half F16_log10(half f) +{ + return half(F32_log10(float(f))); +} + +SLANG_FORCE_INLINE half F16_exp2(half f) +{ + return half(F32_exp2(float(f))); +} + +SLANG_FORCE_INLINE half F16_exp(half f) +{ + return half(F32_exp(float(f))); +} + +SLANG_FORCE_INLINE half F16_abs(half f) +{ + return U16_ashalf(F16_asuint(f) & 0x7FFF); +} + +SLANG_FORCE_INLINE half F16_trunc(half f) +{ + return half(F32_trunc(float(f))); +} + +SLANG_FORCE_INLINE half F16_sqrt(half f) +{ + return half(F32_sqrt(float(f))); +} + +SLANG_FORCE_INLINE bool F16_isnan(half f) +{ + uint16_t u = F16_asuint(f); + return (u & 0x7C00) == 0x7C00 && (u & 0x3FF) != 0; +} + +SLANG_FORCE_INLINE bool F16_isfinite(half f) +{ + uint16_t u = F16_asuint(f); + return (u & 0x7C00) != 0x7C00; +} + +SLANG_FORCE_INLINE bool F16_isinf(half f) +{ + uint16_t u = F16_asuint(f); + return (u & 0x7C00) == 0x7C00 && (u & 0x3FF) == 0; +} + +SLANG_FORCE_INLINE half F16_min(half a, half b) +{ + if (F16_isnan(a)) + return b; + if (F16_isnan(b)) + return a; + return a < b ? a : b; +} + +SLANG_FORCE_INLINE half F16_max(half a, half b) +{ + if (F16_isnan(a)) + return b; + if (F16_isnan(b)) + return a; + return a > b ? a : b; +} + +SLANG_FORCE_INLINE half F16_pow(half a, half b) +{ + return half(F32_pow(float(a), float(b))); +} + +SLANG_FORCE_INLINE half F16_fmod(half a, half b) +{ + return half(F32_fmod(float(a), float(b))); +} + +SLANG_FORCE_INLINE half F16_remainder(half a, half b) +{ + return half(F32_remainder(float(a), float(b))); +} + +SLANG_FORCE_INLINE half F16_atan2(half a, half b) +{ + return half(F32_atan2(float(a), float(b))); +} + +SLANG_FORCE_INLINE half F16_frexp(half x, int* e) +{ + return half(F32_frexp(float(x), e)); +} + +SLANG_FORCE_INLINE half F16_modf(half x, half* ip) +{ + float ipf; + float res = F32_modf(float(x), &ipf); + *ip = half(ipf); + return half(res); +} + +SLANG_FORCE_INLINE half F16_fma(half a, half b, half c) +{ + return half(F32_fma(float(a), float(b), float(c))); +} + +SLANG_FORCE_INLINE half F16_calcSafeRadians(half radians) +{ + // Put 0 to 2pi cycles to cycle around 0 to 1 + float a = float(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 half(a * float(SLANG_PRELUDE_PI * 2)); +} + +SLANG_FORCE_INLINE half F16_rsqrt(half f) +{ + return half(1.0f / F32_sqrt(float(f))); +} + +SLANG_FORCE_INLINE int F16_sign(half f) +{ + uint16_t u = F16_asuint(f); + if ((u & 0x7FFF) == 0) + return 0; + return (u & 0x8000) != 0 ? -1 : 1; +} + +SLANG_FORCE_INLINE half F16_frac(half h) +{ + float f = float(h); + return half(f - F32_floor(f)); +} + +// ----------------------------- U16 ----------------------------------------- +SLANG_FORCE_INLINE uint32_t U16_countbits(uint16_t v) +{ +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + return __builtin_popcount(uint32_t(v)); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + return __popcnt16(v); +#else + uint32_t c = 0; + while (v) + { + c++; + v &= v - 1; + } + return c; +#endif +} + +SLANG_FORCE_INLINE half U16_ashalf(uint16_t x) +{ + Union16 u; + u.u = x; + return u.h; +} + +// ----------------------------- I16 ----------------------------------------- +SLANG_FORCE_INLINE uint32_t I16_countbits(int16_t v) +{ + return U16_countbits(uint16_t(v)); +} + +// ----------------------------- U8 ----------------------------------------- +SLANG_FORCE_INLINE uint32_t U8_countbits(uint8_t v) +{ + // No native 8bit __popcnt yet, just cast and use 16bit variant + return U16_countbits(uint16_t(v)); +} + +// ----------------------------- I8 ----------------------------------------- +SLANG_FORCE_INLINE uint32_t I8_countbits(int16_t v) +{ + return U8_countbits(uint8_t(v)); +} + +// ----------------------------- U32 ----------------------------------------- + +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 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) +{ + Union64 u; + u.u = (uint64_t(hi) << 32) | low; + return u.d; +} + +SLANG_FORCE_INLINE uint32_t U32_countbits(uint32_t v) +{ +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + return __builtin_popcount(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + return __popcnt(v); +#else + uint32_t c = 0; + while (v) + { + c++; + v &= v - 1; + } + return c; +#endif +} + +SLANG_FORCE_INLINE uint32_t U32_firstbitlow(uint32_t v) +{ + if (v == 0) + return ~0u; + +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + // __builtin_ctz returns number of trailing zeros, which is the 0-based index of first set bit + return __builtin_ctz(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + // _BitScanForward returns 1 on success, 0 on failure, and sets index + unsigned long index; + return _BitScanForward(&index, v) ? index : ~0u; +#else + // Generic implementation - find first set bit + uint32_t result = 0; + while (result < 32 && !(v & (1u << result))) + result++; + return result; +#endif +} + +SLANG_FORCE_INLINE uint32_t U32_firstbithigh(uint32_t v) +{ + if (v == 0) + return ~0u; +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + // __builtin_clz returns number of leading zeros + // firstbithigh should return 0-based bit position of MSB + return 31 - __builtin_clz(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + // _BitScanReverse returns 1 on success, 0 on failure, and sets index + unsigned long index; + return _BitScanReverse(&index, v) ? index : ~0u; +#else + // Generic implementation - find highest set bit + int result = 31; + while (result >= 0 && !(v & (1u << result))) + result--; + return result; +#endif +} + +SLANG_FORCE_INLINE uint32_t U32_reversebits(uint32_t v) +{ + v = ((v >> 1) & 0x55555555u) | ((v & 0x55555555u) << 1); + v = ((v >> 2) & 0x33333333u) | ((v & 0x33333333u) << 2); + v = ((v >> 4) & 0x0F0F0F0Fu) | ((v & 0x0F0F0F0Fu) << 4); + v = ((v >> 8) & 0x00FF00FFu) | ((v & 0x00FF00FFu) << 8); + v = (v >> 16) | (v << 16); + return v; +} + +// ----------------------------- I32 ----------------------------------------- + +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 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); + return u.d; +} + +SLANG_FORCE_INLINE uint32_t I32_countbits(int32_t v) +{ + return U32_countbits(uint32_t(v)); +} + +SLANG_FORCE_INLINE uint32_t I32_firstbitlow(int32_t v) +{ + return U32_firstbitlow(uint32_t(v)); +} + +SLANG_FORCE_INLINE uint32_t I32_firstbithigh(int32_t v) +{ + if (v < 0) + v = ~v; + return U32_firstbithigh(uint32_t(v)); +} + +SLANG_FORCE_INLINE int32_t I32_reversebits(int32_t v) +{ + return U32_reversebits(int32_t(v)); +} + +// ----------------------------- U64 ----------------------------------------- + +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 uint32_t U64_countbits(uint64_t v) +{ +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + return uint32_t(__builtin_popcountll(v)); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + return uint32_t(__popcnt64(v)); +#else + uint32_t c = 0; + while (v) + { + c++; + v &= v - 1; + } + return c; +#endif +} + +SLANG_FORCE_INLINE uint32_t U64_firstbitlow(uint64_t v) +{ + if (v == 0) + return ~uint32_t(0); + +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + // __builtin_ctz returns number of trailing zeros, which is the 0-based index of first set bit + return __builtin_ctz(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + // _BitScanForward returns 1 on success, 0 on failure, and sets index + unsigned long index; + return _BitScanForward64(&index, v) ? index : ~uint32_t(0); +#else + // Generic implementation - find first set bit + uint32_t result = 0; + while (result < 64 && !(v & (uint64_t(1) << result))) + result++; + return result; +#endif +} + +SLANG_FORCE_INLINE uint32_t U64_firstbithigh(uint64_t v) +{ + if (v == 0) + return ~uint32_t(0); + +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) + // __builtin_clz returns number of leading zeros + // firstbithigh should return 0-based bit position of MSB + return 63 - __builtin_clz(v); +#elif SLANG_PROCESSOR_X86_64 && SLANG_VC + // _BitScanReverse returns 1 on success, 0 on failure, and sets index + unsigned long index; + return _BitScanReverse64(&index, v) ? index : ~uint32_t(0); +#else + // Generic implementation - find highest set bit + int result = 63; + while (result >= 0 && !(v & (uint64_t(1) << result))) + result--; + return result; +#endif +} + +SLANG_FORCE_INLINE uint64_t U64_reversebits(uint64_t v) +{ + v = ((v >> 1) & 0x5555555555555555ull) | ((v & 0x5555555555555555ull) << 1); + v = ((v >> 2) & 0x3333333333333333ull) | ((v & 0x3333333333333333ull) << 2); + v = ((v >> 4) & 0x0F0F0F0F0F0F0F0Full) | ((v & 0x0F0F0F0F0F0F0F0Full) << 4); + v = ((v >> 8) & 0x00FF00FF00FF00FFull) | ((v & 0x00FF00FF00FF00FFull) << 8); + v = ((v >> 16) & 0x0000FFFF0000FFFFull) | ((v & 0x0000FFFF0000FFFFull) << 16); + v = (v >> 32) | (v << 32); + return v; +} + +// ----------------------------- I64 ----------------------------------------- + +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 uint32_t I64_countbits(int64_t v) +{ + return U64_countbits(uint64_t(v)); +} + +SLANG_FORCE_INLINE uint32_t I64_firstbitlow(int64_t v) +{ + return U64_firstbitlow(uint64_t(v)); +} + +SLANG_FORCE_INLINE uint32_t I64_firstbithigh(int64_t v) +{ + if (v < 0) + v = ~v; + return U64_firstbithigh(uint64_t(v)); +} + +SLANG_FORCE_INLINE int64_t I64_reversebits(int64_t v) +{ + return int64_t(U64_reversebits(uint64_t(v))); +} + +// ----------------------------- UPTR ----------------------------------------- + +SLANG_FORCE_INLINE uintptr_t UPTR_abs(uintptr_t f) +{ + return f; +} + +SLANG_FORCE_INLINE uintptr_t UPTR_min(uintptr_t a, uintptr_t b) +{ + return a < b ? a : b; +} + +SLANG_FORCE_INLINE uintptr_t UPTR_max(uintptr_t a, uintptr_t b) +{ + return a > b ? a : b; +} + +// ----------------------------- IPTR ----------------------------------------- + +SLANG_FORCE_INLINE intptr_t IPTR_abs(intptr_t f) +{ + return (f < 0) ? -f : f; +} + +SLANG_FORCE_INLINE intptr_t IPTR_min(intptr_t a, intptr_t b) +{ + return a < b ? a : b; +} + +SLANG_FORCE_INLINE intptr_t IPTR_max(intptr_t a, intptr_t b) +{ + return a > b ? a : b; +} + +// ----------------------------- Interlocked --------------------------------- + +#if SLANG_LLVM + +#else // SLANG_LLVM + +#ifdef _WIN32 +#include +#endif + +SLANG_FORCE_INLINE void InterlockedAdd(uint32_t* dest, uint32_t value, uint32_t* oldValue) +{ +#ifdef _WIN32 + *oldValue = _InterlockedExchangeAdd((long*)dest, (long)value); +#else + *oldValue = __sync_fetch_and_add(dest, value); +#endif +} + +#endif // SLANG_LLVM + + +// ----------------------- fmod -------------------------- +SLANG_FORCE_INLINE float _slang_fmod(float x, float y) +{ + return F32_fmod(x, y); +} +SLANG_FORCE_INLINE double _slang_fmod(double x, double y) +{ + return F64_fmod(x, y); +} + +#ifdef SLANG_PRELUDE_NAMESPACE +} +#endif + +#endif diff --git a/lib/All/slang/include/slang-cpp-types-core.h b/lib/All/slang/include/slang-cpp-types-core.h new file mode 100644 index 0000000..5f2024a --- /dev/null +++ b/lib/All/slang/include/slang-cpp-types-core.h @@ -0,0 +1,712 @@ +#ifndef SLANG_PRELUDE_CPP_TYPES_CORE_H +#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 +#endif + +// Since we are using unsigned arithmatic care is need in this comparison. +// It is *assumed* that sizeInBytes >= elemSize. Which means (sizeInBytes >= elemSize) >= 0 +// Which means only a single test is needed + +// 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); + +// 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) +#else +#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) +#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) +#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) +#endif + +struct TypeInfo +{ + size_t typeSize; +}; + +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]; + } + + 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 +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]; + } + + T* data; + size_t count; +}; + +/* Constant buffers become a pointer to the contained type, so ConstantBuffer becomes T* in C++ + * code. + */ + +template +struct Vector; + +template +struct Vector +{ + T x; + const T& operator[](size_t /*index*/) const { return x; } + T& operator[](size_t /*index*/) { return x; } + operator T() const { return x; } + Vector() = default; + Vector(T scalar) { x = scalar; } + template + Vector(Vector other) + { + x = (T)other.x; + } + template + Vector(Vector other) + { + int minSize = 1; + if (otherSize < minSize) + minSize = otherSize; + for (int i = 0; i < minSize; i++) + (*this)[i] = (T)other[i]; + } +}; + +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 _x, T _y) + { + x = _x; + y = _y; + } + template + Vector(Vector other) + { + x = (T)other.x; + y = (T)other.y; + } + template + Vector(Vector other) + { + int minSize = 2; + if (otherSize < minSize) + minSize = otherSize; + for (int i = 0; i < minSize; i++) + (*this)[i] = (T)other[i]; + } +}; + +template +struct Vector +{ + T x, y, z; + 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 = scalar; } + Vector(T _x, T _y, T _z) + { + x = _x; + y = _y; + z = _z; + } + template + Vector(Vector other) + { + x = (T)other.x; + y = (T)other.y; + z = (T)other.z; + } + template + Vector(Vector other) + { + int minSize = 3; + if (otherSize < minSize) + minSize = otherSize; + for (int i = 0; i < minSize; i++) + (*this)[i] = (T)other[i]; + } +}; + +template +struct Vector +{ + T x, y, z, w; + + 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 _x, T _y, T _z, T _w) + { + x = _x; + y = _y; + z = _z; + w = _w; + } + template + Vector(Vector other) + { + int minSize = 4; + 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) +{ + Vector result; + for (int i = 0; i < N; i++) + { + result[i] = condition[i] ? v0[i] : v1[i]; + } + return result; +} + +template +SLANG_FORCE_INLINE T _slang_select(bool condition, T v0, T v1) +{ + return condition ? v0 : v1; +} + +template +SLANG_FORCE_INLINE T _slang_vector_get_element(Vector x, int index) +{ + return x[index]; +} + +template +SLANG_FORCE_INLINE const T* _slang_vector_get_element_ptr(const Vector* x, int index) +{ + return &((*const_cast*>(x))[index]); +} + +template +SLANG_FORCE_INLINE T* _slang_vector_get_element_ptr(Vector* x, int index) +{ + return &((*x)[index]); +} + +template +SLANG_FORCE_INLINE Vector _slang_vector_reshape(const Vector other) +{ + Vector result; + for (int i = 0; i < n; i++) + { + OtherT otherElement = T(0); + if (i < m) + otherElement = _slang_vector_get_element(other, i); + *_slang_vector_get_element_ptr(&result, i) = (T)otherElement; + } + return result; +} + +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 \ + 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, !) \ + 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, ==) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, !=) + +SLANG_INT_VECTOR_OPS(bool) +SLANG_INT_VECTOR_OPS(int) +SLANG_INT_VECTOR_OPS(int8_t) +SLANG_INT_VECTOR_OPS(int16_t) +SLANG_INT_VECTOR_OPS(int64_t) +SLANG_INT_VECTOR_OPS(uint) +SLANG_INT_VECTOR_OPS(uint8_t) +SLANG_INT_VECTOR_OPS(uint16_t) +SLANG_INT_VECTOR_OPS(uint64_t) +#if SLANG_INTPTR_TYPE_IS_DISTINCT +SLANG_INT_VECTOR_OPS(intptr_t) +SLANG_INT_VECTOR_OPS(uintptr_t) +#endif + +SLANG_FLOAT_VECTOR_OPS(float) +SLANG_FLOAT_VECTOR_OPS(double) + +#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; \ + } +SLANG_VECTOR_INT_NEG_OP(int) +SLANG_VECTOR_INT_NEG_OP(int8_t) +SLANG_VECTOR_INT_NEG_OP(int16_t) +SLANG_VECTOR_INT_NEG_OP(int64_t) +SLANG_VECTOR_INT_NEG_OP(uint) +SLANG_VECTOR_INT_NEG_OP(uint8_t) +SLANG_VECTOR_INT_NEG_OP(uint16_t) +SLANG_VECTOR_INT_NEG_OP(uint64_t) +#if SLANG_INTPTR_TYPE_IS_DISTINCT +SLANG_VECTOR_INT_NEG_OP(intptr_t) +SLANG_VECTOR_INT_NEG_OP(uintptr_t) +#endif + +#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; \ + } + +SLANG_FLOAT_VECTOR_MOD(float) +SLANG_FLOAT_VECTOR_MOD(double) +#undef SLANG_FLOAT_VECTOR_MOD +#undef SLANG_VECTOR_BINARY_OP +#undef SLANG_VECTOR_UNARY_OP +#undef SLANG_INT_VECTOR_OPS +#undef SLANG_FLOAT_VECTOR_OPS +#undef SLANG_VECTOR_INT_NEG_OP +#undef SLANG_FLOAT_VECTOR_MOD + +template +struct Matrix +{ + Vector rows[ROWS]; + const Vector& operator[](size_t index) const { return rows[index]; } + Vector& operator[](size_t index) { return rows[index]; } + Matrix() = default; + Matrix(T scalar) + { + for (int i = 0; i < ROWS; i++) + rows[i] = Vector(scalar); + } + Matrix(const Vector& row0) { rows[0] = row0; } + Matrix(const Vector& row0, const Vector& row1) + { + rows[0] = row0; + rows[1] = row1; + } + Matrix(const Vector& row0, const Vector& row1, const Vector& row2) + { + rows[0] = row0; + rows[1] = row1; + rows[2] = row2; + } + Matrix( + const Vector& row0, + const Vector& row1, + const Vector& row2, + const Vector& row3) + { + rows[0] = row0; + rows[1] = row1; + rows[2] = row2; + rows[3] = row3; + } + template + Matrix(const Matrix& other) + { + int minRow = ROWS; + int minCol = COLS; + 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; + } + 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; + } + 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; + } + } + 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; + } + 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; + } + } + 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; + } + 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; + } + 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; + } + } + 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; + } +}; + +#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; \ + } + +#define SLANG_MATRIX_BINARY_COMPARE_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; \ + } + +#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_BINARY_COMPARE_OP(T, >) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, <) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, >=) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, <=) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, ==) \ + SLANG_MATRIX_BINARY_COMPARE_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_UNARY_OP(T, -) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, >) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, <) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, >=) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, <=) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, ==) \ + SLANG_MATRIX_BINARY_COMPARE_OP(T, !=) +SLANG_INT_MATRIX_OPS(int) +SLANG_INT_MATRIX_OPS(int8_t) +SLANG_INT_MATRIX_OPS(int16_t) +SLANG_INT_MATRIX_OPS(int64_t) +SLANG_INT_MATRIX_OPS(uint) +SLANG_INT_MATRIX_OPS(uint8_t) +SLANG_INT_MATRIX_OPS(uint16_t) +SLANG_INT_MATRIX_OPS(uint64_t) +#if SLANG_INTPTR_TYPE_IS_DISTINCT +SLANG_INT_MATRIX_OPS(intptr_t) +SLANG_INT_MATRIX_OPS(uintptr_t) +#endif + +SLANG_FLOAT_MATRIX_OPS(float) +SLANG_FLOAT_MATRIX_OPS(double) + +#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) +#if SLANG_INTPTR_TYPE_IS_DISTINCT +SLANG_MATRIX_INT_NEG_OP(intptr_t) +SLANG_MATRIX_INT_NEG_OP(uintptr_t) +#endif + +#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; \ + } + +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 +#undef SLANG_INT_MATRIX_OPS +#undef SLANG_FLOAT_MATRIX_OPS +#undef SLANG_MATRIX_INT_NEG_OP +#undef SLANG_FLOAT_MATRIX_MOD + +template +TResult slang_bit_cast(TInput val) +{ + return *(TResult*)(&val); +} + +#endif diff --git a/lib/All/slang/include/slang-cpp-types.h b/lib/All/slang/include/slang-cpp-types.h new file mode 100644 index 0000000..26b45d5 --- /dev/null +++ b/lib/All/slang/include/slang-cpp-types.h @@ -0,0 +1,1364 @@ +#ifndef SLANG_PRELUDE_CPP_TYPES_H +#define SLANG_PRELUDE_CPP_TYPES_H + +#ifdef SLANG_PRELUDE_NAMESPACE +namespace SLANG_PRELUDE_NAMESPACE +{ +#endif + +#ifndef SLANG_FORCE_INLINE +#define SLANG_FORCE_INLINE inline +#endif + +#include "slang-cpp-types-core.h" + +typedef Vector float2; +typedef Vector float3; +typedef Vector float4; + +typedef Vector int2; +typedef Vector int3; +typedef Vector int4; + +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. +typedef size_t NonUniformResourceIndex; + +// ----------------------------- ResourceType ----------------------------------------- + +// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions +// Missing Load(_In_ int Location, _Out_ uint Status); + +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)); + } + + T* data; + size_t count; +}; + +template +struct StructuredBuffer +{ + SLANG_FORCE_INLINE T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + 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 +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]; + } + void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); } + + T* data; + size_t count; +}; + +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]; + } + void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); } + + T* data; + size_t count; +}; + +// Missing Load(_In_ int Location, _Out_ uint Status); +struct ByteAddressBuffer +{ + void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); } + uint32_t Load(size_t index) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + return data[index >> 2]; + } + 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]}; + } + 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]}; + } + 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]}; + } + template + T Load(size_t index) const + { + 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 +}; + +// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer +// 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 + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + return data[index >> 2]; + } + 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]}; + } + 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]}; + } + 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]}; + } + template + T Load(size_t index) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); + return *(const T*)(((const char*)data) + index); + } + + void Store(size_t index, uint32_t v) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + data[index >> 2] = v; + } + void Store2(size_t index, uint2 v) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); + const size_t dataIdx = index >> 2; + data[dataIdx + 0] = v.x; + data[dataIdx + 1] = v.y; + } + void Store3(size_t index, uint3 v) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); + 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 + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); + const size_t dataIdx = index >> 2; + data[dataIdx + 0] = v.x; + data[dataIdx + 1] = v.y; + data[dataIdx + 2] = v.z; + data[dataIdx + 3] = v.w; + } + template + void Store(size_t index, T const& value) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); + *(T*)(((char*)data) + index) = value; + } + + uint32_t* data; + size_t sizeInBytes; //< Must be multiple of 4 +}; + +struct ISamplerState; +struct ISamplerComparisonState; + +struct SamplerState +{ + ISamplerState* state; +}; + +struct SamplerComparisonState +{ + ISamplerComparisonState* state; +}; + +#ifndef SLANG_RESOURCE_SHAPE +#define SLANG_RESOURCE_SHAPE +typedef unsigned int SlangResourceShape; +enum +{ + SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F, + + 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_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_TEXTURE_FEEDBACK_FLAG = 0x10, + 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_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 + +// +struct TextureDimensions +{ + void reset() + { + shape = 0; + width = height = depth = 0; + numberOfLevels = 0; + arrayElementCount = 0; + } + int getDimSizes(uint32_t outDims[4]) const + { + const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK); + int count = 0; + switch (baseShape) + { + case SLANG_TEXTURE_1D: + { + outDims[count++] = width; + break; + } + case SLANG_TEXTURE_2D: + { + outDims[count++] = width; + outDims[count++] = height; + break; + } + case SLANG_TEXTURE_3D: + { + outDims[count++] = width; + outDims[count++] = height; + outDims[count++] = depth; + break; + } + case SLANG_TEXTURE_CUBE: + { + outDims[count++] = width; + outDims[count++] = height; + outDims[count++] = 6; + break; + } + } + + if (shape & SLANG_TEXTURE_ARRAY_FLAG) + { + outDims[count++] = arrayElementCount; + } + return count; + } + int getMIPDims(int outDims[3]) const + { + const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK); + int count = 0; + switch (baseShape) + { + case SLANG_TEXTURE_1D: + { + outDims[count++] = width; + break; + } + case SLANG_TEXTURE_CUBE: + case SLANG_TEXTURE_2D: + { + outDims[count++] = width; + outDims[count++] = height; + break; + } + case SLANG_TEXTURE_3D: + { + outDims[count++] = width; + outDims[count++] = height; + outDims[count++] = depth; + break; + } + } + return count; + } + int calcMaxMIPLevels() const + { + int dims[3]; + const int dimCount = getMIPDims(dims); + for (int count = 1; true; count++) + { + bool allOne = true; + for (int i = 0; i < dimCount; ++i) + { + if (dims[i] > 1) + { + allOne = false; + dims[i] >>= 1; + } + } + if (allOne) + { + return count; + } + } + } + + uint32_t shape; + uint32_t width, height, depth; + uint32_t numberOfLevels; + 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; +}; + +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(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(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) const + { + T out; + texture->SampleLevel(samplerState, &loc, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +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 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( + 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) const + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +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; + *outDepth = dims.depth; + } + 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; + *outHeight = dims.height; + *outDepth = dims.depth; + *outNumberOfLevels = dims.numberOfLevels; + } + void GetDimensions(float* outWidth, float* outHeight, float* outDepth) + { + 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) + { + const auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *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) const + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +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 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( + 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) const + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +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) + { + 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) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outNumberOfLevels = dims.numberOfLevels; + *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) const + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +template +struct Texture2DArray +{ + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + 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; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + *outNumberOfLevels = dims.numberOfLevels; + } + + void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *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) const + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; +}; + +template +struct TextureCubeArray +{ + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + 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; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + *outNumberOfLevels = dims.numberOfLevels; + } + + void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *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) const + { + 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. + virtual void* refAt(const uint32_t* loc) = 0; +}; + +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(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; + } + T& operator[](uint32_t loc) { return *(T*)texture->refAt(&loc); } + IRWTexture* texture; +}; + +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 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( + 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& operator[](const uint2& loc) { return *(T*)texture->refAt(&loc.x); } + IRWTexture* texture; +}; + +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; + *outDepth = dims.depth; + } + 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; + *outHeight = dims.height; + *outDepth = dims.depth; + *outNumberOfLevels = dims.numberOfLevels; + } + void GetDimensions(float* outWidth, float* outHeight, float* outDepth) + { + 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) + { + const auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *outDepth = dims.depth; + *outNumberOfLevels = dims.numberOfLevels; + } + + 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 +struct RWTexture1DArray +{ + 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) + { + 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( + 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& operator[](uint2 loc) { return *(T*)texture->refAt(&loc.x); } + + IRWTexture* texture; +}; + +template +struct RWTexture2DArray +{ + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + 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; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + *outNumberOfLevels = dims.numberOfLevels; + } + void GetDimensions(float* outWidth, float* outHeight, float* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) + { + const auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + *outNumberOfLevels = dims.numberOfLevels; + } + + 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; +}; + +// FeedbackTexture + +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; +}; + +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 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( + 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 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); + } + + // Without Clamp + 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 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 +struct FeedbackTexture2DArray +{ + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + 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; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + *outNumberOfLevels = dims.numberOfLevels; + } + void GetDimensions(float* outWidth, float* outHeight, float* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) + { + const auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outHeight = dims.height; + *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 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); + } + + // Without Clamp + + 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 WriteSamplerFeedbackGrad( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float3 ddx, + float3 ddy) + { + texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x); + } + + IFeedbackTexture* texture; +}; + +/* Varying input for Compute */ + +/* Used when running a single thread */ +struct ComputeThreadVaryingInput +{ + uint3 groupID; + uint3 groupThreadID; +}; + +struct ComputeVaryingInput +{ + 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. + +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/lib/All/slang/include/slang-cuda-prelude.h b/lib/All/slang/include/slang-cuda-prelude.h new file mode 100644 index 0000000..bf1d05c --- /dev/null +++ b/lib/All/slang/include/slang-cuda-prelude.h @@ -0,0 +1,7926 @@ +#ifndef SLANG_CUDA_PRELUDE_H +#define SLANG_CUDA_PRELUDE_H + +#define SLANG_PRELUDE_EXPORT + +#ifdef __CUDACC_RTC__ +#define SLANG_CUDA_RTC 1 +#else +#define SLANG_CUDA_RTC 0 +#endif + +#if SLANG_CUDA_RTC + +#else + +#include +#include + +#endif + +// 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. + +#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 +#endif + +#ifdef SLANG_CUDA_ENABLE_FP8 +#include +#endif + +#ifdef SLANG_CUDA_ENABLE_BF16 +#include +#endif + +#ifdef SLANG_CUDA_ENABLE_OPTIX +#include +#endif + +// Define slang offsetof implementation +#ifndef SLANG_OFFSET_OF +#define SLANG_OFFSET_OF(type, member) (size_t)((char*)&(((type*)0)->member) - (char*)0) +#endif + +// Must be large enough to cause overflow and therefore infinity +#ifndef SLANG_INFINITY +#define SLANG_INFINITY ((float)(1e+300 * 1e+300)) +#endif + +// For now we'll disable any asserts in this prelude +#define SLANG_PRELUDE_ASSERT(x) + +#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_BITMASK (~int(0)) + +// +#define SLANG_FORCE_INLINE inline + +#define SLANG_CUDA_CALL __device__ + +#define SLANG_FORCE_INLINE inline +#define SLANG_INLINE inline + + +// Since we are using unsigned arithmatic care is need in this comparison. +// It is *assumed* that sizeInBytes >= elemSize. Which means (sizeInBytes >= elemSize) >= 0 +// Which means only a single test is needed + +// 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); + +// 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) +#else +#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) +#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) +#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) +#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. + +#ifndef SLANG_CUDA_BOUNDARY_MODE +#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 + +#define SLANG_PTX_BOUNDARY_MODE "zero" +#endif + +struct TypeInfo +{ + size_t typeSize; +}; + +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]; + } + + 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 +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]; + } + + 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; + +// 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. +typedef size_t NonUniformResourceIndex; + +// Code generator will generate the specific type +template +struct Matrix; + +// Boolean vector types should follow CUDA's builtin vector alignment rules +// Align boolX the same as charX according to CUDA spec: +// char1/uchar1: 1-byte aligned, char2/uchar2: 2-byte aligned +// char3/uchar3: 1-byte aligned, char4/uchar4: 4-byte aligned +struct __align__(1) bool1 +{ + bool x; + + SLANG_FORCE_INLINE SLANG_CUDA_CALL bool& operator[](int idx) + { + return (&x)[idx]; + } + SLANG_FORCE_INLINE SLANG_CUDA_CALL const bool& operator[](int idx) const + { + return (&x)[idx]; + } +}; + +struct __align__(2) bool2 +{ + bool x, y; + + SLANG_FORCE_INLINE SLANG_CUDA_CALL bool& operator[](int idx) + { + return (&x)[idx]; + } + SLANG_FORCE_INLINE SLANG_CUDA_CALL const bool& operator[](int idx) const + { + return (&x)[idx]; + } +}; + +struct __align__(1) bool3 +{ + bool x, y, z; + + SLANG_FORCE_INLINE SLANG_CUDA_CALL bool& operator[](int idx) + { + return (&x)[idx]; + } + SLANG_FORCE_INLINE SLANG_CUDA_CALL const bool& operator[](int idx) const + { + return (&x)[idx]; + } +}; + +struct __align__(4) bool4 +{ + bool x, y, z, w; + + SLANG_FORCE_INLINE SLANG_CUDA_CALL bool& operator[](int idx) + { + return (&x)[idx]; + } + SLANG_FORCE_INLINE SLANG_CUDA_CALL const bool& operator[](int idx) const + { + return (&x)[idx]; + } +}; + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool __ldg(const bool* ptr) +{ + return (bool)(__ldg((const char*)ptr)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool2 __ldg(const bool2* ptr) +{ + auto val = __ldg((const char2*)ptr); + return {val.x != 0, val.y != 0}; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool4 __ldg(const bool4* ptr) +{ + auto val = __ldg((const char4*)ptr); + return {val.x != 0, val.y != 0, val.z != 0, val.w != 0}; +} + +#if SLANG_CUDA_RTC + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef ptrdiff_t intptr_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef size_t uintptr_t; + +typedef long long longlong; +typedef unsigned long long ulonglong; + +#else + +// When not using NVRTC, match the platform's int64_t definition for signed type +// On Linux: int64_t is 'long', on Windows: int64_t is 'long long' +typedef int64_t longlong; +// ulonglong must remain 'unsigned long long' to match CUDA's atomic operations +typedef unsigned long long ulonglong; + +#endif + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; + +#if SLANG_CUDA_ENABLE_HALF +typedef __half half; +#endif + +union Union32 +{ + uint32_t u; + int32_t i; + float f; +}; + +union Union64 +{ + uint64_t u; + int64_t i; + double d; +}; + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL float make_float(T val) +{ + return (float)val; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL float _slang_fmod(float x, float y) +{ + return ::fmodf(x, y); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double _slang_fmod(double x, double y) +{ + return ::fmod(x, 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; +}; +#endif + +#if SLANG_CUDA_ENABLE_BF16 + +// Add the other vector bfloat16 types +struct __nv_bfloat161 +{ + __nv_bfloat16 x; +}; +struct __nv_bfloat163 +{ + __nv_bfloat16 x, y, z; +}; +struct __nv_bfloat164 +{ + __nv_bfloat16 x, y, z, w; +}; +#endif + +#if SLANG_CUDA_ENABLE_FP8 + +// Add the other vector fp8 types +struct __nv_fp8_e4m31 +{ + __nv_fp8_e4m3 x; +}; +struct __nv_fp8_e4m32 +{ + __nv_fp8_e4m3 x, y; +}; +struct __nv_fp8_e4m33 +{ + __nv_fp8_e4m3 x, y, z; +}; +struct __nv_fp8_e4m34 +{ + __nv_fp8_e4m3 x, y, z, w; +}; +struct __nv_fp8_e5m21 +{ + __nv_fp8_e5m2 x; +}; +struct __nv_fp8_e5m22 +{ + __nv_fp8_e5m2 x, y; +}; +struct __nv_fp8_e5m23 +{ + __nv_fp8_e5m2 x, y, z; +}; +struct __nv_fp8_e5m24 +{ + __nv_fp8_e5m2 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]; \ + } +SLANG_VECTOR_GET_ELEMENT(int) +SLANG_VECTOR_GET_ELEMENT(bool) +SLANG_VECTOR_GET_ELEMENT(uint) +SLANG_VECTOR_GET_ELEMENT(short) +SLANG_VECTOR_GET_ELEMENT(ushort) +SLANG_VECTOR_GET_ELEMENT(char) +SLANG_VECTOR_GET_ELEMENT(uchar) +SLANG_VECTOR_GET_ELEMENT(longlong) +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(const T##1 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(const T##2 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(const T##3 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(const T##4 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } +SLANG_VECTOR_GET_ELEMENT_PTR(int) +SLANG_VECTOR_GET_ELEMENT_PTR(bool) +SLANG_VECTOR_GET_ELEMENT_PTR(uint) +SLANG_VECTOR_GET_ELEMENT_PTR(short) +SLANG_VECTOR_GET_ELEMENT_PTR(ushort) +SLANG_VECTOR_GET_ELEMENT_PTR(char) +SLANG_VECTOR_GET_ELEMENT_PTR(uchar) +SLANG_VECTOR_GET_ELEMENT_PTR(longlong) +SLANG_VECTOR_GET_ELEMENT_PTR(ulonglong) +SLANG_VECTOR_GET_ELEMENT_PTR(float) +SLANG_VECTOR_GET_ELEMENT_PTR(double) + +#if SLANG_CUDA_ENABLE_HALF +SLANG_VECTOR_GET_ELEMENT(__half) +SLANG_VECTOR_GET_ELEMENT_PTR(__half) +#endif + +#if SLANG_CUDA_ENABLE_BF16 +SLANG_VECTOR_GET_ELEMENT(__nv_bfloat16) +SLANG_VECTOR_GET_ELEMENT_PTR(__nv_bfloat16) + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_bfloat16 +_slang_vector_dot(__nv_bfloat162 v0, __nv_bfloat162 v1) +{ + __nv_bfloat16 result = __nv_bfloat16(0.0f); + for (int i = 0; i < 2; i++) + { + result += _slang_vector_get_element(v0, i) * _slang_vector_get_element(v1, i); + } + return result; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_bfloat16 +_slang_vector_dot(__nv_bfloat163 v0, __nv_bfloat163 v1) +{ + __nv_bfloat16 result = __nv_bfloat16(0.0f); + for (int i = 0; i < 3; i++) + { + result += _slang_vector_get_element(v0, i) * _slang_vector_get_element(v1, i); + } + return result; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_bfloat16 +_slang_vector_dot(__nv_bfloat164 v0, __nv_bfloat164 v1) +{ + __nv_bfloat16 result = __nv_bfloat16(0.0f); + for (int i = 0; i < 4; i++) + { + result += _slang_vector_get_element(v0, i) * _slang_vector_get_element(v1, i); + } + return result; +} +#endif + +#if SLANG_CUDA_ENABLE_FP8 +SLANG_VECTOR_GET_ELEMENT(__nv_fp8_e4m3) +SLANG_VECTOR_GET_ELEMENT_PTR(__nv_fp8_e4m3) +SLANG_VECTOR_GET_ELEMENT(__nv_fp8_e5m2) +SLANG_VECTOR_GET_ELEMENT_PTR(__nv_fp8_e5m2) +#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_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) = \ + (_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, 4) + +SLANG_CUDA_VECTOR_INT_OPS(int) +SLANG_CUDA_VECTOR_INT_OPS(bool) +SLANG_CUDA_VECTOR_INT_OPS(uint) +SLANG_CUDA_VECTOR_INT_OPS(ushort) +SLANG_CUDA_VECTOR_INT_OPS(short) +SLANG_CUDA_VECTOR_INT_OPS(char) +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, !=) \ + 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, 4) + +SLANG_CUDA_VECTOR_FLOAT_OPS(float) +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) \ + 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) \ + 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}; \ + } +#endif + +#if SLANG_CUDA_RTC +SLANG_MAKE_VECTOR(int) +SLANG_MAKE_VECTOR(uint) +SLANG_MAKE_VECTOR(short) +SLANG_MAKE_VECTOR(ushort) +SLANG_MAKE_VECTOR(char) +SLANG_MAKE_VECTOR(uchar) +SLANG_MAKE_VECTOR(float) +SLANG_MAKE_VECTOR(double) +SLANG_MAKE_VECTOR(longlong) +SLANG_MAKE_VECTOR(ulonglong) +#endif + +#if SLANG_CUDA_ENABLE_HALF +SLANG_MAKE_VECTOR(__half) +#endif + +#if SLANG_CUDA_ENABLE_BF16 +SLANG_MAKE_VECTOR(__nv_bfloat16) +#endif + +#if SLANG_CUDA_ENABLE_FP8 +SLANG_MAKE_VECTOR(__nv_fp8_e4m3) +SLANG_MAKE_VECTOR(__nv_fp8_e5m2) +#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}; +} + +#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); \ + } +#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); \ + } +#endif +SLANG_MAKE_VECTOR_FROM_SCALAR(int) +SLANG_MAKE_VECTOR_FROM_SCALAR(uint) +SLANG_MAKE_VECTOR_FROM_SCALAR(short) +SLANG_MAKE_VECTOR_FROM_SCALAR(ushort) +SLANG_MAKE_VECTOR_FROM_SCALAR(char) +SLANG_MAKE_VECTOR_FROM_SCALAR(uchar) +SLANG_MAKE_VECTOR_FROM_SCALAR(longlong) +SLANG_MAKE_VECTOR_FROM_SCALAR(ulonglong) +SLANG_MAKE_VECTOR_FROM_SCALAR(float) +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}; +} +#endif +#endif +#if SLANG_CUDA_ENABLE_BF16 +SLANG_MAKE_VECTOR_FROM_SCALAR(__nv_bfloat16) +#if !SLANG_CUDA_RTC +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_bfloat16 make___nv_bfloat161(__nv_bfloat16 x) +{ + return __nv_bfloat16{x}; +} +#endif +#endif + +#if SLANG_CUDA_ENABLE_FP8 +SLANG_MAKE_VECTOR_FROM_SCALAR(__nv_fp8_e4m3) +SLANG_MAKE_VECTOR_FROM_SCALAR(__nv_fp8_e5m2) +#if !SLANG_CUDA_RTC +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_fp8_e4m3 make___nv_fp8_e4m31(__nv_fp8_e4m3 x) +{ + return __nv_fp8_e4m3{x}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __nv_fp8_e5m2 make___nv_fp8_e5m21(__nv_fp8_e5m2 x) +{ + return __nv_fp8_e5m2{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; \ + } + +#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 900 +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, float, 2) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, float, 4) +#endif +#if defined(SLANG_CUDA_ENABLE_HALF) && defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 700) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, __half, 3) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, __half, 4) +#endif +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, float, 3) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, int, 2) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, int, 3) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, int, 4) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, uint, 2) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, uint, 3) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, uint, 4) +SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, ulonglong, 2) +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); \ + } \ + }; +#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) +GET_VECTOR_TYPE_IMPL_N(bool) +GET_VECTOR_TYPE_IMPL_N(uint) +GET_VECTOR_TYPE_IMPL_N(short) +GET_VECTOR_TYPE_IMPL_N(ushort) +GET_VECTOR_TYPE_IMPL_N(char) +GET_VECTOR_TYPE_IMPL_N(uchar) +GET_VECTOR_TYPE_IMPL_N(longlong) +GET_VECTOR_TYPE_IMPL_N(ulonglong) +GET_VECTOR_TYPE_IMPL_N(float) +GET_VECTOR_TYPE_IMPL_N(double) +#if SLANG_CUDA_ENABLE_HALF +GET_VECTOR_TYPE_IMPL_N(__half) +#endif +#if SLANG_CUDA_ENABLE_BF16 +GET_VECTOR_TYPE_IMPL_N(__nv_bfloat16) +#endif +#if SLANG_CUDA_ENABLE_FP8 +GET_VECTOR_TYPE_IMPL_N(__nv_fp8_e4m3) +GET_VECTOR_TYPE_IMPL_N(__nv_fp8_e5m2) +#endif + +template +using Vector = typename GetVectorTypeImpl::type; + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector _slang_vector_reshape(const Vector other) +{ + Vector result; + for (int i = 0; i < n; i++) + { + OtherT otherElement = T(0); + if (i < m) + otherElement = _slang_vector_get_element(other, i); + *_slang_vector_get_element_ptr(&result, i) = (T)otherElement; + } + return result; +} + +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 const Vector& operator[](size_t index) const + { + return rows[index]; + } +}; + + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T scalar) +{ + Matrix result; + for (int i = 0; i < ROWS; i++) + result.rows[i] = GetVectorTypeImpl::fromScalar(scalar); + return result; +} + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector& row0) +{ + Matrix result; + result.rows[0] = row0; + return result; +} + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Vector& row0, + const Vector& row1) +{ + Matrix result; + result.rows[0] = row0; + result.rows[1] = row1; + return result; +} + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Vector& row0, + const Vector& row1, + const Vector& row2) +{ + Matrix result; + result.rows[0] = row0; + result.rows[1] = row1; + result.rows[2] = row2; + return result; +} + +template +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; + result.rows[1] = row1; + result.rows[2] = row2; + result.rows[3] = row3; + return result; +} + +template +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; + 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); + return result; +} + +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; + return rs; +} + +template +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) + { + *_slang_vector_get_element_ptr(&rs.rows[0], 0) = v0; + *_slang_vector_get_element_ptr(&rs.rows[0], 1) = v1; + *_slang_vector_get_element_ptr(&rs.rows[0], 2) = v2; + *_slang_vector_get_element_ptr(&rs.rows[1], 0) = v3; + *_slang_vector_get_element_ptr(&rs.rows[1], 1) = v4; + *_slang_vector_get_element_ptr(&rs.rows[1], 2) = 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; + } + 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) +{ + Matrix rs; + if (COLS == 4) + { + *_slang_vector_get_element_ptr(&rs.rows[0], 0) = v0; + *_slang_vector_get_element_ptr(&rs.rows[0], 1) = v1; + *_slang_vector_get_element_ptr(&rs.rows[0], 2) = v2; + *_slang_vector_get_element_ptr(&rs.rows[0], 3) = v3; + *_slang_vector_get_element_ptr(&rs.rows[1], 0) = v4; + *_slang_vector_get_element_ptr(&rs.rows[1], 1) = v5; + *_slang_vector_get_element_ptr(&rs.rows[1], 2) = v6; + *_slang_vector_get_element_ptr(&rs.rows[1], 3) = 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; + } + 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) +{ + 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; + 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) +{ + Matrix rs; + if (COLS == 4) + { + *_slang_vector_get_element_ptr(&rs.rows[0], 0) = v0; + *_slang_vector_get_element_ptr(&rs.rows[0], 1) = v1; + *_slang_vector_get_element_ptr(&rs.rows[0], 2) = v2; + *_slang_vector_get_element_ptr(&rs.rows[0], 3) = v3; + *_slang_vector_get_element_ptr(&rs.rows[1], 0) = v4; + *_slang_vector_get_element_ptr(&rs.rows[1], 1) = v5; + *_slang_vector_get_element_ptr(&rs.rows[1], 2) = v6; + *_slang_vector_get_element_ptr(&rs.rows[1], 3) = v7; + *_slang_vector_get_element_ptr(&rs.rows[2], 0) = v8; + *_slang_vector_get_element_ptr(&rs.rows[2], 1) = v9; + *_slang_vector_get_element_ptr(&rs.rows[2], 2) = v10; + *_slang_vector_get_element_ptr(&rs.rows[2], 3) = 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; + } + 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) +{ + 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; + 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_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, !) \ + 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_UNARY_OP(T, -) +SLANG_INT_MATRIX_OPS(int) +SLANG_INT_MATRIX_OPS(uint) +SLANG_INT_MATRIX_OPS(short) +SLANG_INT_MATRIX_OPS(ushort) +SLANG_INT_MATRIX_OPS(char) +SLANG_INT_MATRIX_OPS(uchar) +SLANG_INT_MATRIX_OPS(longlong) +SLANG_INT_MATRIX_OPS(ulonglong) +SLANG_FLOAT_MATRIX_OPS(float) +SLANG_FLOAT_MATRIX_OPS(double) +#if SLANG_CUDA_ENABLE_HALF +SLANG_FLOAT_MATRIX_OPS(__half) +#endif +#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) +#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; +} +#endif +#undef SLANG_FLOAT_MATRIX_MOD +#undef SLANG_MATRIX_BINARY_OP +#undef SLANG_MATRIX_UNARY_OP +#undef SLANG_INT_MATRIX_OPS +#undef SLANG_FLOAT_MATRIX_OPS +#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) \ + SLANG_SELECT_IMPL(T, 4) + +SLANG_SELECT_T(int) +SLANG_SELECT_T(bool) +SLANG_SELECT_T(uint) +SLANG_SELECT_T(short) +SLANG_SELECT_T(ushort) +SLANG_SELECT_T(char) +SLANG_SELECT_T(uchar) +SLANG_SELECT_T(float) +SLANG_SELECT_T(double) + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_select(bool condition, T v0, T v1) +{ + return condition ? v0 : 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)}; +} + +// 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)); +} + +// 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 + +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)); \ + } + +SLANG_SURFACE_READ(surf1Dread, (int x), (x)) +SLANG_SURFACE_READ(surf2Dread, (int x, int y), (x, y)) +SLANG_SURFACE_READ(surf3Dread, (int x, int y, int z), (x, y, z)) +SLANG_SURFACE_READ(surf1DLayeredread, (int x, int layer), (x, layer)) +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); \ + } + +SLANG_SURFACE_WRITE(surf1Dwrite, (int x), (x)) +SLANG_SURFACE_WRITE(surf2Dwrite, (int x, int y), (x, y)) +SLANG_SURFACE_WRITE(surf3Dwrite, (int x, int y, int z), (x, y, z)) +SLANG_SURFACE_WRITE(surf1DLayeredwrite, (int x, int layer), (x, layer)) +SLANG_SURFACE_WRITE(surf2DLayeredwrite, (int x, int y, int layer), (x, y, layer)) +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)) +SLANG_SURFACE_READ_HALF_CONVERT(surf3Dread, (int x, int y, int z), (x, y, z)) + +#endif + +// 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. + +// https://docs.nvidia.com/cuda/inline-ptx-assembly/index.html +// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#surface-instructions-sust + + +// surf1Dwrite_convert + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( + T v, + cudaSurfaceObject_t surfObj, + int x, + cudaSurfaceBoundaryMode boundaryMode); + +#define SLANG_SURF1DWRITE_CONVERT_IMPL(T, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( \ + T v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + asm volatile( \ + "sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2};" ::"l"(surfObj), \ + "r"(x), \ + c(v)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( \ + T##2 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y; \ + asm volatile( \ + "sust.p.1d.v2.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2, %3};" ::"l"(surfObj), \ + "r"(x), \ + c(vx), \ + c(vy)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( \ + T##4 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y, vz = v.z, vw = v.w; \ + asm volatile( \ + "sust.p.1d.v4.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1}], {%2, %3, %4, %5};" ::"l"(surfObj), \ + "r"(x), \ + c(vx), \ + c(vy), \ + c(vz), \ + c(vw)); \ + } + +SLANG_SURF1DWRITE_CONVERT_IMPL(float, "f") +SLANG_SURF1DWRITE_CONVERT_IMPL(uint, "r") +SLANG_SURF1DWRITE_CONVERT_IMPL(int, "r") + +// surf1DLayeredwrite_convert (not supported) + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1DLayeredwrite_convert( + T v, + cudaSurfaceObject_t surfObj, + int x, + int layer, + cudaSurfaceBoundaryMode boundaryMode) +{ + // TODO: static_assert(false) can fail on some compilers, even if template is not instantiated. + // We should check for this in hlsl.meta.slang instead. + // static_assert(false, "CUDA doesn't support formatted surface writes on 1D array surfaces"); +} + +// surf2Dwrite_convert + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( + T v, + cudaSurfaceObject_t surfObj, + int x, + int y, + cudaSurfaceBoundaryMode boundaryMode); + +#define SLANG_SURF2DWRITE_CONVERT_IMPL(T, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( \ + T v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + asm volatile( \ + "sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1, %2}], {%3};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + c(v)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( \ + T##2 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y; \ + asm volatile( \ + "sust.p.2d.v2.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1, %2}], {%3, %4};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + c(vx), \ + c(vy)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( \ + T##4 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y, vz = v.z, vw = v.w; \ + asm volatile( \ + "sust.p.2d.v4.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1, %2}], {%3, %4, %5, %6};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + c(vx), \ + c(vy), \ + c(vz), \ + c(vw)); \ + } + +SLANG_SURF2DWRITE_CONVERT_IMPL(float, "f") +SLANG_SURF2DWRITE_CONVERT_IMPL(uint, "r") +SLANG_SURF2DWRITE_CONVERT_IMPL(int, "r") + +// surf2DLayeredwrite_convert (not supported) + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2DLayeredwrite_convert( + T v, + cudaSurfaceObject_t surfObj, + int x, + int y, + int layer, + cudaSurfaceBoundaryMode boundaryMode) +{ + // TODO: static_assert(false) can fail on some compilers, even if template is not instantiated. + // We should check for this in hlsl.meta.slang instead. + // static_assert(false, "CUDA doesn't support formatted surface writes on 2D array surfaces"); +} + +// surf3Dwrite_convert + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( + T v, + cudaSurfaceObject_t surfObj, + int x, + int y, + int z, + cudaSurfaceBoundaryMode boundaryMode); + +#define SLANG_SURF3DWRITE_CONVERT_IMPL(T, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( \ + T v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + int z, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + asm volatile( \ + "sust.p.3d.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1, %2, %3, %4}], {%5};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + "r"(z), \ + "r"(0), \ + c(v)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( \ + T##2 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + int z, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y; \ + asm volatile( \ + "sust.p.3d.v2.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1, %2, %3, %4}], {%5, %6};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + "r"(z), \ + "r"(0), \ + c(vx), \ + c(vy)); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( \ + T##4 v, \ + cudaSurfaceObject_t surfObj, \ + int x, \ + int y, \ + int z, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const T vx = v.x, vy = v.y, vz = v.z, vw = v.w; \ + asm volatile( \ + "sust.p.3d.v4.b32." SLANG_PTX_BOUNDARY_MODE \ + " [%0, {%1, %2, %3, %4}], {%5, %6, %7, %8};" ::"l"(surfObj), \ + "r"(x), \ + "r"(y), \ + "r"(z), \ + "r"(0), \ + c(vx), \ + c(vy), \ + c(vz), \ + c(vw)); \ + } + +SLANG_SURF3DWRITE_CONVERT_IMPL(float, "f") +SLANG_SURF3DWRITE_CONVERT_IMPL(uint, "r") +SLANG_SURF3DWRITE_CONVERT_IMPL(int, "r") + +// ----------------------------- F16 ----------------------------------------- +#if SLANG_CUDA_ENABLE_HALF +// Unary +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_ceil(__half f) +{ + return ::hceil(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_floor(__half f) +{ + return ::hfloor(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_round(__half f) +{ + return ::hrint(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_sin(__half f) +{ + return ::hsin(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_cos(__half f) +{ + return ::hcos(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL void F16_sincos(__half f, __half* s, __half* c) +{ + *s = ::hsin(f); + *c = ::hcos(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_tan(__half f) +{ + return __float2half(::tanf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_asin(__half f) +{ + return __float2half(::asinf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_acos(__half f) +{ + return __float2half(::acosf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_atan(__half f) +{ + return __float2half(::atanf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_sinh(__half f) +{ + return __float2half(::sinhf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_cosh(__half f) +{ + return __float2half(::coshf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_tanh(__half f) +{ + return __float2half(::tanhf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_asinh(__half f) +{ + return __float2half(::asinhf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_acosh(__half f) +{ + return __float2half(::acoshf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_atanh(__half f) +{ + return __float2half(::atanhf(__half2float(f))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_log2(__half f) +{ + return ::hlog2(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_log(__half f) +{ + return ::hlog(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_log10(__half f) +{ + return ::hlog10(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_exp2(__half f) +{ + return ::hexp2(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_exp(__half f) +{ + return ::hexp(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_abs(__half f) +{ + return __habs(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_trunc(__half f) +{ + return ::htrunc(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_sqrt(__half f) +{ + return ::hsqrt(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_rsqrt(__half f) +{ + return ::hrsqrt(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int F16_sign(__half f) +{ + return (f == __half(0.0f)) ? 0 : ((f < __half(0.0f)) ? -1 : 1); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_frac(__half f) +{ + return f - F16_floor(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F16_isnan(__half f) +{ + return __hisnan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F16_isfinite(__half f) +{ + return !__hisinf(f) && !__hisnan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F16_isinf(__half f) +{ + return __hisinf(f); +} + +// Binary +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_min(__half a, __half b) +{ + return __hmin(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_max(__half a, __half b) +{ + return __hmax(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_pow(__half a, __half b) +{ + return __float2half(::powf(__half2float(a), __half2float(b))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_fmod(__half a, __half b) +{ + return __float2half(::fmodf(__half2float(a), __half2float(b))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_remainder(__half a, __half b) +{ + return __float2half(::remainderf(__half2float(a), __half2float(b))); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_atan2(__half a, __half b) +{ + return __float2half(::atan2(__half2float(a), __half2float(b))); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_frexp(__half x, int* e) +{ + return __float2half(frexpf(__half2float(x), e)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_modf(__half x, __half* ip) +{ + float ipf; + float res = ::modff(__half2float(x), &ipf); + *ip = __float2half(ipf); + return __float2half(res); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint16_t F16_asuint(__half h) +{ + return __half_as_ushort(h); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int16_t F16_asint(__half h) +{ + return __half_as_short(h); +} + +// Ternary +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half F16_fma(__half a, __half b, __half c) +{ + return __hfma(a, b, c); +} + +#endif + +// ----------------------------- 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_asinh(float f) +{ + return ::asinhf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_acosh(float f) +{ + return ::acoshf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_atanh(float f) +{ + return ::atanhf(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 int F32_sign(float f) +{ + return (f == 0.0f) ? 0 : ((f < 0.0f) ? -1 : 1); +} +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_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; +} + +// Ternary +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 int F64_sign(double f) +{ + return (f == 0.0) ? 0 : ((f < 0.0) ? -1 : 1); +} +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_frexp(double x, int* e) +{ + return ::frexp(x, e); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_modf(double x, double* ip) +{ + return ::modf(x, ip); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL void F64_asuint(double d, uint32_t* low, uint32_t* hi) +{ + Union64 u; + u.d = d; + *low = uint32_t(u.u); + *hi = uint32_t(u.u >> 32); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL void F64_asint(double d, int32_t* low, int32_t* hi) +{ + Union64 u; + u.d = d; + *low = int32_t(u.u); + *hi = int32_t(u.u >> 32); +} + +// Ternary +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_fma(double a, double b, double c) +{ + return ::fma(a, b, c); +} + +// ----------------------------- U8 ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U8_countbits(uint8_t v) +{ + // No native 8bit popc yet, just cast and use 32bit variant + return __popc(uint32_t(v)); +} + +// ----------------------------- I8 ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I8_countbits(int8_t v) +{ + return U8_countbits(uint8_t(v)); +} + +// ----------------------------- U16 ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U16_countbits(uint16_t v) +{ + // No native 16bit popc yet, just cast and use 32bit variant + return __popc(uint32_t(v)); +} + +// ----------------------------- I16 ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I16_countbits(int16_t v) +{ + return U16_countbits(uint16_t(v)); +} + +// ----------------------------- U32 ----------------------------------------- + +// 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 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) +{ + Union64 u; + u.u = (uint64_t(hi) << 32) | low; + return u.d; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_countbits(uint32_t v) +{ + return __popc(v); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_firstbitlow(uint32_t v) +{ + // __ffs returns 1-based bit position or 0 if no bits set + // firstbitlow should return 0-based bit position or ~0u if no bits set + return v == 0 ? ~0u : (__ffs(v) - 1); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_firstbithigh(uint32_t v) +{ + // maps to hlsl firstbithigh + if ((int32_t)v < 0) + v = ~v; + if (v == 0) + return ~0u; + return 31 - __clz(v); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_reversebits(uint32_t v) +{ + return __brev(v); +} + +// ----------------------------- I32 ----------------------------------------- + +// Unary +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 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); + return u.d; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_countbits(int32_t v) +{ + return U32_countbits(uint32_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_firstbitlow(int32_t v) +{ + return U32_firstbitlow(uint32_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_firstbithigh(int32_t v) +{ + return U32_firstbithigh(uint32_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_reversebits(int32_t v) +{ + return int32_t(U32_reversebits(uint32_t(v))); +} + +// ----------------------------- 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_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) +{ + return __popcll(v); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U64_firstbitlow(uint64_t v) +{ + // __ffs returns 1-based bit position or 0 if no bits set + // firstbitlow should return 0-based bit position or ~0u if no bits set + return v == 0 ? ~uint32_t(0) : (__ffsll(v) - 1u); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U64_firstbithigh(uint64_t v) +{ + if (v == 0) + return ~uint32_t(0); + return 63 - __clzll(v); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint64_t U64_reversebits(uint64_t v) +{ + return __brevll(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_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 uint32_t I64_countbits(int64_t v) +{ + return U64_countbits(uint64_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I64_firstbitlow(int64_t v) +{ + return U64_firstbitlow(uint64_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I64_firstbithigh(int64_t v) +{ + if (v < 0) + v = ~v; + return U64_firstbithigh(uint64_t(v)); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_reversebits(int64_t v) +{ + return int64_t(U64_reversebits(uint64_t(v))); +} + +// ----------------------------- IPTR ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL intptr_t IPTR_abs(intptr_t f) +{ + return (f < 0) ? -f : f; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL intptr_t IPTR_min(intptr_t a, intptr_t b) +{ + return a < b ? a : b; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL intptr_t IPTR_max(intptr_t a, intptr_t b) +{ + return a > b ? a : b; +} + +// ----------------------------- UPTR ----------------------------------------- + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uintptr_t UPTR_abs(uintptr_t f) +{ + return f; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uintptr_t UPTR_min(uintptr_t a, uintptr_t b) +{ + return a < b ? a : b; +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL uintptr_t UPTR_max(uintptr_t a, uintptr_t b) +{ + return a > b ? a : b; +} + +// ----------------------------- ResourceType ----------------------------------------- + + +// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions +// Missing Load(_In_ int Location, _Out_ uint Status); + +template +struct StructuredBuffer +{ + SLANG_CUDA_CALL T& operator[](size_t index) const + { +#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT + SLANG_BOUND_CHECK(index, count); +#endif + return data[index]; + } + + SLANG_CUDA_CALL T& Load(size_t index) const + { +#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT + SLANG_BOUND_CHECK(index, count); +#endif + return data[index]; + } + +#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT + SLANG_CUDA_CALL void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) const + { + *outNumStructs = uint32_t(count); + *outStride = uint32_t(sizeof(T)); + } +#endif + + T* data; +#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT + size_t count; +#endif +}; + +template +struct RWStructuredBuffer : StructuredBuffer +{ + SLANG_CUDA_CALL T& operator[](size_t index) const + { +#ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT + SLANG_BOUND_CHECK(index, this->count); +#endif + return this->data[index]; + } +}; + +// Missing Load(_In_ int Location, _Out_ uint Status); +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_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + 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 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]}; + } + 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]}; + } + template + SLANG_CUDA_CALL T Load(size_t index) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); + T data; + memcpy(&data, ((const char*)this->data) + index, sizeof(T)); + return data; + } + template + SLANG_CUDA_CALL StructuredBuffer asStructuredBuffer() const + { + StructuredBuffer rs; + rs.data = (T*)data; + rs.count = sizeInBytes / sizeof(T); + return rs; + } + const uint32_t* data; + size_t sizeInBytes; //< Must be multiple of 4 +}; + +// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer +// Atomic operations support + +// Signed 64-bit atomic wrappers +// CUDA only supports unsigned long long atomics, so we cast signed to unsigned +// Use longlong type with explicit unsigned long long casts for platform portability +__device__ __forceinline__ longlong atomicExch(longlong* address, longlong val) +{ + return (longlong)atomicExch((unsigned long long*)address, (unsigned long long)val); +} + +__device__ __forceinline__ longlong atomicCAS(longlong* address, longlong compare, longlong val) +{ + return (longlong)atomicCAS( + (unsigned long long*)address, + (unsigned long long)compare, + (unsigned long long)val); +} + +__device__ __forceinline__ longlong atomicAdd(longlong* address, longlong val) +{ + return (longlong)atomicAdd((unsigned long long*)address, (unsigned long long)val); +} + +// Float bitwise atomic compare-and-swap +// Uses integer atomics to preserve exact float bit patterns +__device__ __forceinline__ float atomicCAS(float* address, float compare, float val) +{ + int* addr_as_int = (int*)address; + int old = atomicCAS(addr_as_int, __float_as_int(compare), __float_as_int(val)); + return __int_as_float(old); +} + +// ===================================================================== +// Atomic Reduction Operations (PTX `red` instruction) +// These are in-place atomic operations that don't return the old value. +// They are faster than the corresponding atomic operations that return values +// because they use the PTX `red` instruction with relaxed memory ordering. +// +// Supported operations based on PTX ISA: +// - add: .s32, .u32, .u64, .s64, .f16, .f16x2, .bf16, .bf16x2, .f32, .f64 +// - min/max: .s32, .u32, .s64, .u64, .f32, .f64, .f16, .f16x2 +// - and/or/xor: .b32, .b64 +// - inc/dec: .u32 +// ===================================================================== + +// Atomic reduction ADD operations +__device__ __forceinline__ void __slang_atomic_reduce_add(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.s32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.u32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.s64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.u64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(float* addr, float val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.f32 [%0], %1;" : : "l"(addr), "f"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(double* addr, double val, int order) +{ + asm volatile("red.relaxed.gpu.global.add.f64 [%0], %1;" : : "l"(addr), "d"(val) : "memory"); +} + +#if SLANG_CUDA_ENABLE_HALF +__device__ __forceinline__ void __slang_atomic_reduce_add(__half* addr, __half val, int order) +{ + unsigned short val_as_ushort = *reinterpret_cast(&val); + asm volatile("red.relaxed.gpu.global.add.noftz.f16 [%0], %1;" + : + : "l"(addr), "h"(val_as_ushort) + : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add(__half2* addr, __half2 val, int order) +{ + unsigned int val_as_uint = *reinterpret_cast(&val); + asm volatile("red.relaxed.gpu.global.add.noftz.f16x2 [%0], %1;" + : + : "l"(addr), "r"(val_as_uint) + : "memory"); +} +#endif + +#if SLANG_CUDA_ENABLE_BF16 +__device__ __forceinline__ void __slang_atomic_reduce_add( + __nv_bfloat16* addr, + __nv_bfloat16 val, + int order) +{ + unsigned short val_as_ushort = *reinterpret_cast(&val); + asm volatile("red.relaxed.gpu.global.add.noftz.bf16 [%0], %1;" + : + : "l"(addr), "h"(val_as_ushort) + : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_add( + __nv_bfloat162* addr, + __nv_bfloat162 val, + int order) +{ + unsigned int val_as_uint = *reinterpret_cast(&val); + asm volatile("red.relaxed.gpu.global.add.noftz.bf16x2 [%0], %1;" + : + : "l"(addr), "r"(val_as_uint) + : "memory"); +} +#endif + +// Atomic reduction MIN operations +__device__ __forceinline__ void __slang_atomic_reduce_min(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.min.s32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_min(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.min.u32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_min(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.min.s64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_min(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.min.u64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +// NOTE: PTX `red` instruction does NOT support min/max for floating-point types. +// Only integer types (.u32, .u64, .s32, .s64) are supported for min/max. +// For floating-point min/max atomics, use the regular `atom` instruction via +// __atomic_min/__atomic_max. + +// Atomic reduction MAX operations +__device__ __forceinline__ void __slang_atomic_reduce_max(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.max.s32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_max(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.max.u32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_max(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.max.s64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_max(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.max.u64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +// NOTE: PTX `red` instruction does NOT support min/max for floating-point types. +// Only integer types (.u32, .u64, .s32, .s64) are supported for min/max. +// For floating-point min/max atomics, use the regular `atom` instruction via +// __atomic_min/__atomic_max. + +// Atomic reduction AND operations (bitwise, integers only) +__device__ __forceinline__ void __slang_atomic_reduce_and(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.and.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_and(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.and.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_and(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.and.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_and(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.and.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +// Atomic reduction OR operations (bitwise, integers only) +__device__ __forceinline__ void __slang_atomic_reduce_or(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.or.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_or(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.or.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_or(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.or.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_or(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.or.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +// Atomic reduction XOR operations (bitwise, integers only) +__device__ __forceinline__ void __slang_atomic_reduce_xor(int32_t* addr, int32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.xor.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_xor(uint32_t* addr, uint32_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.xor.b32 [%0], %1;" : : "l"(addr), "r"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_xor(int64_t* addr, int64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.xor.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_xor(uint64_t* addr, uint64_t val, int order) +{ + asm volatile("red.relaxed.gpu.global.xor.b64 [%0], %1;" : : "l"(addr), "l"(val) : "memory"); +} + +// Atomic reduction INC/DEC operations (unsigned 32-bit only in PTX) +// Note: PTX inc/dec have specific semantics: +// inc: d = (old >= b) ? 0 : old + 1 +// dec: d = ((old == 0) || (old > b)) ? b : old - 1 +// For simple increment by 1, we use add instead +__device__ __forceinline__ void __slang_atomic_reduce_inc(uint32_t* addr, int order) +{ + asm volatile("red.relaxed.gpu.global.add.u32 [%0], 1;" : : "l"(addr) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_inc(int32_t* addr, int order) +{ + asm volatile("red.relaxed.gpu.global.add.s32 [%0], 1;" : : "l"(addr) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_dec(uint32_t* addr, int order) +{ + asm volatile("red.relaxed.gpu.global.add.u32 [%0], -1;" : : "l"(addr) : "memory"); +} + +__device__ __forceinline__ void __slang_atomic_reduce_dec(int32_t* addr, int order) +{ + asm volatile("red.relaxed.gpu.global.add.s32 [%0], -1;" : : "l"(addr) : "memory"); +} + +// ===================================================================== +// End of Atomic Reduction 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_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + 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 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]}; + } + 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]}; + } + template + SLANG_CUDA_CALL T Load(size_t index) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); + T data; + memcpy(&data, ((const char*)this->data) + index, sizeof(T)); + return data; + } + + SLANG_CUDA_CALL void Store(size_t index, uint32_t v) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); + data[index >> 2] = v; + } + 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; + data[dataIdx + 0] = v.x; + data[dataIdx + 1] = v.y; + } + 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; + 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_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); + const size_t dataIdx = index >> 2; + data[dataIdx + 0] = v.x; + data[dataIdx + 1] = v.y; + data[dataIdx + 2] = v.z; + data[dataIdx + 3] = v.w; + } + template + SLANG_CUDA_CALL void Store(size_t index, T const& value) const + { + 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 + SLANG_CUDA_CALL T* _getPtrAt(size_t index) + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); + return (T*)(((char*)data) + index); + } + template + SLANG_CUDA_CALL RWStructuredBuffer asStructuredBuffer() const + { + RWStructuredBuffer rs; + rs.data = (T*)data; + rs.count = sizeInBytes / sizeof(T); + return rs; + } + uint32_t* data; + 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() +#ifndef SLANG_USE_ASM_LANE_ID +__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. + 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 + // true. + 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. +// +// 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'. +// __activemask() though does not require there is convergence, so that doesn't work. +// +// '__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.``` +// +// 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. + +// Return mask of all the lanes less than the current lane +__forceinline__ __device__ WarpMask _getLaneLtMask() +{ + return (int(1) << _getLaneId()) - 1; +} + +// TODO(JS): +// THIS IS NOT CORRECT! That determining the appropriate active mask requires appropriate +// mask tracking. +__forceinline__ __device__ WarpMask _getActiveMask() +{ + return __ballot_sync(__activemask(), true); +} + +// Return a mask suitable for the 'MultiPrefix' style functions +__forceinline__ __device__ WarpMask _getMultiPrefixMask(int mask) +{ + return mask; +} + +// Note! Note will return true if mask is 0, but thats okay, because there must be one +// lane active to execute anything +__inline__ __device__ bool _waveIsSingleLane(WarpMask mask) +{ + return (mask & (mask - 1)) == 0; +} + +// Returns the power of 2 size of run of set bits. Returns 0 if not a suitable run. +// Examples: +// 0b00000000'00000000'00000000'11111111 -> 8 +// 0b11111111'11111111'11111111'11111111 -> 32 +// 0b00000000'00000000'00000000'00011111 -> 0 (since 5 is not a power of 2) +// 0b00000000'00000000'00000000'11110000 -> 0 (since the run of bits does not start at the LSB) +// 0b00000000'00000000'00000000'00100111 -> 0 (since it is not a single contiguous run) +__inline__ __device__ int _waveCalcPow2Offset(WarpMask mask) +{ + // This should be the most common case, so fast path it + if (mask == SLANG_CUDA_WARP_BITMASK) + { + return SLANG_CUDA_WARP_SIZE; + } + // Is it a contiguous run of bits? + if ((mask & (mask + 1)) == 0) + { + // const int offsetSize = __ffs(mask + 1) - 1; + const int offset = 32 - __clz(mask); + // Is it a power of 2 size + if ((offset & (offset - 1)) == 0) + { + return offset; + } + } + return 0; +} + +__inline__ __device__ bool _waveIsFirstLane() +{ + const WarpMask mask = __activemask(); + // 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()); +} + +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 +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 +struct WaveOpXor +{ + __inline__ __device__ static T getInitial(T a) { return 0; } + __inline__ __device__ static T doOp(T a, T b) { return a ^ b; } + __inline__ __device__ static T doInverse(T a, T b) { return a ^ b; } +}; + +template +struct WaveOpAdd +{ + __inline__ __device__ static T getInitial(T a) { return 0; } + __inline__ __device__ static T doOp(T a, T b) { return a + b; } + __inline__ __device__ static T doInverse(T a, T b) { return a - b; } +}; + +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 + __inline__ __device__ static T doInverse(T a, T b) { return a / b; } +}; + +template +struct WaveOpMax +{ + __inline__ __device__ static T getInitial(T a, bool exclusive = false); + __inline__ __device__ static T doOp(T a, T b) { return a > b ? a : b; } +}; + +template +struct WaveOpMin +{ + __inline__ __device__ static T getInitial(T a, bool exclusive = false); + __inline__ __device__ static T doOp(T a, T b) { return a < b ? a : b; } +}; + +// Compact specializations using macro for getInitial +#define SLANG_WAVE_MIN_SPEC(T, EXCL_VAL) \ + template<> \ + __inline__ __device__ T WaveOpMin::getInitial(T a, bool exclusive) \ + { \ + return exclusive ? (EXCL_VAL) : a; \ + } + +#define SLANG_WAVE_MAX_SPEC(T, EXCL_VAL) \ + template<> \ + __inline__ __device__ T WaveOpMax::getInitial(T a, bool exclusive) \ + { \ + return exclusive ? (EXCL_VAL) : a; \ + } + +// Min specializations (exclusive identity = max value) +SLANG_WAVE_MIN_SPEC(float, SLANG_INFINITY) +SLANG_WAVE_MIN_SPEC(double, SLANG_INFINITY) +SLANG_WAVE_MIN_SPEC(int, 0x7FFFFFFF) +SLANG_WAVE_MIN_SPEC(uint, 0xFFFFFFFF) +SLANG_WAVE_MIN_SPEC(char, (char)0x7F) +SLANG_WAVE_MIN_SPEC(int8_t, (int8_t)0x7F) +SLANG_WAVE_MIN_SPEC(uint8_t, (uint8_t)0xFF) +SLANG_WAVE_MIN_SPEC(int16_t, (int16_t)0x7FFF) +SLANG_WAVE_MIN_SPEC(uint16_t, (uint16_t)0xFFFF) +SLANG_WAVE_MIN_SPEC(int64_t, 0x7FFFFFFFFFFFFFFFLL) +SLANG_WAVE_MIN_SPEC(uint64_t, 0xFFFFFFFFFFFFFFFFULL) +#if SLANG_CUDA_ENABLE_HALF +SLANG_WAVE_MIN_SPEC(__half, __ushort_as_half(0x7BFF)) +#endif + +// Max specializations (exclusive identity = min value) +SLANG_WAVE_MAX_SPEC(float, -SLANG_INFINITY) +SLANG_WAVE_MAX_SPEC(double, -SLANG_INFINITY) +SLANG_WAVE_MAX_SPEC(int, (int)0x80000000) +SLANG_WAVE_MAX_SPEC(uint, 0) +SLANG_WAVE_MAX_SPEC(char, (char)0x80) +SLANG_WAVE_MAX_SPEC(int8_t, (int8_t)0x80) +SLANG_WAVE_MAX_SPEC(uint8_t, 0) +SLANG_WAVE_MAX_SPEC(int16_t, (int16_t)0x8000) +SLANG_WAVE_MAX_SPEC(uint16_t, 0) +SLANG_WAVE_MAX_SPEC(int64_t, (int64_t)0x8000000000000000LL) +SLANG_WAVE_MAX_SPEC(uint64_t, 0) +#if SLANG_CUDA_ENABLE_HALF +SLANG_WAVE_MAX_SPEC(__half, __ushort_as_half(0xFBFF)) +#endif + +#undef SLANG_WAVE_MIN_SPEC +#undef SLANG_WAVE_MAX_SPEC + +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 char Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uchar Type; +}; +template<> +struct ElementTypeTrait +{ + typedef short Type; +}; +template<> +struct ElementTypeTrait +{ + typedef ushort Type; +}; +#if SLANG_CUDA_ENABLE_HALF +template<> +struct ElementTypeTrait<__half> +{ + typedef __half Type; +}; +#endif + +// 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; +}; + +// Additional vector types +template<> +struct ElementTypeTrait +{ + typedef char Type; +}; +template<> +struct ElementTypeTrait +{ + typedef char Type; +}; +template<> +struct ElementTypeTrait +{ + typedef char Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uchar Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uchar Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uchar Type; +}; +template<> +struct ElementTypeTrait +{ + typedef short Type; +}; +template<> +struct ElementTypeTrait +{ + typedef short Type; +}; +template<> +struct ElementTypeTrait +{ + typedef short Type; +}; +template<> +struct ElementTypeTrait +{ + typedef ushort Type; +}; +template<> +struct ElementTypeTrait +{ + typedef ushort Type; +}; +template<> +struct ElementTypeTrait +{ + typedef ushort Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint64_t Type; +}; +#if SLANG_CUDA_ENABLE_HALF +template<> +struct ElementTypeTrait<__half2> +{ + typedef __half Type; +}; +template<> +struct ElementTypeTrait<__half3> +{ + typedef __half Type; +}; +template<> +struct ElementTypeTrait<__half4> +{ + typedef __half Type; +}; +#endif + +// Matrix +template +struct ElementTypeTrait> +{ + typedef T Type; +}; + +// Scalar +template +__device__ T _waveReduceScalar(WarpMask mask, T val) +{ + const int offsetSize = _waveCalcPow2Offset(mask); + if (offsetSize > 0) + { + // Fast path O(log2(activeLanes)) + for (int offset = offsetSize >> 1; offset > 0; offset >>= 1) + { + val = INTF::doOp(val, __shfl_xor_sync(mask, val, offset)); + } + } + else if (!_waveIsSingleLane(mask)) + { + T result = INTF::getInitial(val); + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + // Broadcast (can also broadcast to self) + result = INTF::doOp(result, __shfl_sync(mask, val, srcLane)); + remaining &= ~laneBit; + } + return result; + } + return val; +} + + +// Multiple values +template +__device__ void _waveReduceMultiple(WarpMask mask, T* val) +{ + const int offsetSize = _waveCalcPow2Offset(mask); + if (offsetSize > 0) + { + // Fast path O(log2(activeLanes)) + for (int offset = offsetSize >> 1; offset > 0; offset >>= 1) + { + for (size_t i = 0; i < COUNT; ++i) + { + val[i] = INTF::doOp(val[i], __shfl_xor_sync(mask, val[i], offset)); + } + } + } + else if (!_waveIsSingleLane(mask)) + { + // Copy the original + T originalVal[COUNT]; + for (size_t i = 0; i < COUNT; ++i) + { + const T v = val[i]; + originalVal[i] = v; + val[i] = INTF::getInitial(v); + } + + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + // 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)); + } + remaining &= ~laneBit; + } + } +} + +template +__device__ void _waveReduceMultiple(WarpMask mask, T* val) +{ + 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 _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 _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 _waveMin(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); +} + +template<> +__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); +} + +template<> +__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); +} + +template<> +__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); +} + +template<> +__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); +} +#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 _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 _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 _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__ 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) +{ + typedef typename ElementTypeTrait::Type ElemType; + const size_t count = sizeof(T) / sizeof(ElemType); + int pred; + const ElemType* src = (const ElemType*)&inVal; + for (size_t i = 0; i < count; ++i) + { + __match_all_sync(mask, src[i], &pred); + if (pred == 0) + { + return false; + } + } + return true; +} + +template +__inline__ __device__ T _waveReadFirst(WarpMask mask, T val) +{ + const int lowestLaneId = __ffs(mask) - 1; + return __shfl_sync(mask, val, lowestLaneId); +} + +template +__inline__ __device__ T _waveReadFirstMultiple(WarpMask mask, T inVal) +{ + typedef typename ElementTypeTrait::Type ElemType; + const size_t count = sizeof(T) / sizeof(ElemType); + T outVal; + const ElemType* src = (const ElemType*)&inVal; + ElemType* dst = (ElemType*)&outVal; + const int lowestLaneId = __ffs(mask) - 1; + for (size_t i = 0; i < count; ++i) + { + dst[i] = __shfl_sync(mask, src[i], lowestLaneId); + } + return outVal; +} + +template +__inline__ __device__ T _waveShuffleMultiple(WarpMask mask, T inVal, int lane) +{ + typedef typename ElementTypeTrait::Type ElemType; + const size_t count = sizeof(T) / sizeof(ElemType); + T outVal; + const ElemType* src = (const ElemType*)&inVal; + ElemType* dst = (ElemType*)&outVal; + for (size_t i = 0; i < count; ++i) + { + dst[i] = __shfl_sync(mask, src[i], lane); + } + return outVal; +} + +// 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 +__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) + { + const T readVal = __shfl_up_sync(mask, result, i, offsetSize); + if (laneId >= i) + { + result = INTF::doOp(result, readVal); + } + } + // Remove val from the result, by applyin inverse + result = INTF::doInverse(result, val); + } + else + { + result = INTF::getInitial(val); + if (!_waveIsSingleLane(mask)) + { + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + // 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) + { + result = INTF::doOp(result, readValue); + } + remaining &= ~laneBit; + } + } + } + return result; +} + + +// This implementation separately tracks the value to be propogated, and the value +// 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); + 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) + { + const T readVal = __shfl_up_sync(mask, val, i, offsetSize); + if (laneId >= i) + { + result = INTF::doOp(result, readVal); + val = INTF::doOp(val, readVal); + } + } + } + else + { + if (!_waveIsSingleLane(mask)) + { + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + // 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) + { + result = INTF::doOp(result, readValue); + } + remaining &= ~laneBit; + } + } + } + return result; +} + + +template +__device__ T _waveOpCopy(T* dst, const T* src) +{ + for (size_t j = 0; j < COUNT; ++j) + { + dst[j] = src[j]; + } +} + + +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 +__device__ T _waveOpSetInitial(T* out, const T* val) +{ + for (size_t j = 0; j < COUNT; ++j) + { + out[j] = INTF::getInitial(val[j]); + } +} + +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) + { + // 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 + // work as expected with everything in lock step. + for (size_t j = 0; j < COUNT; ++j) + { + const T readVal = __shfl_up_sync(mask, val[j], i, offsetSize); + if (laneId >= i) + { + val[j] = INTF::doOp(val[j], readVal); + } + } + } + // Remove originalVal from the result, by applyin inverse + _waveOpDoInverse(val, originalVal); + } + else + { + _waveOpSetInitial(val, val); + if (!_waveIsSingleLane(mask)) + { + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + + for (size_t j = 0; j < COUNT; ++j) + { + // 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) + { + val[j] = INTF::doOp(val[j], readValue); + } + remaining &= ~laneBit; + } + } + } + } +} + +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 (size_t j = 0; j < COUNT; ++j) + { + const T readVal = __shfl_up_sync(mask, work[j], i, offsetSize); + if (laneId >= i) + { + work[j] = INTF::doOp(work[j], readVal); + val[j] = INTF::doOp(val[j], readVal); + } + } + } + } + else + { + if (!_waveIsSingleLane(mask)) + { + int remaining = mask; + while (remaining) + { + const int laneBit = remaining & -remaining; + // Get the sourceLane + const int srcLane = __ffs(laneBit) - 1; + + for (size_t j = 0; j < COUNT; ++j) + { + // 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) + { + val[j] = INTF::doOp(val[j], readValue); + } + } + remaining &= ~laneBit; + } + } + } +} + +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); + 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); + 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); + 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); + return val; +} + +template +__inline__ __device__ T _wavePrefixMin(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixMax(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixMinMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); + return val; +} + +template +__inline__ __device__ T _wavePrefixMaxMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); + return val; +} + +// Wrapper structures for exclusive operations that use the overloaded getInitial method +template +struct WaveOpExclusiveMin +{ + __inline__ __device__ static T getInitial(T a) { return WaveOpMin::getInitial(a, true); } + __inline__ __device__ static T doOp(T a, T b) { return WaveOpMin::doOp(a, b); } +}; + +template +struct WaveOpExclusiveMax +{ + __inline__ __device__ static T getInitial(T a) { return WaveOpMax::getInitial(a, true); } + __inline__ __device__ static T doOp(T a, T b) { return WaveOpMax::doOp(a, b); } +}; + +// Inclusive prefix min/max functions (for WaveMultiPrefixInclusive*) +template +__inline__ __device__ T _wavePrefixInclusiveMin(WarpMask mask, T val) +{ + return _wavePrefixMin(mask, val); +} + +template +__inline__ __device__ T _wavePrefixInclusiveMax(WarpMask mask, T val) +{ + return _wavePrefixMax(mask, val); +} + +template +__inline__ __device__ T _wavePrefixInclusiveMinMultiple(WarpMask mask, T val) +{ + return _wavePrefixMinMultiple(mask, val); +} + +template +__inline__ __device__ T _wavePrefixInclusiveMaxMultiple(WarpMask mask, T val) +{ + return _wavePrefixMaxMultiple(mask, val); +} + +// Explicit exclusive prefix min/max functions (for WaveMultiPrefixExclusive*) +template +__inline__ __device__ T _wavePrefixExclusiveMin(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixExclusiveMax(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixExclusiveMinMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); + return val; +} + +template +__inline__ __device__ T _wavePrefixExclusiveMaxMultiple(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) +{ + int pred; + return make_uint4(__match_all_sync(mask, val, &pred), 0, 0, 0); +} + +template +__inline__ __device__ uint4 _waveMatchMultiple(WarpMask mask, const T& inVal) +{ + typedef typename ElementTypeTrait::Type ElemType; + const size_t count = sizeof(T) / sizeof(ElemType); + int pred; + const ElemType* src = (const ElemType*)&inVal; + uint matchBits = 0xffffffff; + for (size_t i = 0; i < count && matchBits; ++i) + { + matchBits = matchBits & __match_all_sync(mask, src[i], &pred); + } + return make_uint4(matchBits, 0, 0, 0); +} + +__inline__ __device__ uint getAt(dim3 a, int b) +{ + SLANG_PRELUDE_ASSERT(b >= 0 && b < 3); + return (&a.x)[b]; +} +__inline__ __device__ uint3 operator*(uint3 a, dim3 b) +{ + uint3 r; + r.x = a.x * b.x; + r.y = a.y * b.y; + r.z = a.z * b.z; + return r; +} + +template +__inline__ __device__ TResult slang_bit_cast(TInput val) +{ + return *(TResult*)(&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. +*/ +struct UniformEntryPointParams; +struct UniformState; + +// ---------------------- OptiX Ray Payload -------------------------------------- +#ifdef SLANG_CUDA_ENABLE_OPTIX + +struct RayDesc +{ + float3 Origin; + float TMin; + float3 Direction; + float TMax; +}; + +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); + return ptr; +} + +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() +{ + const uint32_t u0 = optixGetPayload_0(); + const uint32_t u1 = optixGetPayload_1(); + return unpackOptiXRayPayloadPointer(u0, u1); +} + +// Maximum number of 32-bit registers for OptiX payload (32 registers = 128 bytes) +static constexpr size_t kMaxOptiXPayloadRegisters = 32; + +// Helper to pack/unpack payload to/from registers for small payloads (<= 128 bytes) +template +struct PayloadRegisters +{ + uint32_t regs[N > 0 ? N : 1]; + + __forceinline__ __device__ void pack(const T& payload) { memcpy(regs, &payload, sizeof(T)); } + + __forceinline__ __device__ void unpack(T& payload) { memcpy(&payload, regs, sizeof(T)); } +}; + +// Internal helper to call optixTrace with the right number of register arguments +template +__forceinline__ __device__ void optixTraceWithRegs( + OptixTraversableHandle AccelerationStructure, + float3 Origin, + float3 Direction, + float TMin, + float TMax, + float Time, + uint32_t InstanceInclusionMask, + uint32_t RayFlags, + uint32_t RayContributionToHitGroupIndex, + uint32_t MultiplierForGeometryContributionToHitGroupIndex, + uint32_t MissShaderIndex, + PayloadRegisters& pr) +{ + // Call optixTrace with the appropriate number of payload registers + if constexpr (N == 0) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex); + } + else if constexpr (N == 1) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0]); + } + else if constexpr (N == 2) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1]); + } + else if constexpr (N == 3) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2]); + } + else if constexpr (N == 4) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3]); + } + else if constexpr (N == 5) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4]); + } + else if constexpr (N == 6) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5]); + } + else if constexpr (N == 7) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6]); + } + else if constexpr (N == 8) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7]); + } + else if constexpr (N <= 16) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15]); + } + else if constexpr (N <= kMaxOptiXPayloadRegisters) + { + optixTrace( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15], + pr.regs[16], + pr.regs[17], + pr.regs[18], + pr.regs[19], + pr.regs[20], + pr.regs[21], + pr.regs[22], + pr.regs[23], + pr.regs[24], + pr.regs[25], + pr.regs[26], + pr.regs[27], + pr.regs[28], + pr.regs[29], + pr.regs[30], + pr.regs[31]); + } +} + +template +__forceinline__ __device__ void optixTrace( + OptixTraversableHandle AccelerationStructure, + uint32_t RayFlags, + uint32_t InstanceInclusionMask, + uint32_t RayContributionToHitGroupIndex, + uint32_t MultiplierForGeometryContributionToHitGroupIndex, + uint32_t MissShaderIndex, + RayDesc Ray, + T* Payload) +{ + constexpr size_t numRegs = (sizeof(T) + 3) / 4; + + if constexpr (numRegs <= kMaxOptiXPayloadRegisters) + { + // Register-based approach for small payloads + PayloadRegisters pr; + pr.pack(*Payload); + + optixTraceWithRegs( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + 0.f, /* Time for motion blur */ + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr); + + // Read back updated payload registers + // Native optixTrace updates regs in place + pr.unpack(*Payload); + } + else + { + // Pointer-based fallback for large payloads + uint32_t r0, r1; + packOptiXRayPayloadPointer((void*)Payload, r0, r1); + optixTrace( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + 0.f, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + r0, + r1); + } +} + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ float4 optixGetSpherePositionAndRadius() +{ + float4 data[1]; + optixGetSphereData(data); + return data[0]; +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ float4 +optixHitObjectGetSpherePositionAndRadius(OptixTraversableHandle* Obj) +{ + float4 data[1]; + optixHitObjectGetSphereData(data); + return data[0]; +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ Matrix optixGetLssPositionsAndRadii() +{ + float4 data[2]; + optixGetLinearCurveVertexData(data); + return makeMatrix(data[0], data[1]); +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ Matrix optixHitObjectGetLssPositionsAndRadii( + OptixTraversableHandle* Obj) +{ + float4 data[2]; + optixHitObjectGetLinearCurveVertexData(data); + return makeMatrix(data[0], data[1]); +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ bool optixIsSphereHit() +{ + return optixGetPrimitiveType() == OPTIX_PRIMITIVE_TYPE_SPHERE; +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ bool optixHitObjectIsSphereHit(OptixTraversableHandle* Obj) +{ + return optixGetPrimitiveType(optixHitObjectGetHitKind()) == OPTIX_PRIMITIVE_TYPE_SPHERE; +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ bool optixIsLSSHit() +{ + return optixGetPrimitiveType() == OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR; +} +#endif + +#if (OPTIX_VERSION >= 90000) +__forceinline__ __device__ bool optixHitObjectIsLSSHit(OptixTraversableHandle* Obj) +{ + return optixGetPrimitiveType(optixHitObjectGetHitKind()) == OPTIX_PRIMITIVE_TYPE_ROUND_LINEAR; +} +#endif + +// Internal helper to call optixTraverse with the right number of register arguments +template +__forceinline__ __device__ void optixTraverseWithRegs( + OptixTraversableHandle AccelerationStructure, + float3 Origin, + float3 Direction, + float TMin, + float TMax, + float Time, + uint32_t InstanceInclusionMask, + uint32_t RayFlags, + uint32_t RayContributionToHitGroupIndex, + uint32_t MultiplierForGeometryContributionToHitGroupIndex, + uint32_t MissShaderIndex, + PayloadRegisters& pr) +{ + // Call optixTraverse with the appropriate number of payload registers + if constexpr (N == 0) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex); + } + else if constexpr (N == 1) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0]); + } + else if constexpr (N == 2) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1]); + } + else if constexpr (N == 3) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2]); + } + else if constexpr (N == 4) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3]); + } + else if constexpr (N == 5) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4]); + } + else if constexpr (N == 6) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5]); + } + else if constexpr (N == 7) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6]); + } + else if constexpr (N == 8) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7]); + } + else if constexpr (N <= 16) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15]); + } + else if constexpr (N <= kMaxOptiXPayloadRegisters) + { + optixTraverse( + AccelerationStructure, + Origin, + Direction, + TMin, + TMax, + Time, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15], + pr.regs[16], + pr.regs[17], + pr.regs[18], + pr.regs[19], + pr.regs[20], + pr.regs[21], + pr.regs[22], + pr.regs[23], + pr.regs[24], + pr.regs[25], + pr.regs[26], + pr.regs[27], + pr.regs[28], + pr.regs[29], + pr.regs[30], + pr.regs[31]); + } +} + +template +__forceinline__ __device__ void optixTraverse( + OptixTraversableHandle AccelerationStructure, + uint32_t RayFlags, + uint32_t InstanceInclusionMask, + uint32_t RayContributionToHitGroupIndex, + uint32_t MultiplierForGeometryContributionToHitGroupIndex, + uint32_t MissShaderIndex, + RayDesc Ray, + T* Payload, + OptixTraversableHandle* hitObj) +{ + constexpr size_t numRegs = (sizeof(T) + 3) / 4; + + if constexpr (numRegs <= kMaxOptiXPayloadRegisters) + { + // Register-based approach for small payloads + PayloadRegisters pr; + pr.pack(*Payload); + + optixTraverseWithRegs( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + 0.f, /* Time for motion blur */ + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr); + + // Read back updated payload registers + // Native optixTrace updates regs in place + pr.unpack(*Payload); + } + else + { + // Pointer-based fallback for large payloads + uint32_t r0, r1; + packOptiXRayPayloadPointer((void*)Payload, r0, r1); + optixTraverse( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + 0.f, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + r0, + r1); + } +} + +template +__forceinline__ __device__ void optixTraverse( + OptixTraversableHandle AccelerationStructure, + uint32_t RayFlags, + uint32_t InstanceInclusionMask, + uint32_t RayContributionToHitGroupIndex, + uint32_t MultiplierForGeometryContributionToHitGroupIndex, + uint32_t MissShaderIndex, + RayDesc Ray, + float RayTime, + T* Payload, + OptixTraversableHandle* hitObj) +{ + constexpr size_t numRegs = (sizeof(T) + 3) / 4; + + if constexpr (numRegs <= kMaxOptiXPayloadRegisters) + { + // Register-based approach for small payloads + PayloadRegisters pr; + pr.pack(*Payload); + + optixTraverseWithRegs( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + RayTime, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + pr); + + // Read back updated payload registers + // Native optixTrace updates regs in place + pr.unpack(*Payload); + } + else + { + // Pointer-based fallback for large payloads + uint32_t r0, r1; + packOptiXRayPayloadPointer((void*)Payload, r0, r1); + optixTraverse( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + RayTime, + InstanceInclusionMask, + RayFlags, + RayContributionToHitGroupIndex, + MultiplierForGeometryContributionToHitGroupIndex, + MissShaderIndex, + r0, + r1); + } +} + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ bool slangOptixHitObjectIsHit(OptixTraversableHandle* hitObj) +{ + return optixHitObjectIsHit(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ bool slangOptixHitObjectIsMiss(OptixTraversableHandle* hitObj) +{ + return optixHitObjectIsMiss(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ bool slangOptixHitObjectIsNop(OptixTraversableHandle* hitObj) +{ + return optixHitObjectIsNop(); +} +#endif + +#if (OPTIX_VERSION >= 90000) +static __forceinline__ __device__ uint +slangOptixHitObjectGetClusterId(OptixTraversableHandle* hitObj) +{ + return optixHitObjectGetClusterId(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ void optixMakeMissHitObject( + uint MissShaderIndex, + RayDesc Ray, + OptixTraversableHandle* missObj) +{ + optixMakeMissHitObject( + MissShaderIndex, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + 0.f /* rayTime */ +#if (OPTIX_VERSION >= 90000) + , + OPTIX_RAY_FLAG_NONE /* rayFlags*/ +#endif + ); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ void optixMakeMissHitObject( + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime, + OptixTraversableHandle* missObj) +{ + optixMakeMissHitObject( + MissShaderIndex, + Ray.Origin, + Ray.Direction, + Ray.TMin, + Ray.TMax, + CurrentTime +#if (OPTIX_VERSION >= 90000) + , + OPTIX_RAY_FLAG_NONE /* rayFlags*/ +#endif + ); +} +#endif + +#if (OPTIX_VERSION >= 90000) +template +static __forceinline__ __device__ void optixMakeHitObject( + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + T attr, + OptixTraversableHandle* handle) +{ + OptixTraverseData data{}; + optixHitObjectGetTraverseData(&data); + optixMakeHitObject( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + 0.f, + OPTIX_RAY_FLAG_NONE, /* rayFlags*/ + data, + nullptr, /*OptixTraversableHandle* transforms*/ + 0 /*numTransforms */); +} +#elif (OPTIX_VERSION >= 80100) +template +static __forceinline__ __device__ void optixMakeHitObject( + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + T attr, + OptixTraversableHandle* handle) +{ + // OptiX 8.1 version: call native optixMakeHitObject directly + optixMakeHitObject( + AccelerationStructure, // handle + Ray.Origin, // rayOrigin + Ray.Direction, // rayDirection + Ray.TMin, // tmin + Ray.TMax, // tmax + 0.f, // rayTime + RayContributionToHitGroupIndex, // sbtOffset + MultiplierForGeometryContributionToHitGroupIndex, // sbtStride + InstanceIndex, // instIdx + nullptr, // transforms + 0, // numTransforms + GeometryIndex, // sbtGASIdx + PrimitiveIndex, // primIdx + HitKind // hitKind + /* no attributes passed - empty variadic pack */ + ); +} +#endif + +#if (OPTIX_VERSION >= 90000) +template +static __forceinline__ __device__ void optixMakeHitObject( + uint HitGroupRecordIndex, + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + T attr, + OptixTraversableHandle* handle) +{ + OptixTraverseData data{}; + optixHitObjectGetTraverseData(&data); + optixMakeHitObject( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + 0.f, + OPTIX_RAY_FLAG_NONE, /* rayFlags*/ + data, + nullptr, /*OptixTraversableHandle* transforms*/ + 0 /*numTransforms */); +} +#elif (OPTIX_VERSION >= 80100) +template +static __forceinline__ __device__ void optixMakeHitObject( + uint HitGroupRecordIndex, + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + T attr, + OptixTraversableHandle* handle) +{ + // OptiX 8.1 version: call optixMakeHitObjectWithRecord directly + optixMakeHitObjectWithRecord( + AccelerationStructure, // handle + Ray.Origin, // rayOrigin + Ray.Direction, // rayDirection + Ray.TMin, // tmin + Ray.TMax, // tmax + 0.f, // rayTime + HitGroupRecordIndex, // sbtRecordIndex + InstanceIndex, // instIdx + nullptr, // transforms + 0, // numTransforms + GeometryIndex, // sbtGASIdx + PrimitiveIndex, // primIdx + HitKind // hitKind + /* no attributes passed - empty variadic pack */ + ); +} +#endif + +#if (OPTIX_VERSION >= 90000) +template +static __forceinline__ __device__ void optixMakeHitObject( + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + float CurrentTime, + T attr, + OptixTraversableHandle* handle) +{ + OptixTraverseData data{}; + optixHitObjectGetTraverseData(&data); + optixMakeHitObject( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + CurrentTime, + OPTIX_RAY_FLAG_NONE, /* rayFlags*/ + data, + nullptr, /*OptixTraversableHandle* transforms*/ + 0 /*numTransforms */); +} +#elif (OPTIX_VERSION >= 80100) +template +static __forceinline__ __device__ void optixMakeHitObject( + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + float CurrentTime, + T attr, + OptixTraversableHandle* handle) +{ + // OptiX 8.1 version: call native optixMakeHitObject directly + optixMakeHitObject( + AccelerationStructure, // handle + Ray.Origin, // rayOrigin + Ray.Direction, // rayDirection + Ray.TMin, // tmin + Ray.TMax, // tmax + CurrentTime, // rayTime + RayContributionToHitGroupIndex, // sbtOffset + MultiplierForGeometryContributionToHitGroupIndex, // sbtStride + InstanceIndex, // instIdx + nullptr, // transforms + 0, // numTransforms + GeometryIndex, // sbtGASIdx + PrimitiveIndex, // primIdx + HitKind // hitKind + /* no attributes passed - empty variadic pack */ + ); +} +#endif + +#if (OPTIX_VERSION >= 90000) +template +static __forceinline__ __device__ void optixMakeHitObject( + uint HitGroupRecordIndex, + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + float CurrentTime, + T attr, + OptixTraversableHandle* handle) +{ + OptixTraverseData data{}; + optixHitObjectGetTraverseData(&data); + optixMakeHitObject( + AccelerationStructure, + Ray.Origin, + Ray.Direction, + Ray.TMin, + CurrentTime, + OPTIX_RAY_FLAG_NONE, /* rayFlags*/ + data, + nullptr, /*OptixTraversableHandle* transforms*/ + 0 /*numTransforms */); +} +#elif (OPTIX_VERSION >= 80100) +template +static __forceinline__ __device__ void optixMakeHitObject( + uint HitGroupRecordIndex, + OptixTraversableHandle AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + float CurrentTime, + T attr, + OptixTraversableHandle* handle) +{ + // OptiX 8.1 version: call optixMakeHitObjectWithRecord directly + optixMakeHitObjectWithRecord( + AccelerationStructure, // handle + Ray.Origin, // rayOrigin + Ray.Direction, // rayDirection + Ray.TMin, // tmin + Ray.TMax, // tmax + CurrentTime, // rayTime + HitGroupRecordIndex, // sbtRecordIndex + InstanceIndex, // instIdx + nullptr, // transforms + 0, // numTransforms + GeometryIndex, // sbtGASIdx + PrimitiveIndex, // primIdx + HitKind // hitKind + /* no attributes passed - empty variadic pack */ + ); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ void slangOptixMakeNopHitObject(OptixTraversableHandle* Obj) +{ + optixMakeNopHitObject(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +// Internal helper to call optixInvoke with the right number of register arguments +template +__forceinline__ __device__ void optixInvokeWithRegs(PayloadRegisters& pr) +{ + if constexpr (N == 0) + { + optixInvoke(); + } + else if constexpr (N == 1) + { + optixInvoke(pr.regs[0]); + } + else if constexpr (N == 2) + { + optixInvoke(pr.regs[0], pr.regs[1]); + } + else if constexpr (N == 3) + { + optixInvoke(pr.regs[0], pr.regs[1], pr.regs[2]); + } + else if constexpr (N == 4) + { + optixInvoke(pr.regs[0], pr.regs[1], pr.regs[2], pr.regs[3]); + } + else if constexpr (N == 5) + { + optixInvoke(pr.regs[0], pr.regs[1], pr.regs[2], pr.regs[3], pr.regs[4]); + } + else if constexpr (N == 6) + { + optixInvoke(pr.regs[0], pr.regs[1], pr.regs[2], pr.regs[3], pr.regs[4], pr.regs[5]); + } + else if constexpr (N == 7) + { + optixInvoke( + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6]); + } + else if constexpr (N == 8) + { + optixInvoke( + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7]); + } + else if constexpr (N <= 16) + { + optixInvoke( + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15]); + } + else if constexpr (N <= kMaxOptiXPayloadRegisters) + { + optixInvoke( + pr.regs[0], + pr.regs[1], + pr.regs[2], + pr.regs[3], + pr.regs[4], + pr.regs[5], + pr.regs[6], + pr.regs[7], + pr.regs[8], + pr.regs[9], + pr.regs[10], + pr.regs[11], + pr.regs[12], + pr.regs[13], + pr.regs[14], + pr.regs[15], + pr.regs[16], + pr.regs[17], + pr.regs[18], + pr.regs[19], + pr.regs[20], + pr.regs[21], + pr.regs[22], + pr.regs[23], + pr.regs[24], + pr.regs[25], + pr.regs[26], + pr.regs[27], + pr.regs[28], + pr.regs[29], + pr.regs[30], + pr.regs[31]); + } +} + +template +static __forceinline__ __device__ void optixInvoke( + OptixTraversableHandle AccelerationStructure, + OptixTraversableHandle* HitOrMiss, + T* Payload) +{ + constexpr size_t numRegs = (sizeof(T) + 3) / 4; + + if constexpr (numRegs <= kMaxOptiXPayloadRegisters) + { + // Register-based approach for small payloads + PayloadRegisters pr; + pr.pack(*Payload); + optixInvokeWithRegs(pr); + // Read back updated payload registers + pr.unpack(*Payload); + } + else + { + // Pointer-based fallback for large payloads + uint32_t r0, r1; + packOptiXRayPayloadPointer((void*)Payload, r0, r1); + optixInvoke(r0, r1); + } +} + +// Overload for empty payloads (when payload is eliminated by type legalization) +static __forceinline__ __device__ void optixInvoke( + OptixTraversableHandle AccelerationStructure, + OptixTraversableHandle* HitOrMiss) +{ + // Call OptiX invoke with no payload for empty payload case + optixInvoke(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ RayDesc optixHitObjectGetRayDesc(OptixTraversableHandle* obj) +{ + RayDesc ray = { + optixHitObjectGetWorldRayOrigin(), + optixHitObjectGetRayTmin(), + optixHitObjectGetWorldRayDirection(), + optixHitObjectGetRayTmax()}; + return ray; +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ uint +slangOptixHitObjectGetInstanceIndex(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetInstanceIndex(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ uint slangOptixHitObjectGetInstanceId(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetInstanceId(); +} +#endif + +#if (OPTIX_VERSION >= 80000) +static __forceinline__ __device__ float slangOptixHitObjectGetRayTime(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetRayTime(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ uint +slangOptixHitObjectGetSbtGASIndex(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetSbtGASIndex(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ uint +slangOptixHitObjectGetPrimitiveIndex(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetPrimitiveIndex(); +} +#endif + +#if (OPTIX_VERSION >= 80100) +template +static __forceinline__ __device__ T optixHitObjectGetAttribute(OptixTraversableHandle* Obj) +{ + constexpr size_t numInts = (sizeof(T) + sizeof(uint32_t) - 1) / + sizeof(uint32_t); // Number of 32-bit values, rounded up + static_assert(numInts <= 8, "Attribute type is too large"); + + // Create an array to hold the attribute values + uint32_t values[numInts == 0 ? 1 : numInts] = {0}; // Ensure we have at least one element + + // Read the appropriate number of attribute registers + if constexpr (numInts > 0) + values[0] = optixHitObjectGetAttribute_0(); + if constexpr (numInts > 1) + values[1] = optixHitObjectGetAttribute_1(); + if constexpr (numInts > 2) + values[2] = optixHitObjectGetAttribute_2(); + if constexpr (numInts > 3) + values[3] = optixHitObjectGetAttribute_3(); + if constexpr (numInts > 4) + values[4] = optixHitObjectGetAttribute_4(); + if constexpr (numInts > 5) + values[5] = optixHitObjectGetAttribute_5(); + if constexpr (numInts > 6) + values[6] = optixHitObjectGetAttribute_6(); + if constexpr (numInts > 7) + values[7] = optixHitObjectGetAttribute_7(); + + // Reinterpret the array as the desired type + T result; + memcpy(&result, values, sizeof(T)); + return result; +} +#endif + +#if (OPTIX_VERSION >= 80100) +static __forceinline__ __device__ uint +slangOptixHitObjectGetSbtRecordIndex(OptixTraversableHandle* Obj) +{ + return optixHitObjectGetSbtRecordIndex(); +} +#endif + +#if (OPTIX_VERSION >= 90000) +static __forceinline__ __device__ void slangOptixHitObjectSetSbtRecordIndex( + OptixTraversableHandle* Obj, + uint sbtRecordIndex) +{ + optixHitObjectSetSbtRecordIndex(sbtRecordIndex); +} +#endif + +// HitObject transform matrix wrappers for SER (Shader Execution Reordering) +// These wrappers convert OptiX's float[12] matrix format to Slang's Matrix type +// Available in RG, CH, MS, CC, DC stages per OptiX documentation +// Note: optixHitObjectGetWorldToObjectTransformMatrix/optixHitObjectGetObjectToWorldTransformMatrix +// were added in OptiX 9.0 (not available in 8.0 or 8.1) +#if (OPTIX_VERSION >= 90000) +static __forceinline__ __device__ Matrix slangOptixHitObjectGetWorldToObject( + OptixTraversableHandle* hitObj) +{ + float m[12]; + optixHitObjectGetWorldToObjectTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4, we need to transpose to 4 rows of float3 + return makeMatrix( + make_float3(m[0], m[4], m[8]), + make_float3(m[1], m[5], m[9]), + make_float3(m[2], m[6], m[10]), + make_float3(m[3], m[7], m[11])); +} +#endif + +#if (OPTIX_VERSION >= 90000) +static __forceinline__ __device__ Matrix slangOptixHitObjectGetObjectToWorld( + OptixTraversableHandle* hitObj) +{ + float m[12]; + optixHitObjectGetObjectToWorldTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4, we need to transpose to 4 rows of float3 + return makeMatrix( + make_float3(m[0], m[4], m[8]), + make_float3(m[1], m[5], m[9]), + make_float3(m[2], m[6], m[10]), + make_float3(m[3], m[7], m[11])); +} +#endif + +// OptiX multi-level traversal wrappers +// These wrappers convert OptiX's float[12] matrix pointer returns to Slang's Matrix type +__device__ __forceinline__ Matrix _slang_optixGetInstanceTransformFromHandle( + ulonglong handle) +{ + const float4* m = optixGetInstanceTransformFromHandle(handle); + // OptiX stores matrix as 3 rows of float4 in the array + return makeMatrix(m[0], m[1], m[2]); +} + +__device__ __forceinline__ Matrix _slang_optixGetInstanceInverseTransformFromHandle( + ulonglong handle) +{ + const float4* m = optixGetInstanceInverseTransformFromHandle(handle); + // OptiX stores matrix as 3 rows of float4 in the array + return makeMatrix(m[0], m[1], m[2]); +} + +// OptiX transformation matrix wrappers +// These wrappers convert OptiX's float[12] matrix format to Slang's Matrix type +__device__ __forceinline__ Matrix slangOptixGetObjectToWorldTransformMatrix() +{ + float m[12]; + optixGetObjectToWorldTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4 in the array + return makeMatrix( + make_float4(m[0], m[1], m[2], m[3]), + make_float4(m[4], m[5], m[6], m[7]), + make_float4(m[8], m[9], m[10], m[11])); +} + +__device__ __forceinline__ Matrix slangOptixGetWorldToObjectTransformMatrix() +{ + float m[12]; + optixGetWorldToObjectTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4 in the array + return makeMatrix( + make_float4(m[0], m[1], m[2], m[3]), + make_float4(m[4], m[5], m[6], m[7]), + make_float4(m[8], m[9], m[10], m[11])); +} + +__device__ __forceinline__ Matrix slangOptixGetObjectToWorldTransformMatrix4x3() +{ + float m[12]; + optixGetObjectToWorldTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4, we need to transpose to 4 rows of float3 + return makeMatrix( + make_float3(m[0], m[4], m[8]), + make_float3(m[1], m[5], m[9]), + make_float3(m[2], m[6], m[10]), + make_float3(m[3], m[7], m[11])); +} + +__device__ __forceinline__ Matrix slangOptixGetWorldToObjectTransformMatrix4x3() +{ + float m[12]; + optixGetWorldToObjectTransformMatrix(m); + // OptiX stores matrix as 3 rows of float4, we need to transpose to 4 rows of float3 + return makeMatrix( + make_float3(m[0], m[4], m[8]), + make_float3(m[1], m[5], m[9]), + make_float3(m[2], m[6], m[10]), + make_float3(m[3], m[7], m[11])); +} + +#else +// Define OptixTraversableHandle even if OptiX is not enabled. +// This allows RaytracingAccelerationStructure to be properly reflected in non-OptiX code. +typedef unsigned long long OptixTraversableHandle; +#endif +static const int kSlangTorchTensorMaxDim = 5; + +// TensorView +// NOTE: If you change this struct's layout, also update the hard-coded size/alignment +// in _createTypeLayout() in slang-type-layout.cpp. +struct TensorView +{ + uint8_t* data; + uint32_t strides[kSlangTorchTensorMaxDim]; + uint32_t sizes[kSlangTorchTensorMaxDim]; + uint32_t dimensionCount; + + template + __device__ T* data_ptr() + { + return reinterpret_cast(data); + } + + template + __device__ T* data_ptr_at(uint32_t index) + { + uint64_t offset = strides[0] * index; + return reinterpret_cast(data + offset); + } + + template + __device__ T* data_ptr_at(uint2 index) + { + uint64_t offset = strides[0] * index.x + strides[1] * index.y; + return reinterpret_cast(data + offset); + } + + template + __device__ T* data_ptr_at(uint3 index) + { + uint64_t offset = strides[0] * index.x + strides[1] * index.y + strides[2] * index.z; + return reinterpret_cast(data + offset); + } + + 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; + return reinterpret_cast(data + offset); + } + + template + __device__ T* data_ptr_at(uint index[N]) + { + uint64_t offset = 0; + for (unsigned int i = 0; i < N; ++i) + { + offset += strides[i] * index[i]; + } + return reinterpret_cast(data + offset); + } + + template + __device__ T& load(uint32_t x) + { + return *reinterpret_cast(data + strides[0] * x); + } + template + __device__ T& load(uint32_t x, uint32_t y) + { + return *reinterpret_cast(data + strides[0] * x + strides[1] * y); + } + template + __device__ T& load(uint2 index) + { + return *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y); + } + template + __device__ T& load(uint32_t x, uint32_t y, uint32_t z) + { + return *reinterpret_cast(data + strides[0] * x + strides[1] * y + strides[2] * z); + } + template + __device__ T& load(uint3 index) + { + 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); + } + 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); + } + 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); + } + + // Generic version of load + template + __device__ T& load(uint index[N]) + { + uint64_t offset = 0; + for (unsigned int i = 0; i < N; ++i) + { + offset += strides[i] * index[i]; + } + return *reinterpret_cast(data + offset); + } + + template + __device__ void store(uint32_t x, T val) + { + *reinterpret_cast(data + strides[0] * x) = val; + } + template + __device__ void store(uint32_t x, uint32_t y, T val) + { + *reinterpret_cast(data + strides[0] * x + strides[1] * y) = val; + } + template + __device__ void store(uint2 index, T val) + { + *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y) = val; + } + template + __device__ void store(uint32_t x, uint32_t y, uint32_t z, T val) + { + *reinterpret_cast(data + strides[0] * x + strides[1] * y + strides[2] * z) = val; + } + template + __device__ void store(uint3 index, T 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) + { + *reinterpret_cast( + data + strides[0] * x + strides[1] * y + strides[2] * z + strides[3] * w) = val; + } + 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; + } + 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; + } + + // Generic version + template + __device__ void store(uint index[N], T val) + { + uint64_t offset = 0; + for (unsigned int i = 0; i < N; ++i) + { + offset += strides[i] * index[i]; + } + *reinterpret_cast(data + offset) = val; + } +}; + +// Implementations for texture fetch/load functions using tex PTX intrinsics +// These are used for read-only texture access with integer coordinates. + +// 1D is not supported via PTX. Keeping the implementation below in case it ever gets supported. +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T tex1Dfetch_int(CUtexObject texObj, int x, int mip) +{ + // TODO: static_assert(false) can fail on some compilers, even if template is not instantiated. + // We should check for this in hlsl.meta.slang instead. + // static_assert(false, "CUDA does not support fetching from 1D textures"); +} + +#if 0 +#define SLANG_TEX1DFETCH_INT_IMPL(T, dtype, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T tex1Dfetch_int(CUtexObject texObj, int x, int mip) \ + { \ + T result; \ + [[maybe_unused]] T stub; \ + asm("tex.level.1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5}], %6;" \ + : c(result), c(stub), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(mip)); \ + return result; \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 tex1Dfetch_int(CUtexObject texObj, int x, int mip) \ + { \ + T result_x, result_y; \ + [[maybe_unused]] T stub; \ + asm("tex.level.1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5}], %6;" \ + : c(result_x), c(result_y), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(mip)); \ + return make_##T##2(result_x, result_y); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 tex1Dfetch_int(CUtexObject texObj, int x, int mip) \ + { \ + T result_x, result_y, result_z, result_w; \ + asm("tex.level.1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5}], %6;" \ + : c(result_x), c(result_y), c(result_z), c(result_w) \ + : "l"(texObj), "r"(x), "r"(mip)); \ + return make_##T##4(result_x, result_y, result_z, result_w); \ + } + +SLANG_TEX1DFETCH_INT_IMPL(float, "f32", "=f") +SLANG_TEX1DFETCH_INT_IMPL(uint, "u32", "=r") +SLANG_TEX1DFETCH_INT_IMPL(int, "s32", "=r") +#endif + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T tex2Dfetch_int(CUtexObject texObj, int x, int y, int mip); + +#define SLANG_TEX2DFETCH_INT_IMPL(T, dtype, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T tex2Dfetch_int(CUtexObject texObj, int x, int y, int mip) \ + { \ + T result; \ + [[maybe_unused]] T stub; \ + asm("tex.level.2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result), c(stub), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(y), "r"(mip)); \ + return result; \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##2 tex2Dfetch_int(CUtexObject texObj, int x, int y, int mip) \ + { \ + T result_x, result_y; \ + [[maybe_unused]] T stub; \ + asm("tex.level.2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result_x), c(result_y), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(y), "r"(mip)); \ + return make_##T##2(result_x, result_y); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##4 tex2Dfetch_int(CUtexObject texObj, int x, int y, int mip) \ + { \ + T result_x, result_y, result_z, result_w; \ + asm("tex.level.2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result_x), c(result_y), c(result_z), c(result_w) \ + : "l"(texObj), "r"(x), "r"(y), "r"(mip)); \ + return make_##T##4(result_x, result_y, result_z, result_w); \ + } + +SLANG_TEX2DFETCH_INT_IMPL(float, "f32", "=f") +SLANG_TEX2DFETCH_INT_IMPL(uint, "u32", "=r") +SLANG_TEX2DFETCH_INT_IMPL(int, "s32", "=r") + + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T +tex3Dfetch_int(CUtexObject texObj, int x, int y, int z, int mip); + +#define SLANG_TEX3DFETCH_INT_IMPL(T, dtype, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T \ + tex3Dfetch_int(CUtexObject texObj, int x, int y, int z, int mip) \ + { \ + T result; \ + [[maybe_unused]] T stub; \ + asm("tex.level.3d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result), c(stub), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(y), "r"(z), "r"(z) /* ignored */, "r"(mip)); \ + return result; \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##2 tex3Dfetch_int(CUtexObject texObj, int x, int y, int z, int mip) \ + { \ + T result_x, result_y; \ + [[maybe_unused]] T stub; \ + asm("tex.level.3d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result_x), c(result_y), c(stub), c(stub) \ + : "l"(texObj), "r"(x), "r"(y), "r"(z), "r"(z) /* ignored */, "r"(mip)); \ + return make_##T##2(result_x, result_y); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##4 tex3Dfetch_int(CUtexObject texObj, int x, int y, int z, int mip) \ + { \ + T result_x, result_y, result_z, result_w; \ + asm("tex.level.3d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result_x), c(result_y), c(result_z), c(result_w) \ + : "l"(texObj), "r"(x), "r"(y), "r"(z), "r"(z) /* ignored */, "r"(mip)); \ + return make_##T##4(result_x, result_y, result_z, result_w); \ + } + +SLANG_TEX3DFETCH_INT_IMPL(float, "f32", "=f") +SLANG_TEX3DFETCH_INT_IMPL(uint, "u32", "=r") +SLANG_TEX3DFETCH_INT_IMPL(int, "s32", "=r") + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T +tex1DArrayfetch_int(CUtexObject texObj, int x, int layer, int mip); + +#define SLANG_TEX1DARRAYFETCH_INT_IMPL(T, dtype, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T \ + tex1DArrayfetch_int(CUtexObject texObj, int x, int layer, int mip) \ + { \ + T result; \ + [[maybe_unused]] T stub; \ + asm("tex.level.a1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result), c(stub), c(stub), c(stub) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(mip)); \ + return result; \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##2 tex1DArrayfetch_int(CUtexObject texObj, int x, int layer, int mip) \ + { \ + T result_x, result_y; \ + [[maybe_unused]] T stub; \ + asm("tex.level.a1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result_x), c(result_y), c(stub), c(stub) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(mip)); \ + return make_##T##2(result_x, result_y); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##4 tex1DArrayfetch_int(CUtexObject texObj, int x, int layer, int mip) \ + { \ + T result_x, result_y, result_z, result_w; \ + asm("tex.level.a1d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6}], %7;" \ + : c(result_x), c(result_y), c(result_z), c(result_w) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(mip)); \ + return make_##T##4(result_x, result_y, result_z, result_w); \ + } + +SLANG_TEX1DARRAYFETCH_INT_IMPL(float, "f32", "=f") +SLANG_TEX1DARRAYFETCH_INT_IMPL(uint, "u32", "=r") +SLANG_TEX1DARRAYFETCH_INT_IMPL(int, "s32", "=r") + +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL T +tex2DArrayfetch_int(CUtexObject texObj, int x, int y, int layer, int mip); + +#define SLANG_TEX2DARRAYFETCH_INT_IMPL(T, dtype, c) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T \ + tex2DArrayfetch_int(CUtexObject texObj, int x, int y, int layer, int mip) \ + { \ + T result; \ + [[maybe_unused]] T stub; \ + asm("tex.level.a2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result), c(stub), c(stub), c(stub) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(y), "r"(layer) /* ignored */, "r"(mip)); \ + return result; \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##2 tex2DArrayfetch_int(CUtexObject texObj, int x, int y, int layer, int mip) \ + { \ + T result_x, result_y; \ + [[maybe_unused]] T stub; \ + asm("tex.level.a2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result_x), c(result_y), c(stub), c(stub) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(y), "r"(layer) /* ignored */, "r"(mip)); \ + return make_##T##2(result_x, result_y); \ + } \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL \ + T##4 tex2DArrayfetch_int(CUtexObject texObj, int x, int y, int layer, int mip) \ + { \ + T result_x, result_y, result_z, result_w; \ + asm("tex.level.a2d.v4." dtype ".s32 {%0, %1, %2, %3}, [%4, {%5, %6, %7, %8}], %9;" \ + : c(result_x), c(result_y), c(result_z), c(result_w) \ + : "l"(texObj), "r"(layer), "r"(x), "r"(y), "r"(layer) /* ignored */, "r"(mip)); \ + return make_##T##4(result_x, result_y, result_z, result_w); \ + } + +SLANG_TEX2DARRAYFETCH_INT_IMPL(float, "f32", "=f") +SLANG_TEX2DARRAYFETCH_INT_IMPL(uint, "u32", "=r") +SLANG_TEX2DARRAYFETCH_INT_IMPL(int, "s32", "=r") + +// Wave rotate helper functions - templated approach +#define SLANG_WARP_FULL_MASK 0xFFFFFFFF + +// Macro-based wave rotate implementation following codebase patterns +#define SLANG_WAVE_ROTATE_IMPL(T) \ + __device__ __forceinline__ T##2 _slang_waveRotate(T##2 value, unsigned int delta) \ + { \ + return make_##T##2( \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.x, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.y, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE)); \ + } \ + __device__ __forceinline__ T##3 _slang_waveRotate(T##3 value, unsigned int delta) \ + { \ + return make_##T##3( \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.x, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.y, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.z, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE)); \ + } \ + __device__ __forceinline__ T##4 _slang_waveRotate(T##4 value, unsigned int delta) \ + { \ + return make_##T##4( \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.x, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.y, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.z, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE), \ + (T)__shfl_sync( \ + SLANG_WARP_FULL_MASK, \ + value.w, \ + (_getLaneId() + delta) % SLANG_CUDA_WARP_SIZE)); \ + } + +// Generate wave rotate functions for all standard vector types +SLANG_WAVE_ROTATE_IMPL(uint) +SLANG_WAVE_ROTATE_IMPL(int) +SLANG_WAVE_ROTATE_IMPL(float) +SLANG_WAVE_ROTATE_IMPL(short) +SLANG_WAVE_ROTATE_IMPL(ushort) +SLANG_WAVE_ROTATE_IMPL(char) +SLANG_WAVE_ROTATE_IMPL(uchar) +SLANG_WAVE_ROTATE_IMPL(longlong) +SLANG_WAVE_ROTATE_IMPL(ulonglong) + +#ifdef SLANG_CUDA_ENABLE_HALF +SLANG_WAVE_ROTATE_IMPL(__half) +#endif + +// Special handling for boolean vectors (requires int conversion) +__device__ __forceinline__ bool2 _slang_waveRotate(bool2 value, unsigned int delta) +{ + int2 intValue = make_int2((int)value.x, (int)value.y); + int2 result = _slang_waveRotate(intValue, delta); + return make_bool2((bool)result.x, (bool)result.y); +} + +__device__ __forceinline__ bool3 _slang_waveRotate(bool3 value, unsigned int delta) +{ + int3 intValue = make_int3((int)value.x, (int)value.y, (int)value.z); + int3 result = _slang_waveRotate(intValue, delta); + return make_bool3((bool)result.x, (bool)result.y, (bool)result.z); +} + +__device__ __forceinline__ bool4 _slang_waveRotate(bool4 value, unsigned int delta) +{ + int4 intValue = make_int4((int)value.x, (int)value.y, (int)value.z, (int)value.w); + int4 result = _slang_waveRotate(intValue, delta); + return make_bool4((bool)result.x, (bool)result.y, (bool)result.z, (bool)result.w); +} + +#undef SLANG_WAVE_ROTATE_IMPL + +// Quad control operations for CUDA +__device__ __forceinline__ bool _slang_quadAny(bool expr) +{ + // Get values from all 4 lanes in the quad + bool v0 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 0); + bool v1 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 1); + bool v2 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 2); + bool v3 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 3); + return v0 || v1 || v2 || v3; +} + +__device__ __forceinline__ bool _slang_quadAll(bool expr) +{ + // Get values from all 4 lanes in the quad + bool v0 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 0); + bool v1 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 1); + bool v2 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 2); + bool v3 = __shfl_sync(0xFFFFFFFF, expr, (_getLaneId() & 0xFFFFFFFC) | 3); + return v0 && v1 && v2 && v3; +} + +// Clustered wave rotate operations for CUDA +// Clustered rotate rotates values within clusters of specified size +#define SLANG_WAVE_CLUSTERED_ROTATE_IMPL(T) \ + __device__ __forceinline__ T \ + _slang_waveClusteredRotate(T value, unsigned int delta, unsigned int clusterSize) \ + { \ + unsigned int laneId = _getLaneId(); \ + unsigned int clusterStart = (laneId / clusterSize) * clusterSize; \ + unsigned int targetLane = clusterStart + ((laneId - clusterStart + delta) % clusterSize); \ + return __shfl_sync(SLANG_WARP_FULL_MASK, value, targetLane); \ + } \ + __device__ __forceinline__ \ + T##2 _slang_waveClusteredRotate(T##2 value, unsigned int delta, unsigned int clusterSize) \ + { \ + unsigned int laneId = _getLaneId(); \ + unsigned int clusterStart = (laneId / clusterSize) * clusterSize; \ + unsigned int targetLane = clusterStart + ((laneId - clusterStart + delta) % clusterSize); \ + return make_##T##2( \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.x, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.y, targetLane)); \ + } \ + __device__ __forceinline__ \ + T##3 _slang_waveClusteredRotate(T##3 value, unsigned int delta, unsigned int clusterSize) \ + { \ + unsigned int laneId = _getLaneId(); \ + unsigned int clusterStart = (laneId / clusterSize) * clusterSize; \ + unsigned int targetLane = clusterStart + ((laneId - clusterStart + delta) % clusterSize); \ + return make_##T##3( \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.x, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.y, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.z, targetLane)); \ + } \ + __device__ __forceinline__ \ + T##4 _slang_waveClusteredRotate(T##4 value, unsigned int delta, unsigned int clusterSize) \ + { \ + unsigned int laneId = _getLaneId(); \ + unsigned int clusterStart = (laneId / clusterSize) * clusterSize; \ + unsigned int targetLane = clusterStart + ((laneId - clusterStart + delta) % clusterSize); \ + return make_##T##4( \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.x, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.y, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.z, targetLane), \ + (T)__shfl_sync(SLANG_WARP_FULL_MASK, value.w, targetLane)); \ + } + +// Generate clustered wave rotate functions for all standard types +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(uint) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(int) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(float) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(short) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(ushort) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(char) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(uchar) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(longlong) +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(ulonglong) + +#ifdef SLANG_CUDA_ENABLE_HALF +SLANG_WAVE_CLUSTERED_ROTATE_IMPL(__half) +#endif + +// Special handling for boolean clustered rotate +__device__ __forceinline__ bool _slang_waveClusteredRotate( + bool value, + unsigned int delta, + unsigned int clusterSize) +{ + int intValue = (int)value; + int result = _slang_waveClusteredRotate(intValue, delta, clusterSize); + return (bool)result; +} + +__device__ __forceinline__ bool2 +_slang_waveClusteredRotate(bool2 value, unsigned int delta, unsigned int clusterSize) +{ + int2 intValue = make_int2((int)value.x, (int)value.y); + int2 result = _slang_waveClusteredRotate(intValue, delta, clusterSize); + return make_bool2((bool)result.x, (bool)result.y); +} + +__device__ __forceinline__ bool3 +_slang_waveClusteredRotate(bool3 value, unsigned int delta, unsigned int clusterSize) +{ + int3 intValue = make_int3((int)value.x, (int)value.y, (int)value.z); + int3 result = _slang_waveClusteredRotate(intValue, delta, clusterSize); + return make_bool3((bool)result.x, (bool)result.y, (bool)result.z); +} + +__device__ __forceinline__ bool4 +_slang_waveClusteredRotate(bool4 value, unsigned int delta, unsigned int clusterSize) +{ + int4 intValue = make_int4((int)value.x, (int)value.y, (int)value.z, (int)value.w); + int4 result = _slang_waveClusteredRotate(intValue, delta, clusterSize); + return make_bool4((bool)result.x, (bool)result.y, (bool)result.z, (bool)result.w); +} + +#undef SLANG_WAVE_CLUSTERED_ROTATE_IMPL + +// ---------------------- OptiX Cooperative Vector Wrappers -------------------------------------- +#ifdef SLANG_CUDA_ENABLE_OPTIX + +#if (OPTIX_VERSION >= 90000) + +// Constexpr function to map Slang component type enum to OptiX cooperative vector element type +__host__ __device__ constexpr OptixCoopVecElemType slangToOptixComponentType(unsigned slangEnum) +{ + switch (slangEnum) + { + case 0: + return OPTIX_COOP_VEC_ELEM_TYPE_FLOAT8_E4M3; // FloatE4M3 + case 1: + return OPTIX_COOP_VEC_ELEM_TYPE_FLOAT8_E5M2; // FloatE5M2 + case 2: + return OPTIX_COOP_VEC_ELEM_TYPE_FLOAT16; // Float16 + case 3: + return OPTIX_COOP_VEC_ELEM_TYPE_FLOAT32; // Float32 + case 5: + return OPTIX_COOP_VEC_ELEM_TYPE_INT8; // SignedInt8 + case 7: + return OPTIX_COOP_VEC_ELEM_TYPE_INT32; // SignedInt32 + case 10: + return OPTIX_COOP_VEC_ELEM_TYPE_UINT8; // UnsignedInt8 + case 12: + return OPTIX_COOP_VEC_ELEM_TYPE_UINT32; // UnsignedInt32 + default: + return OPTIX_COOP_VEC_ELEM_TYPE_FLOAT32; // Default + } +} + +// Constexpr function to map Slang matrix layout enum to OptiX cooperative vector matrix layout +__host__ __device__ constexpr OptixCoopVecMatrixLayout slangToOptixMatrixLayout(unsigned slangEnum) +{ + switch (slangEnum) + { + case 0: + return OPTIX_COOP_VEC_MATRIX_LAYOUT_ROW_MAJOR; // RowMajor + case 1: + return OPTIX_COOP_VEC_MATRIX_LAYOUT_COLUMN_MAJOR; // ColumnMajor + case 2: + return OPTIX_COOP_VEC_MATRIX_LAYOUT_INFERENCING_OPTIMAL; // InferencingOptimal + case 3: + return OPTIX_COOP_VEC_MATRIX_LAYOUT_TRAINING_OPTIMAL; // TrainingOptimal + default: + return OPTIX_COOP_VEC_MATRIX_LAYOUT_ROW_MAJOR; // Default + } +} + +// Wrapper structs to maintain compatibility with existing template-based interface +template +struct SlangToOptixComponentType +{ + static constexpr OptixCoopVecElemType value = slangToOptixComponentType(SlangEnum); +}; + +template +struct SlangToOptixMatrixLayout +{ + static constexpr OptixCoopVecMatrixLayout value = slangToOptixMatrixLayout(SlangEnum); +}; + +// Template trait to extract vector size from OptixCoopVec +// Conditional compilation for NVRTC compatibility +template +struct OptixCoopVecTraits; + +// Template specialization for OptiX's OptixCoopVec - only enabled when cooperative vectors are +// available NVRTC explicitly disables cooperative vectors by setting +// OPTIX_INCLUDE_COOPERATIVE_VECTOR to 0 +#if defined(OPTIX_VERSION) && OPTIX_VERSION > 90000 +template +struct OptixCoopVecTraits> +{ + static constexpr unsigned int size = N; +}; +#endif + +template< + typename VecTOut, + typename VecTIn, + unsigned inputInterpretation, + unsigned matrixInterpretation, + unsigned matrixLayout> +__forceinline__ __device__ VecTOut slangOptixCoopVecMatMul( + const VecTIn& inputVector, + CUdeviceptr matrix, + unsigned matrixOffset, + bool transpose, + unsigned matrixStride) +{ + constexpr unsigned N = OptixCoopVecTraits::size; // Output vector size + constexpr unsigned K = OptixCoopVecTraits::size; // Input vector size + + return optixCoopVecMatMul< + VecTOut, + VecTIn, + SlangToOptixComponentType::value, + SlangToOptixMatrixLayout::value, + false, + N, + K, + SlangToOptixComponentType::value>( + inputVector, + matrix, + matrixOffset, + matrixStride); +} + +// OptiX cooperative vector matrix multiplication wrapper (WITH bias - 6 runtime params) +template< + typename VecTOut, + typename VecTIn, + unsigned inputInterpretation, + unsigned matrixInterpretation, + unsigned matrixLayout, + unsigned biasInterpretation> +__forceinline__ __device__ VecTOut slangOptixCoopVecMatMul( + const VecTIn& inputVector, + CUdeviceptr matrix, + unsigned matrixOffset, + CUdeviceptr bias, + unsigned biasOffset, + unsigned matrixStride) +{ + constexpr unsigned N = OptixCoopVecTraits::size; // Output vector size + constexpr unsigned K = OptixCoopVecTraits::size; // Input vector size + + // Call OptiX SDK with bias (6 runtime parameters) + return optixCoopVecMatMul< + VecTOut, + VecTIn, + SlangToOptixComponentType::value, + SlangToOptixMatrixLayout::value, + false, + N, + K, + SlangToOptixComponentType::value, + SlangToOptixComponentType::value>( + inputVector, + matrix, + matrixOffset, + bias, + biasOffset, + matrixStride); +} + +// OptiX cooperative vector matrix multiplication wrapper (WITHOUT bias, 4 runtime params - +// StructuredBuffer variant) +template< + typename VecTOut, + typename VecTIn, + unsigned inputInterpretation, + unsigned matrixInterpretation, + unsigned matrixLayout> +__forceinline__ __device__ VecTOut slangOptixCoopVecMatMul( + const VecTIn& inputVector, + CUdeviceptr matrix, + unsigned matrixOffset, + unsigned matrixStride) +{ + constexpr unsigned N = OptixCoopVecTraits::size; // Output vector size + constexpr unsigned K = OptixCoopVecTraits::size; // Input vector size + + // Call OptiX SDK without bias and without transpose (4 runtime parameters) + return optixCoopVecMatMul< + VecTOut, + VecTIn, + SlangToOptixComponentType::value, + SlangToOptixMatrixLayout::value, + false, + N, + K, + SlangToOptixComponentType::value>( + inputVector, + matrix, + matrixOffset, + matrixStride); +} + +#endif // (OPTIX_VERSION >= 90000) + +#endif // SLANG_CUDA_ENABLE_OPTIX + + +// This implementation can only be enabled on CUDA Toolkit 12.5+ +#if ((__CUDACC_VER_MAJOR__ > 12) || (__CUDACC_VER_MAJOR__ == 12 && __CUDACC_VER_MINOR__ >= 5)) || \ + (CUDA_VERSION >= 12050) +// The reason we have to implement our own wmma operation on CUDA is the interface +// design of cooperative_matrix on Vulkan is quite different from CUDA WMMA API, where +// SPIRV spec doesn't require the matrix layout during declaration of the cooperative_matrix, +// instead it is only required during load/store operations. However, in CUDA WMMA API, the layout +// has to be specified during the declaration of the fragment itself. Slang's interface desgin +// is more similar to SPIRV's cooperative_matrix. So to bridge this gap, we have to implement our +// wmma operation by using PTX wmma instructions directly, because PTX wmma instructions is quite +// similar to SPIRV's cooperative_matrix spec. +namespace Slang_CUDA_WMMA +{ + +// Enums for template specialization +enum MatrixUse : int +{ + MatrixA = 0, + MatrixB = 1, + MatrixC = 2, + MatrixD = 3, +}; + +enum Layout : int +{ + RowMajor = 0, + ColMajor = 1 +}; + +enum ShapeCombination : int +{ + m16n16k16 = 0, + m8n32k16 = 1, + m32n8k16 = 2 +}; + +// ==================================================================================== +// PTX Name Helpers +// ==================================================================================== + +// Shape names +template +struct PtxShapeName; +template<> +struct PtxShapeName<16, 16, 16> +{ + static constexpr const char name[] = "m16n16k16"; +}; +template<> +struct PtxShapeName<8, 32, 16> +{ + static constexpr const char name[] = "m8n32k16"; +}; +template<> +struct PtxShapeName<32, 8, 16> +{ + static constexpr const char name[] = "m32n8k16"; +}; + +// Matrix role names +template +struct PtxMatrixRoleName; +template<> +struct PtxMatrixRoleName +{ + static constexpr const char name[] = "a"; +}; +template<> +struct PtxMatrixRoleName +{ + static constexpr const char name[] = "b"; +}; +template<> +struct PtxMatrixRoleName +{ + static constexpr const char name[] = "c"; +}; +template<> +struct PtxMatrixRoleName +{ + static constexpr const char name[] = "d"; +}; + +// Layout names +template +struct PtxLayoutName; +template<> +struct PtxLayoutName +{ + static constexpr const char name[] = "row"; +}; +template<> +struct PtxLayoutName +{ + static constexpr const char name[] = "col"; +}; + +// Type names +template +struct PtxTypeName; + +#if SLANG_CUDA_ENABLE_HALF +template<> +struct PtxTypeName +{ + static constexpr const char name[] = "f16"; +}; +#endif // #if SLANG_CUDA_ENABLE_HALF + +#if SLANG_CUDA_ENABLE_FP8 +template<> +struct PtxTypeName<__nv_fp8_e4m3> +{ + static constexpr const char name[] = "f8e4m3"; +}; +template<> +struct PtxTypeName<__nv_fp8_e5m2> +{ + static constexpr const char name[] = "f8e5m2"; +}; +#endif // #if SLANG_CUDA_ENABLE_FP8 + +#if SLANG_CUDA_ENABLE_BF16 +template<> +struct PtxTypeName<__nv_bfloat16> +{ + static constexpr const char name[] = "bf16"; +}; +#endif + +template<> +struct PtxTypeName +{ + static constexpr const char name[] = "f32"; +}; +template<> +struct PtxTypeName +{ + static constexpr const char name[] = "s8"; +}; +template<> +struct PtxTypeName +{ + static constexpr const char name[] = "u8"; +}; +template<> +struct PtxTypeName +{ + static constexpr const char name[] = "s32"; +}; + +// ==================================================================================== +// Register Counts for different matrices +// ==================================================================================== +template +struct RegisterCount; + +#if SLANG_CUDA_ENABLE_HALF +// Half (f16) - 8 regs for A/B, 4 regs for C/D +template +struct RegisterCount +{ + static constexpr int value = 8; +}; +template +struct RegisterCount +{ + static constexpr int value = 8; +}; +template +struct RegisterCount +{ + static constexpr int value = 4; +}; +template +struct RegisterCount +{ + static constexpr int value = 4; +}; +#endif // #if SLANG_CUDA_ENABLE_HALF + +#if SLANG_CUDA_ENABLE_BF16 +// bfloat16 - 8 regs for A/B, 4 regs for C/D +template +struct RegisterCount<__nv_bfloat16, M, N, K, MatrixUse::MatrixA> +{ + static constexpr int value = 8; +}; +template +struct RegisterCount<__nv_bfloat16, M, N, K, MatrixUse::MatrixB> +{ + static constexpr int value = 8; +}; +template +struct RegisterCount<__nv_bfloat16, M, N, K, MatrixUse::MatrixC> +{ + static constexpr int value = 4; +}; +template +struct RegisterCount<__nv_bfloat16, M, N, K, MatrixUse::MatrixD> +{ + static constexpr int value = 4; +}; +#endif // #if SLANG_CUDA_ENABLE_BF16 + +// Float (f32) - 8 regs for C/D only +template +struct RegisterCount +{ + static constexpr int value = 8; +}; +template +struct RegisterCount +{ + static constexpr int value = 8; +}; + +// Int32 (s32) - 8 regs for C/D (accumulator for int8 operations) +template +struct RegisterCount +{ + static constexpr int value = 8; +}; +template +struct RegisterCount +{ + static constexpr int value = 8; +}; + +// Uint8 (u8) - varies by shape +template<> +struct RegisterCount +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 1; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 1; +}; + +// Int8 (s8) - same as u8 +template<> +struct RegisterCount +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 1; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount +{ + static constexpr int value = 1; +}; + +#if SLANG_CUDA_ENABLE_FP8 +// fp8 - same as u8 +template<> +struct RegisterCount<__nv_fp8_e4m3, 16, 16, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount<__nv_fp8_e4m3, 16, 16, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount<__nv_fp8_e4m3, 8, 32, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 1; +}; +template<> +struct RegisterCount<__nv_fp8_e4m3, 8, 32, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount<__nv_fp8_e4m3, 32, 8, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount<__nv_fp8_e4m3, 32, 8, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 1; +}; + +template<> +struct RegisterCount<__nv_fp8_e5m2, 16, 16, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount<__nv_fp8_e5m2, 16, 16, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 2; +}; +template<> +struct RegisterCount<__nv_fp8_e5m2, 8, 32, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 1; +}; +template<> +struct RegisterCount<__nv_fp8_e5m2, 8, 32, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount<__nv_fp8_e5m2, 32, 8, 16, MatrixUse::MatrixA> +{ + static constexpr int value = 4; +}; +template<> +struct RegisterCount<__nv_fp8_e5m2, 32, 8, 16, MatrixUse::MatrixB> +{ + static constexpr int value = 1; +}; +#endif + + +// ==================================================================================== +// Saturation at the output for integer MMA +// ==================================================================================== +template +struct IsSaturated; + +template<> +struct IsSaturated +{ + static constexpr const char name[] = ".satfinite"; +}; + +template<> +struct IsSaturated +{ + static constexpr const char name[] = ""; +}; + +// ==================================================================================== +// WMMA Load - Inline PTX +// ==================================================================================== + +template +__device__ inline void wmmaLoad(uint32_t* regs, const void* ptr, int stride) +{ + constexpr int nregs = RegisterCount::value; + + switch (nregs) + { + case 1: + asm volatile("wmma.load.%1.sync.aligned.%2.%3.%4 {%0}, [%5], %6;\n" + : "=r"(regs[0]) + : "C"(PtxMatrixRoleName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(stride)); + break; + + case 2: + asm volatile("wmma.load.%2.sync.aligned.%3.%4.%5 {%0, %1}, [%6], %7;\n" + : "=r"(regs[0]), "=r"(regs[1]) + : "C"(PtxMatrixRoleName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(stride)); + break; + + case 4: + asm volatile("wmma.load.%4.sync.aligned.%5.%6.%7 {%0, %1, %2, %3}, [%8], %9;\n" + : "=r"(regs[0]), "=r"(regs[1]), "=r"(regs[2]), "=r"(regs[3]) + : "C"(PtxMatrixRoleName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(stride)); + break; + + case 8: + asm volatile("wmma.load.%8.sync.aligned.%9.%10.%11 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, [%12], %13;\n" + : "=r"(regs[0]), + "=r"(regs[1]), + "=r"(regs[2]), + "=r"(regs[3]), + "=r"(regs[4]), + "=r"(regs[5]), + "=r"(regs[6]), + "=r"(regs[7]) + : "C"(PtxMatrixRoleName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(stride)); + break; + } +} + +// ==================================================================================== +// WMMA Store - Inline PTX +// ==================================================================================== + +template +__device__ inline void wmmaStore(void* ptr, const uint32_t* regs, int stride) +{ + constexpr int nregs = RegisterCount::value; + + switch (nregs) + { + case 4: + asm volatile("wmma.store.d.sync.aligned.%0.%1.%2 [%3], {%4, %5, %6, %7}, %8;\n" + : + : "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(regs[0]), + "r"(regs[1]), + "r"(regs[2]), + "r"(regs[3]), + "r"(stride)); + break; + + case 8: + asm volatile("wmma.store.d.sync.aligned.%0.%1.%2 " + "[%3], {%4, %5, %6, %7, %8, %9, %10, %11}, %12;\n" + : + : "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "l"(ptr), + "r"(regs[0]), + "r"(regs[1]), + "r"(regs[2]), + "r"(regs[3]), + "r"(regs[4]), + "r"(regs[5]), + "r"(regs[6]), + "r"(regs[7]), + "r"(stride)); + break; + } +} + +// Helper to get M, N, K from ShapeCombination +template +struct ShapeToMNK; +template<> +struct ShapeToMNK +{ + static constexpr int M = 16, N = 16, K = 16; +}; +template<> +struct ShapeToMNK +{ + static constexpr int M = 8, N = 32, K = 16; +}; +template<> +struct ShapeToMNK +{ + static constexpr int M = 32, N = 8, K = 16; +}; + +template +inline unsigned __device__ Pack32Helper(T value); + +#if SLANG_CUDA_ENABLE_HALF +template<> +inline unsigned __device__ Pack32Helper(half value) +{ + return __half_as_ushort(value) | (__half_as_ushort(value) << 16); +}; +#endif + +template<> +inline unsigned __device__ Pack32Helper(float value) +{ + return __float_as_uint(value); +}; + +template<> +inline unsigned __device__ Pack32Helper(int value) +{ + return (unsigned)value; +}; +template<> +inline unsigned __device__ Pack32Helper(char value) +{ + return value << 24 | value << 16 | value << 8 | value; +}; +template<> +inline unsigned __device__ Pack32Helper(unsigned char value) +{ + return value << 24 | value << 16 | value << 8 | value; +}; + + +// The dimensions of the fragment are specified by M, N, K which are totally determined during +// compile time, so slang already did the pre-filter on the shape & type combination. +template +struct WmmaFragment +{ + __device__ WmmaFragment() {} + __device__ WmmaFragment(T scalarValue) { fill(scalarValue); } + + typedef WmmaFragment This; + template + void __device__ Store(RWStructuredBuffer buffer, uint element, uint stride) + { + Store(buffer.data, element, stride); + } + + template + static This __device__ Load(StructuredBuffer buffer, uint element, uint stride) + { + return Load(buffer.data, element, stride); + } + + // There is no fill intrinsic in PTX wmma, so it's just 'move' value + // to the fragment registers. + void __device__ fill(T value) + { + unsigned packed = Pack32Helper(value); + constexpr int nregs = RegisterCount::value; + for (int i = 0; i < nregs; i++) + { + regs[i] = packed; + } + } + + __device__ This operator*(T b) + { + This result; + + // This loop will be unrolled by the compiler becuase nregs is constexpr + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) * b); + } + return result; + } + + __device__ This operator*(const This& b) + { + This result; + + // This loop will be unrolled by the compiler becuase nregs is constexpr + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) * b.get(i)); + } + return result; + } + + __device__ This operator/(const This& other) + { + This result; + + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) / other.get(i)); + } + return result; + } + + __device__ This operator-(const This& other) + { + This result; + + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) - other.get(i)); + } + return result; + } + + __device__ This operator-() + { + This result; + + for (int i = 0; i < GetLength(); i++) + { + result.set(i, -get(i)); + } + return result; + } + + __device__ This operator+(const This& other) + { + This result; + + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) + other.get(i)); + } + return result; + } + + __device__ This operator%(const This& other) + { + This result; + + for (int i = 0; i < GetLength(); i++) + { + result.set(i, get(i) % other.get(i)); + } + return result; + } + + template + __device__ void copyFrom(const WmmaFragment& other) + { + // If the data type is different, we need to copy element by element. + // Since the shape of two matrices are the same, they have the same + // number of elements. + for (int i = 0; i < GetLength(); i++) + { + set(i, static_cast(other.get(i))); + } + } + + // Get element by index (handles bit-level access for packed types) + // For example: u8/s8 matrices have 4 elements per register (32-bit) + // - index 0: bits [0:7] of regs[0] + // - index 1: bits [8:15] of regs[0] + // - index 2: bits [16:23] of regs[0] + // - index 3: bits [24:31] of regs[0] + __device__ T get(int index) const + { + if constexpr (sizeof(T) == 4) + { + // T is 32-bit (float or int32): 1 element per register + T v; + memcpy(&v, ®s[index], 4); + return v; + } + else if constexpr (sizeof(T) == 2) + { + // T is 16-bit (half): 2 elements per register + // Elements per register: [0:15] and [16:31] + int regIndex = index / 2; + int elementOffset = index % 2; + int bitOffset = elementOffset * 16; + uint32_t extracted = (regs[regIndex] >> bitOffset) & 0xFFFF; + uint16_t value16 = static_cast(extracted); + T v; + memcpy(&v, &value16, 2); + return v; + } + else if constexpr (sizeof(T) == 1) + { + // T is 8-bit (int8_t, uint8_t): 4 elements per register + // Elements per register: [0:7], [8:15], [16:23], [24:31] + int regIndex = index / 4; + int elementOffset = index % 4; + int bitOffset = elementOffset * 8; + uint32_t extracted = (regs[regIndex] >> bitOffset) & 0xFF; + uint8_t value8 = static_cast(extracted); + return *reinterpret_cast(&value8); + } + } + + // Set element by index (handles bit-level access for packed types) + __device__ void set(int index, T value) + { + if constexpr (sizeof(T) == 4) + { + // T is 32-bit (float or int32): 1 element per register + memcpy(®s[index], &value, 4); + } + else if constexpr (sizeof(T) == 2) + { + // T is 16-bit (half): 2 elements per register + int regIndex = index / 2; + int elementOffset = index % 2; + int bitOffset = elementOffset * 16; + uint32_t mask = 0xFFFF; + uint16_t value16; + memcpy(&value16, &value, 2); + + // Clear the bits at the target position + regs[regIndex] &= ~(mask << bitOffset); + + // Set the new value + regs[regIndex] |= (static_cast(value16) << bitOffset); + } + else if constexpr (sizeof(T) == 1) + { + // T is 8-bit (int8_t, uint8_t): 4 elements per register + int regIndex = index / 4; + int elementOffset = index % 4; + int bitOffset = elementOffset * 8; + uint32_t mask = 0xFF; + uint8_t value8 = *reinterpret_cast(&value); + + // Clear the bits at the target position + regs[regIndex] &= ~(mask << bitOffset); + + // Set the new value + regs[regIndex] |= (static_cast(value8) << bitOffset); + } + } + + template + void __device__ Store(T* buffer, uint element, uint stride) + { + // Force compile-time check, so we know the template parameter comibination is valid. + (void)RegisterCount::value; + wmmaStore(buffer + element, regs, stride); + } + + template + void __device__ Store(U* buffer, uint stride) + { + // Force compile-time check, so we know the template parameter comibination is valid. + (void)RegisterCount::value; + wmmaStore(buffer, regs, stride * sizeof(U) / sizeof(T)); + } + + template + static This __device__ Load(T* buffer, uint element, uint stride) + { + WmmaFragment fragment; + + // Force compile-time check, so we know the template parameter comibination is valid. + (void)RegisterCount::value; + wmmaLoad(fragment.regs, buffer + element, stride); + fragment.m_layout = layout; + return fragment; + } + + template + static This __device__ Load(U* buffer, uint stride) + { + WmmaFragment fragment; + + // Force compile-time check, so we know the template parameter comibination is valid. + (void)RegisterCount::value; + wmmaLoad(fragment.regs, buffer, stride * sizeof(U) / sizeof(T)); + fragment.m_layout = layout; + return fragment; + } + + static constexpr __device__ uint32_t GetLength() { return This::elements_per_thread; } + + // For referencing those template parameters outside the struct + using ElementType = T; + static constexpr int m_M = M; + static constexpr int m_N = N; + static constexpr int m_K = K; + Layout m_layout = Layout::RowMajor; + + // Register Count requirement + static constexpr int RegsCount = RegisterCount::value; + unsigned regs[RegsCount] = {}; + + static constexpr uint32_t elements_per_thread = RegsCount * (4 / sizeof(T)); +}; + +// ==================================================================================== +// FP16 MMA Helper - For half x half inputs +// Specialized on CType and DType (accumulator types) +// +// PTX Syntax: wmma.mma.sync.aligned.alayout.blayout.shape.dtype.ctype d, a, b, c; +// where: +// dtype = type of d (output accumulator): {.f16, .f32} +// ctype = type of c (input accumulator): {.f16, .f32} +// +// Note: Types of a and b are implicitly f16 (not specified in PTX instruction). +// Shape (M, N, K) is passed as template parameters, so one template handles all shapes. +// We only need to specialize on CType and DType. +// ==================================================================================== + +template +struct Fp16MMAHelper; + +#if SLANG_CUDA_ENABLE_HALF +// Specialization: c=half, d=half (f16.f16) +template +struct Fp16MMAHelper +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%4.%5.%6.%7.%8 " + "{%0, %1, %2, %3}, " + "{%9, %10, %11, %12, %13, %14, %15, %16}, " + "{%17, %18, %19, %20, %21, %22, %23, %24}, " + "{%25, %26, %27, %28};\n" + : "=r"(d.regs[0]), "=r"(d.regs[1]), "=r"(d.regs[2]), "=r"(d.regs[3]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(a.regs[2]), + "r"(a.regs[3]), + "r"(a.regs[4]), + "r"(a.regs[5]), + "r"(a.regs[6]), + "r"(a.regs[7]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(b.regs[2]), + "r"(b.regs[3]), + "r"(b.regs[4]), + "r"(b.regs[5]), + "r"(b.regs[6]), + "r"(b.regs[7]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3])); + } +}; + +// Specialization: c=float, d=half (f16.f32) +template +struct Fp16MMAHelper +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%4.%5.%6.%7.%8 " + "{%0, %1, %2, %3}, " + "{%9, %10, %11, %12, %13, %14, %15, %16}, " + "{%17, %18, %19, %20, %21, %22, %23, %24}, " + "{%25, %26, %27, %28, %29, %30, %31, %32};\n" + : "=r"(d.regs[0]), "=r"(d.regs[1]), "=r"(d.regs[2]), "=r"(d.regs[3]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(a.regs[2]), + "r"(a.regs[3]), + "r"(a.regs[4]), + "r"(a.regs[5]), + "r"(a.regs[6]), + "r"(a.regs[7]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(b.regs[2]), + "r"(b.regs[3]), + "r"(b.regs[4]), + "r"(b.regs[5]), + "r"(b.regs[6]), + "r"(b.regs[7]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3]), + "r"(c.regs[4]), + "r"(c.regs[5]), + "r"(c.regs[6]), + "r"(c.regs[7])); + } +}; + +// Specialization: c=half, d=float (f32.f16) +template +struct Fp16MMAHelper +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%8.%9.%10.%11.%12 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, " + "{%13, %14, %15, %16, %17, %18, %19, %20}, " + "{%21, %22, %23, %24, %25, %26, %27, %28}, " + "{%29, %30, %31, %32};\n" + : "=r"(d.regs[0]), + "=r"(d.regs[1]), + "=r"(d.regs[2]), + "=r"(d.regs[3]), + "=r"(d.regs[4]), + "=r"(d.regs[5]), + "=r"(d.regs[6]), + "=r"(d.regs[7]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(a.regs[2]), + "r"(a.regs[3]), + "r"(a.regs[4]), + "r"(a.regs[5]), + "r"(a.regs[6]), + "r"(a.regs[7]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(b.regs[2]), + "r"(b.regs[3]), + "r"(b.regs[4]), + "r"(b.regs[5]), + "r"(b.regs[6]), + "r"(b.regs[7]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3])); + } +}; + +// Specialization: c=float, d=float (f32.f32) +template +struct Fp16MMAHelper +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%8.%9.%10.%11.%12 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, " + "{%13, %14, %15, %16, %17, %18, %19, %20}, " + "{%21, %22, %23, %24, %25, %26, %27, %28}, " + "{%29, %30, %31, %32, %33, %34, %35, %36};\n" + : "=r"(d.regs[0]), + "=r"(d.regs[1]), + "=r"(d.regs[2]), + "=r"(d.regs[3]), + "=r"(d.regs[4]), + "=r"(d.regs[5]), + "=r"(d.regs[6]), + "=r"(d.regs[7]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(a.regs[2]), + "r"(a.regs[3]), + "r"(a.regs[4]), + "r"(a.regs[5]), + "r"(a.regs[6]), + "r"(a.regs[7]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(b.regs[2]), + "r"(b.regs[3]), + "r"(b.regs[4]), + "r"(b.regs[5]), + "r"(b.regs[6]), + "r"(b.regs[7]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3]), + "r"(c.regs[4]), + "r"(c.regs[5]), + "r"(c.regs[6]), + "r"(c.regs[7])); + } +}; +#endif // #if SLANG_CUDA_ENABLE_HALF + +// ==================================================================================== +// Integer MMA Helper - For int8/uint8 inputs +// Specialized on shape (register counts depend on shape) +// +// PTX Syntax: wmma.mma.sync.aligned.alayout.blayout.shape.s32.atype.btype.s32{.satfinite} d, a, b, +// c; +// where: +// atype = type of a (input matrix A): {.s8, .u8} +// btype = type of b (input matrix B): {.s8, .u8} +// C and D are always s32 (int32) +// +// Note: Unlike FP16, integer operations explicitly specify atype and btype in the instruction. +// We must specialize on shape because register counts vary: +// m16n16k16: a=2 regs, b=2 regs +// m8n32k16: a=1 reg, b=4 regs +// m32n8k16: a=4 regs, b=1 reg +// C and D always use 8 registers (int32). +// ==================================================================================== + +template< + typename AType, + typename BType, + ShapeCombination shape, + Layout LayoutA, + Layout LayoutB, + bool saturatingAccumulation> +struct IntegerMMAHelper; + +// Specialization: m16n16k16 (a=2 regs, b=2 regs) +template< + typename AType, + typename BType, + Layout LayoutA, + Layout LayoutB, + bool saturatingAccumulation> +struct IntegerMMAHelper< + AType, + BType, + ShapeCombination::m16n16k16, + LayoutA, + LayoutB, + saturatingAccumulation> +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%8.%9.%10.s32.%11.%12.s32%13 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, " + "{%14, %15}, " + "{%16, %17}, " + "{%18, %19, %20, %21, %22, %23, %24, %25};\n" + : "=r"(d.regs[0]), + "=r"(d.regs[1]), + "=r"(d.regs[2]), + "=r"(d.regs[3]), + "=r"(d.regs[4]), + "=r"(d.regs[5]), + "=r"(d.regs[6]), + "=r"(d.regs[7]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName<16, 16, 16>::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "C"(IsSaturated::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3]), + "r"(c.regs[4]), + "r"(c.regs[5]), + "r"(c.regs[6]), + "r"(c.regs[7])); + } +}; + +// Specialization: m8n32k16 (a=1 reg, b=4 regs) +template< + typename AType, + typename BType, + Layout LayoutA, + Layout LayoutB, + bool saturatingAccumulation> +struct IntegerMMAHelper< + AType, + BType, + ShapeCombination::m8n32k16, + LayoutA, + LayoutB, + saturatingAccumulation> +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%8.%9.%10.s32.%11.%12.s32%13 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, " + "{%14}, " + "{%15, %16, %17, %18}, " + "{%19, %20, %21, %22, %23, %24, %25, %26};\n" + : "=r"(d.regs[0]), + "=r"(d.regs[1]), + "=r"(d.regs[2]), + "=r"(d.regs[3]), + "=r"(d.regs[4]), + "=r"(d.regs[5]), + "=r"(d.regs[6]), + "=r"(d.regs[7]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName<8, 32, 16>::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "C"(IsSaturated::name), + "r"(a.regs[0]), + "r"(b.regs[0]), + "r"(b.regs[1]), + "r"(b.regs[2]), + "r"(b.regs[3]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3]), + "r"(c.regs[4]), + "r"(c.regs[5]), + "r"(c.regs[6]), + "r"(c.regs[7])); + } +}; + +// Specialization: m32n8k16 (a=4 regs, b=1 reg) +template< + typename AType, + typename BType, + Layout LayoutA, + Layout LayoutB, + bool saturatingAccumulation> +struct IntegerMMAHelper< + AType, + BType, + ShapeCombination::m32n8k16, + LayoutA, + LayoutB, + saturatingAccumulation> +{ + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c) + { + asm volatile("wmma.mma.sync.aligned.%8.%9.%10.s32.%11.%12.s32%13 " + "{%0, %1, %2, %3, %4, %5, %6, %7}, " + "{%14, %15, %16, %17}, " + "{%18}, " + "{%19, %20, %21, %22, %23, %24, %25, %26};\n" + : "=r"(d.regs[0]), + "=r"(d.regs[1]), + "=r"(d.regs[2]), + "=r"(d.regs[3]), + "=r"(d.regs[4]), + "=r"(d.regs[5]), + "=r"(d.regs[6]), + "=r"(d.regs[7]) + : "C"(PtxLayoutName::name), + "C"(PtxLayoutName::name), + "C"(PtxShapeName<32, 8, 16>::name), + "C"(PtxTypeName::name), + "C"(PtxTypeName::name), + "C"(IsSaturated::name), + "r"(a.regs[0]), + "r"(a.regs[1]), + "r"(a.regs[2]), + "r"(a.regs[3]), + "r"(b.regs[0]), + "r"(c.regs[0]), + "r"(c.regs[1]), + "r"(c.regs[2]), + "r"(c.regs[3]), + "r"(c.regs[4]), + "r"(c.regs[5]), + "r"(c.regs[6]), + "r"(c.regs[7])); + } +}; + + +// ==================================================================================== +// MMA Helper - Primary Template (dispatcher) +// ==================================================================================== + +template< + typename AType, + typename BType, + typename CType, + typename DType, + ShapeCombination shape, + Layout LayoutA, + Layout LayoutB, + bool saturatingAccumulation> +struct MMAHelper +{ + static constexpr int M = ShapeToMNK::M; + static constexpr int N = ShapeToMNK::N; + static constexpr int K = ShapeToMNK::K; + + __device__ static void eval( + WmmaFragment& d, + const WmmaFragment& a, + const WmmaFragment& b, + const WmmaFragment& c, + bool saturate = false) + { + // Dispatch to appropriate helper based on input types + if constexpr (sizeof(AType) == 2 && sizeof(BType) == 2) + { + // FP16 inputs: dispatch to Fp16MMAHelper + Fp16MMAHelper::eval(d, a, b, c); + } + else + { + // Integer inputs (int8/uint8): dispatch to IntegerMMAHelper + IntegerMMAHelper::eval( + d, + a, + b, + c); + } + } +}; + +// +template< + typename AType, + typename BType, + typename CType, + typename DType, + int M, + int N, + int K, + bool saturatingAccumulation> +WmmaFragment __device__ coopMatMulAdd( + WmmaFragment matA, + WmmaFragment matB, + WmmaFragment matC) +{ + constexpr ShapeCombination shape = (M == 16 && N == 16 && K == 16) ? ShapeCombination::m16n16k16 + : (M == 8 && N == 32 && K == 16) + ? ShapeCombination::m8n32k16 + : ShapeCombination::m32n8k16; + + WmmaFragment matD; + uint32_t encodedLayout = (matA.m_layout == Layout::RowMajor ? 1 : 0) << 1 | + (matB.m_layout == Layout::RowMajor ? 1 : 0); + + switch (encodedLayout) + { + // 00011 + case 0x3: + MMAHelper< + AType, + BType, + CType, + DType, + shape, + Layout::RowMajor, + Layout::RowMajor, + saturatingAccumulation>::eval(matD, matA, matB, matC); + break; + // 00010 + case 0x2: + MMAHelper< + AType, + BType, + CType, + DType, + shape, + Layout::RowMajor, + Layout::ColMajor, + saturatingAccumulation>::eval(matD, matA, matB, matC); + break; + // 0001 + case 0x01: + MMAHelper< + AType, + BType, + CType, + DType, + shape, + Layout::ColMajor, + Layout::RowMajor, + saturatingAccumulation>::eval(matD, matA, matB, matC); + break; + // 0000 + case 0x00: + MMAHelper< + AType, + BType, + CType, + DType, + shape, + Layout::ColMajor, + Layout::ColMajor, + saturatingAccumulation>::eval(matD, matA, matB, matC); + break; + } + + return matD; +} + +} // namespace Slang_CUDA_WMMA +#endif // #if (((__CUDACC_VER_MAJOR__ >=12)&&(__CUDACC_VER_MINOR__>=5)) || (CUDA_VERSION >= 12050)) + +#endif diff --git a/lib/All/slang/include/slang-deprecated.h b/lib/All/slang/include/slang-deprecated.h new file mode 100644 index 0000000..765e328 --- /dev/null +++ b/lib/All/slang/include/slang-deprecated.h @@ -0,0 +1,1704 @@ +#pragma once + +#include "slang.h" + +/* DEPRECATED DEFINITIONS + +Everything in this file represents deprecated APIs/definition that are only +being kept around for source/binary compatibility with old client code. New +code should not use any of these declarations, and the Slang API will drop these +declarations over time. +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /*! + @brief Initialize an instance of the Slang library. + */ + SLANG_API SlangSession* spCreateSession(const char* deprecated = 0); + + /*! + @brief Clean up after an instance of the Slang library. + */ + SLANG_API void spDestroySession(SlangSession* session); + + /** @see slang::IGlobalSession::setSharedLibraryLoader + */ + SLANG_API void spSessionSetSharedLibraryLoader( + SlangSession* session, + ISlangSharedLibraryLoader* loader); + + /** @see slang::IGlobalSession::getSharedLibraryLoader + */ + SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader(SlangSession* session); + + /** @see slang::IGlobalSession::checkCompileTargetSupport + */ + SLANG_API SlangResult + spSessionCheckCompileTargetSupport(SlangSession* session, SlangCompileTarget target); + + /** @see slang::IGlobalSession::checkPassThroughSupport + */ + SLANG_API SlangResult + spSessionCheckPassThroughSupport(SlangSession* session, SlangPassThrough passThrough); + + /** @see slang::IGlobalSession::addBuiltins + */ + SLANG_API void spAddBuiltins( + SlangSession* session, + char const* sourcePath, + char const* sourceString); + + /* @see slang::IGlobalSession::createCompileRequest + */ + 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); + + /*! @see slang::ICompileRequest::setFileSystem */ + SLANG_API void spSetFileSystem(SlangCompileRequest* request, ISlangFileSystem* fileSystem); + + /*! @see slang::ICompileRequest::setCompileFlags */ + SLANG_API void spSetCompileFlags(SlangCompileRequest* request, SlangCompileFlags flags); + + /*! @see slang::ICompileRequest::getCompileFlags */ + SLANG_API SlangCompileFlags spGetCompileFlags(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::setDumpIntermediates */ + SLANG_API void spSetDumpIntermediates(SlangCompileRequest* request, int enable); + + /*! @see slang::ICompileRequest::setDumpIntermediatePrefix */ + 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); + + /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */ + SLANG_API void spSetTargetLineDirectiveMode( + SlangCompileRequest* request, + int targetIndex, + SlangLineDirectiveMode mode); + + /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */ + SLANG_API void spSetTargetForceGLSLScalarBufferLayout( + SlangCompileRequest* request, + int targetIndex, + bool forceScalarLayout); + + /*! @see slang::ICompileRequest::setTargetUseMinimumSlangOptimization */ + SLANG_API void spSetTargetUseMinimumSlangOptimization( + slang::ICompileRequest* request, + int targetIndex, + bool val); + + /*! @see slang::ICompileRequest::setIgnoreCapabilityCheck */ + SLANG_API void spSetIgnoreCapabilityCheck(slang::ICompileRequest* request, bool val); + + /*! @see slang::ICompileRequest::setCodeGenTarget */ + SLANG_API void spSetCodeGenTarget(SlangCompileRequest* request, SlangCompileTarget target); + + /*! @see slang::ICompileRequest::addCodeGenTarget */ + SLANG_API int spAddCodeGenTarget(SlangCompileRequest* request, SlangCompileTarget target); + + /*! @see slang::ICompileRequest::setTargetProfile */ + SLANG_API void spSetTargetProfile( + SlangCompileRequest* request, + int targetIndex, + SlangProfileID profile); + + /*! @see slang::ICompileRequest::setTargetFlags */ + SLANG_API void spSetTargetFlags( + SlangCompileRequest* request, + int targetIndex, + SlangTargetFlags flags); + + + /*! @see slang::ICompileRequest::setTargetFloatingPointMode */ + SLANG_API void spSetTargetFloatingPointMode( + SlangCompileRequest* request, + int targetIndex, + SlangFloatingPointMode mode); + + /*! @see slang::ICompileRequest::addTargetCapability */ + SLANG_API void spAddTargetCapability( + slang::ICompileRequest* request, + int targetIndex, + SlangCapabilityID capability); + + /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */ + SLANG_API void spSetTargetMatrixLayoutMode( + SlangCompileRequest* request, + int targetIndex, + SlangMatrixLayoutMode mode); + + /*! @see slang::ICompileRequest::setMatrixLayoutMode */ + SLANG_API void spSetMatrixLayoutMode(SlangCompileRequest* request, SlangMatrixLayoutMode mode); + + /*! @see slang::ICompileRequest::setDebugInfoLevel */ + SLANG_API void spSetDebugInfoLevel(SlangCompileRequest* request, SlangDebugInfoLevel level); + + /*! @see slang::ICompileRequest::setDebugInfoFormat */ + SLANG_API void spSetDebugInfoFormat(SlangCompileRequest* request, SlangDebugInfoFormat format); + + /*! @see slang::ICompileRequest::setOptimizationLevel */ + SLANG_API void spSetOptimizationLevel( + SlangCompileRequest* request, + SlangOptimizationLevel level); + + + /*! @see slang::ICompileRequest::setOutputContainerFormat */ + SLANG_API void spSetOutputContainerFormat( + SlangCompileRequest* request, + SlangContainerFormat format); + + /*! @see slang::ICompileRequest::setPassThrough */ + SLANG_API void spSetPassThrough(SlangCompileRequest* request, SlangPassThrough passThrough); + + /*! @see slang::ICompileRequest::setDiagnosticCallback */ + SLANG_API void spSetDiagnosticCallback( + SlangCompileRequest* request, + SlangDiagnosticCallback callback, + void const* userData); + + /*! @see slang::ICompileRequest::setWriter */ + SLANG_API void spSetWriter( + SlangCompileRequest* request, + SlangWriterChannel channel, + ISlangWriter* writer); + + /*! @see slang::ICompileRequest::getWriter */ + SLANG_API ISlangWriter* spGetWriter(SlangCompileRequest* request, SlangWriterChannel channel); + + /*! @see slang::ICompileRequest::addSearchPath */ + SLANG_API void spAddSearchPath(SlangCompileRequest* request, const char* searchDir); + + /*! @see slang::ICompileRequest::addPreprocessorDefine */ + SLANG_API void spAddPreprocessorDefine( + SlangCompileRequest* request, + const char* key, + const char* value); + + /*! @see slang::ICompileRequest::processCommandLineArguments */ + SLANG_API SlangResult spProcessCommandLineArguments( + SlangCompileRequest* request, + char const* const* args, + int argCount); + + /*! @see slang::ICompileRequest::addTranslationUnit */ + SLANG_API int spAddTranslationUnit( + SlangCompileRequest* request, + SlangSourceLanguage language, + char const* name); + + + /*! @see slang::ICompileRequest::setDefaultModuleName */ + SLANG_API void spSetDefaultModuleName( + SlangCompileRequest* request, + const char* defaultModuleName); + + /*! @see slang::ICompileRequest::addPreprocessorDefine */ + SLANG_API void spTranslationUnit_addPreprocessorDefine( + 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); + + /*! @see slang::ICompileRequest::addTranslationUnitSourceString */ + SLANG_API void spAddTranslationUnitSourceString( + SlangCompileRequest* request, + int translationUnitIndex, + char const* path, + char const* source); + + + /*! @see slang::ICompileRequest::addLibraryReference */ + SLANG_API SlangResult spAddLibraryReference( + 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); + + /*! @see slang::ICompileRequest::addTranslationUnitSourceBlob */ + SLANG_API void spAddTranslationUnitSourceBlob( + SlangCompileRequest* request, + int translationUnitIndex, + char const* path, + ISlangBlob* sourceBlob); + + /*! @see slang::IGlobalSession::findProfile */ + SLANG_API SlangProfileID spFindProfile(SlangSession* session, char const* name); + + /*! @see slang::IGlobalSession::findCapability */ + 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); + + /*! @see slang::ICompileRequest::addEntryPointEx */ + SLANG_API int spAddEntryPointEx( + 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); + + /*! @see slang::ICompileRequest::setTypeNameForGlobalExistentialTypeParam */ + SLANG_API SlangResult spSetTypeNameForGlobalExistentialTypeParam( + SlangCompileRequest* request, + int slotIndex, + char const* typeName); + + /*! @see slang::ICompileRequest::setTypeNameForEntryPointExistentialTypeParam */ + SLANG_API SlangResult spSetTypeNameForEntryPointExistentialTypeParam( + SlangCompileRequest* request, + int entryPointIndex, + int slotIndex, + char const* typeName); + + /*! @see slang::ICompileRequest::compile */ + SLANG_API SlangResult spCompile(SlangCompileRequest* request); + + + /*! @see slang::ICompileRequest::getDiagnosticOutput */ + SLANG_API char const* spGetDiagnosticOutput(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::getDiagnosticOutputBlob */ + SLANG_API SlangResult + spGetDiagnosticOutputBlob(SlangCompileRequest* request, ISlangBlob** outBlob); + + + /*! @see slang::ICompileRequest::getDependencyFileCount */ + SLANG_API int spGetDependencyFileCount(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::getDependencyFilePath */ + SLANG_API char const* spGetDependencyFilePath(SlangCompileRequest* request, int index); + + /*! @see slang::ICompileRequest::getTranslationUnitCount */ + SLANG_API int spGetTranslationUnitCount(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::getEntryPointSource */ + 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); + + /*! @see slang::ICompileRequest::getEntryPointCodeBlob */ + SLANG_API SlangResult spGetEntryPointCodeBlob( + SlangCompileRequest* request, + int entryPointIndex, + int targetIndex, + ISlangBlob** outBlob); + + /*! @see slang::ICompileRequest::getEntryPointHostCallable */ + SLANG_API SlangResult spGetEntryPointHostCallable( + SlangCompileRequest* request, + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary); + + /*! @see slang::ICompileRequest::getTargetCodeBlob */ + SLANG_API SlangResult + spGetTargetCodeBlob(SlangCompileRequest* request, int targetIndex, ISlangBlob** outBlob); + + /*! @see slang::ICompileRequest::getTargetHostCallable */ + SLANG_API SlangResult spGetTargetHostCallable( + SlangCompileRequest* request, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary); + + /*! @see slang::ICompileRequest::getCompileRequestCode */ + SLANG_API void const* spGetCompileRequestCode(SlangCompileRequest* request, size_t* outSize); + + /*! @see slang::ICompileRequest::getContainerCode */ + SLANG_API SlangResult spGetContainerCode(SlangCompileRequest* request, ISlangBlob** outBlob); + + /*! @see slang::ICompileRequest::loadRepro */ + SLANG_API SlangResult spLoadRepro( + SlangCompileRequest* request, + ISlangFileSystem* fileSystem, + const void* data, + size_t size); + + /*! @see slang::ICompileRequest::saveRepro */ + SLANG_API SlangResult spSaveRepro(SlangCompileRequest* request, ISlangBlob** outBlob); + + /*! @see slang::ICompileRequest::enableReproCapture */ + SLANG_API SlangResult spEnableReproCapture(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::getCompileTimeProfile */ + SLANG_API SlangResult spGetCompileTimeProfile( + SlangCompileRequest* request, + ISlangProfiler** compileTimeProfile, + bool shouldClear); + + + /** 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. + + @param session The slang session + @param reproData Holds the repro data + @param reproDataSize The size of the repro data + @param fileSystem File system that the contents of the repro will be written to + @returns A `SlangResult` to indicate success or failure. + */ + SLANG_API SlangResult spExtractRepro( + SlangSession* session, + const void* reproData, + size_t reproDataSize, + ISlangMutableFileSystem* fileSystem); + + /* 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. + + @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 outFileSystem The file system that can be used to access contents + @returns A `SlangResult` to indicate success or failure. + */ + SLANG_API SlangResult spLoadReproAsFileSystem( + SlangSession* session, + const void* reproData, + size_t reproDataSize, + ISlangFileSystem* replaceFileSystem, + ISlangFileSystemExt** outFileSystem); + + /*! @see slang::ICompileRequest::overrideDiagnosticSeverity */ + SLANG_API void spOverrideDiagnosticSeverity( + SlangCompileRequest* request, + SlangInt messageID, + SlangSeverity overrideSeverity); + + /*! @see slang::ICompileRequest::getDiagnosticFlags */ + SLANG_API SlangDiagnosticFlags spGetDiagnosticFlags(SlangCompileRequest* request); + + /*! @see slang::ICompileRequest::setDiagnosticFlags */ + SLANG_API void spSetDiagnosticFlags(SlangCompileRequest* request, SlangDiagnosticFlags flags); + + + // get reflection data from a compilation 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); + + /** 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. + */ + 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 unsigned int spReflectionType_GetFieldCount(SlangReflectionType* type); + SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex( + SlangReflectionType* type, + unsigned index); + + /** Returns the number of elements in the given type. + + 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)`. + + 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. + + Use spReflectionType_GetSpecializedElementCount if the size is dependent on + a link time constant + */ + SLANG_API size_t spReflectionType_GetElementCount(SlangReflectionType* type); + + /** The same as spReflectionType_GetElementCount except it takes into account specialization + * information from the given reflection info + */ + SLANG_API size_t spReflectionType_GetSpecializedElementCount( + SlangReflectionType* type, + SlangReflection* reflection); + + SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionType* type); + + SLANG_API unsigned int spReflectionType_GetRowCount(SlangReflectionType* type); + SLANG_API unsigned int spReflectionType_GetColumnCount(SlangReflectionType* type); + SLANG_API SlangScalarType spReflectionType_GetScalarType(SlangReflectionType* type); + + SLANG_API SlangResourceShape spReflectionType_GetResourceShape(SlangReflectionType* type); + SLANG_API SlangResourceAccess spReflectionType_GetResourceAccess(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); + + // Type Layout Reflection + + SLANG_API SlangReflectionType* spReflectionTypeLayout_GetType(SlangReflectionTypeLayout* type); + SLANG_API SlangTypeKind spReflectionTypeLayout_getKind(SlangReflectionTypeLayout* type); + /** Get the size of a type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources (e.g., unsized arrays). + * Returns `SLANG_UNKNOWN_SIZE` when the size depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API size_t spReflectionTypeLayout_GetSize( + SlangReflectionTypeLayout* type, + SlangParameterCategory category); + + /** Get the stride of a type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when stride depends on unresolved generic parameters or + * link-time constants. + */ + 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); + + /** Get the stride between elements of an array type layout. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when element stride depends on unresolved generic parameters or + * link-time constants. + */ + 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 SlangMatrixLayoutMode + spReflectionTypeLayout_GetMatrixLayoutMode(SlangReflectionTypeLayout* type); + + SLANG_API int spReflectionTypeLayout_getGenericParamIndex(SlangReflectionTypeLayout* type); + + SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getPendingDataTypeLayout( + 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); + /** Get the binding count for a binding range at the specified index. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the count depends on unresolved generic parameters or + * link-time constants. + */ + 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); + /** Get the index offset for a descriptor range within a descriptor set. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex, + SlangInt rangeIndex); + + /** Get the descriptor count for a descriptor range within a descriptor set. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the count depends on unresolved generic parameters or + * link-time constants. + */ + 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); + /** Get the space offset for a sub-object range. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + 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); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeObjectCount(SlangReflectionTypeLayout* typeLayout, SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index); + SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getSubObjectRangeTypeLayout(SlangReflectionTypeLayout* typeLayout, SlangInt index); + + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); + SLANG_API SlangBindingType spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingType(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeBindingCount(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeIndexOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex, SlangInt bindingRangeIndexInSubObject); +#endif + + // Variable Reflection + + 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 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 bool spReflectionVariable_HasDefaultValue(SlangReflectionVariable* inVar); + SLANG_API SlangResult + spReflectionVariable_GetDefaultValueInt(SlangReflectionVariable* inVar, int64_t* rs); + SLANG_API SlangResult + spReflectionVariable_GetDefaultValueFloat(SlangReflectionVariable* inVar, float* rs); + 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 SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout( + SlangReflectionVariableLayout* var); + + /** Get the offset of a variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API size_t spReflectionVariableLayout_GetOffset( + SlangReflectionVariableLayout* var, + SlangParameterCategory category); + + /** Get the register space/set of a variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the space depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API size_t spReflectionVariableLayout_GetSpace( + SlangReflectionVariableLayout* var, + SlangParameterCategory category); + SLANG_API SlangImageFormat + spReflectionVariableLayout_GetImageFormat(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 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 bool spReflectionFunction_isOverloaded(SlangReflectionFunction* func); + SLANG_API unsigned int spReflectionFunction_getOverloadCount(SlangReflectionFunction* func); + 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 char const* spReflectionDecl_getName(SlangReflectionDecl* decl); + SLANG_API SlangDeclKind spReflectionDecl_getKind(SlangReflectionDecl* decl); + SLANG_API SlangReflectionFunction* spReflectionDecl_castToFunction(SlangReflectionDecl* decl); + SLANG_API SlangReflectionVariable* spReflectionDecl_castToVariable(SlangReflectionDecl* decl); + SLANG_API SlangReflectionGeneric* spReflectionDecl_castToGeneric(SlangReflectionDecl* decl); + SLANG_API SlangReflectionType* spReflection_getTypeFromDecl(SlangReflectionDecl* decl); + SLANG_API SlangReflectionDecl* spReflectionDecl_getParent(SlangReflectionDecl* decl); + SLANG_API SlangReflectionModifier* spReflectionDecl_findModifier( + SlangReflectionDecl* decl, + SlangModifierID modifierID); + + // Generic Reflection + + 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 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); + + + /** Get the stage that a variable belongs to (if any). + + A variable "belongs" to a specific stage when it is a varying input/output + parameter either defined as part of the parameter list for an entry + 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 SlangReflectionVariableLayout* spReflectionVariableLayout_getPendingDataLayout( + SlangReflectionVariableLayout* var); + + // Shader Parameter Reflection + + /** Get the binding index for a shader parameter. + * + * Returns `SLANG_UNKNOWN_SIZE` when the index depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API unsigned spReflectionParameter_GetBindingIndex(SlangReflectionParameter* parameter); + + /** Get the binding space for a shader parameter. + * + * Returns `SLANG_UNKNOWN_SIZE` when the space depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API unsigned spReflectionParameter_GetBindingSpace(SlangReflectionParameter* parameter); + + SLANG_API SlangResult spIsParameterLocationUsed( + SlangCompileRequest* request, + 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 + bool& outUsed); + + // Entry Point Reflection + + SLANG_API char const* spReflectionEntryPoint_getName(SlangReflectionEntryPoint* entryPoint); + + SLANG_API char const* spReflectionEntryPoint_getNameOverride( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API SlangReflectionFunction* spReflectionEntryPoint_getFunction( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API unsigned spReflectionEntryPoint_getParameterCount( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getParameterByIndex( + SlangReflectionEntryPoint* entryPoint, + unsigned index); + + SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint* entryPoint); + + SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize( + SlangReflectionEntryPoint* entryPoint, + SlangUInt axisCount, + SlangUInt* outSizeAlongAxis); + + SLANG_API void spReflectionEntryPoint_getComputeWaveSize( + SlangReflectionEntryPoint* entryPoint, + SlangUInt* outWaveSize); + + SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getVarLayout( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getResultVarLayout( + SlangReflectionEntryPoint* entryPoint); + + SLANG_API int spReflectionEntryPoint_hasDefaultConstantBuffer( + SlangReflectionEntryPoint* entryPoint); + + // SlangReflectionTypeParameter + 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); + + // Shader Reflection + + SLANG_API SlangResult spReflection_ToJson( + SlangReflection* reflection, + SlangCompileRequest* request, + ISlangBlob** outBlob); + + SLANG_API unsigned spReflection_GetParameterCount(SlangReflection* reflection); + 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 SlangReflectionFunction* spReflection_TryResolveOverloadedFunction( + SlangReflection* reflection, + uint32_t candidateCount, + SlangReflectionFunction** candidates); + + 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); + + /** Get the binding index for the global constant buffer. + * + * Returns `SLANG_UNKNOWN_SIZE` when the binding depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API SlangUInt spReflection_getGlobalConstantBufferBinding(SlangReflection* reflection); + + /** Get the size of the global constant buffer. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the size depends on unresolved generic parameters or + * link-time constants. + */ + SLANG_API size_t spReflection_getGlobalConstantBufferSize(SlangReflection* reflection); + + SLANG_API SlangReflectionType* spReflection_specializeType( + SlangReflection* reflection, + SlangReflectionType* type, + SlangInt specializationArgCount, + SlangReflectionType* const* specializationArgs, + ISlangBlob** outDiagnostics); + + SLANG_API SlangReflectionGeneric* spReflection_specializeGeneric( + SlangReflection* inProgramLayout, + SlangReflectionGeneric* generic, + SlangInt argCount, + SlangReflectionGenericArgType const* argTypes, + SlangReflectionGenericArg const* args, + ISlangBlob** outDiagnostics); + + SLANG_API bool spReflection_isSubType( + SlangReflection* reflection, + SlangReflectionType* subType, + SlangReflectionType* superType); + + /// 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. + SLANG_API const char* spReflection_getHashedString( + SlangReflection* reflection, + SlangUInt index, + size_t* outCount); + + /// 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 parameters. + SLANG_API SlangReflectionTypeLayout* spReflection_getGlobalParamsTypeLayout( + SlangReflection* reflection); + + /// Get a variable layout representing reflection information for the global-scope parameters. + SLANG_API SlangReflectionVariableLayout* spReflection_getGlobalParamsVarLayout( + SlangReflection* reflection); + + SLANG_API char const* spGetTranslationUnitSource( + SlangCompileRequest* request, + int translationUnitIndex); + + /** Get the descriptor set/space index allocated for the bindless resource heap. + * Returns -1 if the program does not use bindless resource heap. + */ + SLANG_API SlangInt spReflection_getBindlessSpaceIndex(SlangReflection* reflection); +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +SLANG_API slang::ISession* spReflection_GetSession(SlangReflection* reflection); + +namespace slang +{ +struct IComponentType; +struct IModule; +} // namespace slang + +extern "C" +{ + /** @see slang::ICompileRequest::getProgram + */ + SLANG_API SlangResult + spCompileRequest_getProgram(SlangCompileRequest* request, slang::IComponentType** outProgram); + + /** @see slang::ICompileRequest::getProgramWithEntryPoints + */ + SLANG_API SlangResult spCompileRequest_getProgramWithEntryPoints( + SlangCompileRequest* request, + slang::IComponentType** outProgram); + + /** @see slang::ICompileRequest::getEntryPoint + */ + SLANG_API SlangResult spCompileRequest_getEntryPoint( + SlangCompileRequest* request, + SlangInt entryPointIndex, + slang::IComponentType** outEntryPoint); + + /** @see slang::ICompileRequest::getModule + */ + SLANG_API SlangResult spCompileRequest_getModule( + SlangCompileRequest* request, + SlangInt translationUnitIndex, + slang::IModule** outModule); + + /** @see slang::ICompileRequest::getSession + */ + 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 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 available 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; + + virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceCLayout(int targetIndex, bool value) = 0; +}; + + #define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid() + +} // namespace slang +#endif diff --git a/lib/All/slang/include/slang-gfx.h b/lib/All/slang/include/slang-gfx.h new file mode 100644 index 0000000..ec405ba --- /dev/null +++ b/lib/All/slang/include/slang-gfx.h @@ -0,0 +1,2982 @@ +// render.h +#pragma once + +#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 +#endif + +#ifndef SLANG_GFX_API + #define SLANG_GFX_API +#endif + +// Needed for building on cygwin with gcc +#undef Always +#undef None + +// 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. +// - Offset and Size are almost always for bytes and things measured in bytes. +namespace gfx +{ + +using Slang::ComPtr; + +typedef SlangResult Result; + +// Had to move here, because Options needs types defined here +typedef SlangInt Int; +typedef SlangUInt UInt; +typedef uint64_t DeviceAddress; +typedef int GfxIndex; +typedef int GfxCount; +typedef size_t Size; +typedef size_t Offset; + +const uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF; + +enum class StructType +{ + D3D12DeviceExtendedDesc, + D3D12ExperimentalFeaturesDesc, + SlangSessionExtendedDesc, + RayTracingValidationDesc +}; + +// TODO: Rename to Stage +enum class StageType +{ + Unknown, + Vertex, + Hull, + Domain, + Geometry, + Fragment, + Compute, + RayGeneration, + Intersection, + AnyHit, + ClosestHit, + Miss, + Callable, + Amplification, + Mesh, + CountOf, +}; + +// TODO: Implementation or backend or something else? +enum class DeviceType +{ + Unknown, + Default, + DirectX11, + DirectX12, + OpenGl, + Vulkan, + Metal, + CPU, + CUDA, + WebGPU, + CountOf, +}; + +// TODO: Why does this exist it should go poof +enum class ProjectionStyle +{ + Unknown, + OpenGl, + DirectX, + Vulkan, + Metal, + CountOf, +}; + +// TODO: This should also go poof +/// The style of the binding +enum class BindingStyle +{ + Unknown, + DirectX, + OpenGl, + Vulkan, + Metal, + CPU, + CUDA, + CountOf, +}; + +// TODO: Is this actually a flag when there are no bit fields? +enum class AccessFlag +{ + None, + Read, + Write, +}; + +// TODO: Needed? Shouldn't be hard-coded if so +const GfxCount kMaxRenderTargetCount = 8; + +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. + SlangModuleBinaryFile, // a slang module binary code from file. +}; + +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. + SingleProgram, + + // Link and compile each entry-point individually, potentially with different + // specializations. + SeparateEntryPointCompilation + }; + + enum class DownstreamLinkMode + { + None, + Deferred, + }; + + struct Desc + { + // TODO: Tess doesn't like this but doesn't know what to do about it + // The linking style of this program. + LinkingStyle linkingStyle = LinkingStyle::SingleProgram; + + // The global scope or a Slang composite component that represents the entire program. + 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. + // If not 0, then `slangGlobalScope` must not contain any EntryPoint components. + GfxCount entryPointCount = 0; + + // An array of Slang entry points. The size of the array must be `entryPointCount`. + // Each element must define only 1 Slang EntryPoint. + slang::IComponentType** slangEntryPoints = nullptr; + + // Indicates whether the app is responsible for final downstream linking. + DownstreamLinkMode downstreamLinkMode = DownstreamLinkMode::None; + }; + + struct CreateDesc2 + { + ShaderModuleSourceType sourceType; + void* sourceData; + Size sourceDataSize; + + // Number of entry points to include in the shader program. 0 means include all entry points + // defined in the module. + GfxCount entryPointCount = 0; + // Names of entry points to include in the shader program. The size of the array must be + // `entryPointCount`. + const char** entryPointNames = nullptr; + }; + + 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 \ + } \ + } + +// TODO: Confirm with Yong that we really want this naming convention +// TODO: Rename to what? +// Dont' change without keeping in sync with Format +// clang-format off +#define GFX_FORMAT(x) \ + x( Unknown, 0, 0) \ + \ + x(R32G32B32A32_TYPELESS, 16, 1) \ + x(R32G32B32_TYPELESS, 12, 1) \ + x(R32G32_TYPELESS, 8, 1) \ + x(R32_TYPELESS, 4, 1) \ + \ + x(R16G16B16A16_TYPELESS, 8, 1) \ + x(R16G16_TYPELESS, 4, 1) \ + x(R16_TYPELESS, 2, 1) \ + \ + x(R8G8B8A8_TYPELESS, 4, 1) \ + x(R8G8_TYPELESS, 2, 1) \ + x(R8_TYPELESS, 1, 1) \ + x(B8G8R8A8_TYPELESS, 4, 1) \ + \ + x(R32G32B32A32_FLOAT, 16, 1) \ + x(R32G32B32_FLOAT, 12, 1) \ + x(R32G32_FLOAT, 8, 1) \ + x(R32_FLOAT, 4, 1) \ + \ + x(R16G16B16A16_FLOAT, 8, 1) \ + x(R16G16_FLOAT, 4, 1) \ + x(R16_FLOAT, 2, 1) \ + \ + x(R32G32B32A32_UINT, 16, 1) \ + x(R32G32B32_UINT, 12, 1) \ + x(R32G32_UINT, 8, 1) \ + x(R32_UINT, 4, 1) \ + \ + x(R16G16B16A16_UINT, 8, 1) \ + x(R16G16_UINT, 4, 1) \ + x(R16_UINT, 2, 1) \ + \ + x(R8G8B8A8_UINT, 4, 1) \ + x(R8G8_UINT, 2, 1) \ + x(R8_UINT, 1, 1) \ + \ + x(R32G32B32A32_SINT, 16, 1) \ + x(R32G32B32_SINT, 12, 1) \ + x(R32G32_SINT, 8, 1) \ + x(R32_SINT, 4, 1) \ + \ + x(R16G16B16A16_SINT, 8, 1) \ + x(R16G16_SINT, 4, 1) \ + x(R16_SINT, 2, 1) \ + \ + x(R8G8B8A8_SINT, 4, 1) \ + x(R8G8_SINT, 2, 1) \ + x(R8_SINT, 1, 1) \ + \ + x(R16G16B16A16_UNORM, 8, 1) \ + x(R16G16_UNORM, 4, 1) \ + x(R16_UNORM, 2, 1) \ + \ + x(R8G8B8A8_UNORM, 4, 1) \ + x(R8G8B8A8_UNORM_SRGB, 4, 1) \ + x(R8G8_UNORM, 2, 1) \ + x(R8_UNORM, 1, 1) \ + x(B8G8R8A8_UNORM, 4, 1) \ + x(B8G8R8A8_UNORM_SRGB, 4, 1) \ + x(B8G8R8X8_UNORM, 4, 1) \ + x(B8G8R8X8_UNORM_SRGB, 4, 1) \ + \ + x(R16G16B16A16_SNORM, 8, 1) \ + x(R16G16_SNORM, 4, 1) \ + x(R16_SNORM, 2, 1) \ + \ + x(R8G8B8A8_SNORM, 4, 1) \ + x(R8G8_SNORM, 2, 1) \ + x(R8_SNORM, 1, 1) \ + \ + x(D32_FLOAT, 4, 1) \ + x(D16_UNORM, 2, 1) \ + x(D32_FLOAT_S8_UINT, 8, 1) \ + x(R32_FLOAT_X32_TYPELESS, 8, 1) \ + \ + x(B4G4R4A4_UNORM, 2, 1) \ + x(B5G6R5_UNORM, 2, 1) \ + x(B5G5R5A1_UNORM, 2, 1) \ + \ + x(R9G9B9E5_SHAREDEXP, 4, 1) \ + x(R10G10B10A2_TYPELESS, 4, 1) \ + x(R10G10B10A2_UNORM, 4, 1) \ + x(R10G10B10A2_UINT, 4, 1) \ + x(R11G11B10_FLOAT, 4, 1) \ + \ + x(BC1_UNORM, 8, 16) \ + x(BC1_UNORM_SRGB, 8, 16) \ + x(BC2_UNORM, 16, 16) \ + x(BC2_UNORM_SRGB, 16, 16) \ + x(BC3_UNORM, 16, 16) \ + x(BC3_UNORM_SRGB, 16, 16) \ + x(BC4_UNORM, 8, 16) \ + x(BC4_SNORM, 8, 16) \ + x(BC5_UNORM, 16, 16) \ + x(BC5_SNORM, 16, 16) \ + x(BC6H_UF16, 16, 16) \ + x(BC6H_SF16, 16, 16) \ + x(BC7_UNORM, 16, 16) \ + x(BC7_UNORM_SRGB, 16, 16) \ + \ + x(R64_UINT, 8, 1) \ + \ + x(R64_SINT, 8, 1) +// clang-format on + +// 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 +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. + Unknown, + + R32G32B32A32_TYPELESS, + R32G32B32_TYPELESS, + R32G32_TYPELESS, + R32_TYPELESS, + + R16G16B16A16_TYPELESS, + R16G16_TYPELESS, + R16_TYPELESS, + + R8G8B8A8_TYPELESS, + R8G8_TYPELESS, + R8_TYPELESS, + B8G8R8A8_TYPELESS, + + R32G32B32A32_FLOAT, + R32G32B32_FLOAT, + R32G32_FLOAT, + R32_FLOAT, + + R16G16B16A16_FLOAT, + R16G16_FLOAT, + R16_FLOAT, + + R32G32B32A32_UINT, + R32G32B32_UINT, + R32G32_UINT, + R32_UINT, + + R16G16B16A16_UINT, + R16G16_UINT, + R16_UINT, + + R8G8B8A8_UINT, + R8G8_UINT, + R8_UINT, + + R32G32B32A32_SINT, + R32G32B32_SINT, + R32G32_SINT, + R32_SINT, + + R16G16B16A16_SINT, + R16G16_SINT, + R16_SINT, + + R8G8B8A8_SINT, + R8G8_SINT, + R8_SINT, + + R16G16B16A16_UNORM, + R16G16_UNORM, + R16_UNORM, + + R8G8B8A8_UNORM, + R8G8B8A8_UNORM_SRGB, + R8G8_UNORM, + R8_UNORM, + B8G8R8A8_UNORM, + B8G8R8A8_UNORM_SRGB, + B8G8R8X8_UNORM, + B8G8R8X8_UNORM_SRGB, + + R16G16B16A16_SNORM, + R16G16_SNORM, + R16_SNORM, + + R8G8B8A8_SNORM, + R8G8_SNORM, + R8_SNORM, + + D32_FLOAT, + D16_UNORM, + D32_FLOAT_S8_UINT, + R32_FLOAT_X32_TYPELESS, + + B4G4R4A4_UNORM, + B5G6R5_UNORM, + B5G5R5A1_UNORM, + + R9G9B9E5_SHAREDEXP, + R10G10B10A2_TYPELESS, + R10G10B10A2_UNORM, + R10G10B10A2_UINT, + R11G11B10_FLOAT, + + BC1_UNORM, + BC1_UNORM_SRGB, + BC2_UNORM, + BC2_UNORM_SRGB, + BC3_UNORM, + BC3_UNORM_SRGB, + BC4_UNORM, + BC4_SNORM, + BC5_UNORM, + BC5_SNORM, + BC6H_UF16, + BC6H_SF16, + BC7_UNORM, + BC7_UNORM_SRGB, + + R64_UINT, + + R64_SINT, + + _Count, +}; + +// TODO: Aspect = Color, Depth, Stencil, etc. +// TODO: Channel = R, G, B, A, D, S, etc. +// TODO: Pick : pixel or texel +// TODO: Block is a good term for what it is +// 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? + + 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 +}; + +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. +}; + +struct VertexStreamDesc +{ + Size stride; ///< The stride in bytes for this vertex stream. + InputSlotClass slotClass; ///< Whether the stream contains per-vertex or per-instance data. + GfxCount instanceDataStepRate; ///< How many instances to draw per chunk of data. +}; + +enum class PrimitiveType +{ + Point, + Line, + Triangle, + Patch +}; + +enum class PrimitiveTopology +{ + TriangleList, + TriangleStrip, + PointList, + LineList, + LineStrip +}; + +enum class ResourceState +{ + Undefined, + General, + PreInitialized, + VertexBuffer, + IndexBuffer, + ConstantBuffer, + StreamOutput, + ShaderResource, + UnorderedAccess, + RenderTarget, + DepthRead, + DepthWrite, + Present, + IndirectArgument, + CopySource, + CopyDestination, + ResolveSource, + ResolveDestination, + AccelerationStructure, + AccelerationStructureBuildInput, + PixelShaderResource, + NonPixelShaderResource, + _Count +}; + +struct ResourceStateSet +{ +public: + void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); } + template + void add(ResourceState s, TResourceState... states) + { + add(s); + add(states...); + } + 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) + { + add(states...); + } + + ResourceStateSet operator&(const ResourceStateSet& that) const + { + ResourceStateSet result; + result.m_bitFields = this->m_bitFields & that.m_bitFields; + return result; + } + +private: + uint64_t m_bitFields = 0; + void add() {} +}; + + +/// Describes how memory for the resource should be allocated for CPU access. +enum class MemoryType +{ + DeviceLocal, + Upload, + ReadBack, +}; + +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. + D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value. + Metal, // A general Metal object handle. +}; + +struct InteropHandle +{ + InteropHandleAPI api = InteropHandleAPI::Unknown; + uint64_t handleValue = 0; +}; + +// Declare opaque type +class IInputLayout : public ISlangUnknown +{ +public: + struct Desc + { + InputElementDesc const* inputElements = nullptr; + GfxCount inputElementCount = 0; + VertexStreamDesc const* vertexStreams = nullptr; + GfxCount vertexStreamCount = 0; + }; +}; +#define SLANG_UUID_IInputLayout \ + { \ + 0x45223711, 0xa84b, 0x455c, \ + { \ + 0xbe, 0xfa, 0x49, 0x37, 0x42, 0x1e, 0x8e, 0x2e \ + } \ + } + +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) + 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 + _Count, + }; + + /// Base class for Descs + struct DescBase + { + Type type = Type::Unknown; + ResourceState defaultState = ResourceState::Undefined; + ResourceStateSet allowedStates = ResourceStateSet(); + MemoryType memoryType = MemoryType::DeviceLocal; + InteropHandle existingHandle = {}; + bool isShared = false; + }; + + virtual SLANG_NO_THROW Type SLANG_MCALL getType() = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0; + + 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 \ + } \ + } + +struct MemoryRange +{ + // TODO: Change to Offset/Size? + uint64_t offset; + uint64_t size; +}; + +class IBufferResource : public IResource +{ +public: + 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 + Format format = Format::Unknown; + }; + + virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0; + virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0; + 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 \ + } \ + } + +struct DepthStencilClearValue +{ + float depth = 1.0f; + uint32_t stencil = 0; +}; +union ColorClearValue +{ + float floatValues[4]; + uint32_t uintValues[4]; +}; +struct ClearValue +{ + ColorClearValue color = {{0.0f, 0.0f, 0.0f, 0.0f}}; + DepthStencilClearValue depthStencil; +}; + +struct BufferRange +{ + Offset offset; ///< Offset in bytes. + Size size; ///< Size in bytes. +}; + +enum class TextureAspect : uint32_t +{ + Default = 0, + Color = 0x00000001, + Depth = 0x00000002, + Stencil = 0x00000004, + MetaData = 0x00000008, + Plane0 = 0x00000010, + Plane1 = 0x00000020, + Plane2 = 0x00000040, + + DepthStencil = Depth | Stencil, +}; + +struct SubresourceRange +{ + TextureAspect aspectMask; + GfxIndex mipLevel; + GfxCount mipLevelCount; + GfxIndex baseArrayLayer; // For Texture3D, this is WSlice. + GfxCount layerCount; // For cube maps, this is a multiple of 6. +}; + +class ITextureResource : public IResource +{ +public: + static const GfxCount kRemainingTextureSize = 0xffffffff; + struct Offset3D + { + GfxIndex x = 0; + GfxIndex y = 0; + GfxIndex z = 0; + Offset3D() = default; + 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 + }; + + struct Extents + { + 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 + { + Extents 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 + 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`. + /// + struct SubresourceData + { + /// 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. + /// + 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. + /// + 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 \ + } \ + } + + +enum class ComparisonFunc : uint8_t +{ + Never = 0x0, + Less = 0x1, + Equal = 0x2, + LessEqual = 0x3, + Greater = 0x4, + NotEqual = 0x5, + GreaterEqual = 0x6, + Always = 0x7, +}; + +enum class TextureFilteringMode +{ + Point, + Linear, +}; + +enum class TextureAddressingMode +{ + Wrap, + ClampToEdge, + ClampToBorder, + MirrorRepeat, + MirrorOnce, +}; + +enum class TextureReductionOp +{ + Average, + Comparison, + Minimum, + Maximum, +}; + +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; + }; + + /// Returns a native API handle representing this sampler state object. + /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE. + /// 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 \ + } \ + } + +class IResourceView : public ISlangUnknown +{ +public: + enum class Type + { + Unknown, + + RenderTarget, + DepthStencil, + ShaderResource, + UnorderedAccess, + AccelerationStructure, + + CountOf_, + }; + + struct RenderTargetDesc + { + // The resource shape of this render target view. + IResource::Type shape; + }; + + struct Desc + { + 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. + SubresourceRange subresourceRange; + // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view. + BufferRange bufferRange; + }; + 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. + 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 \ + } \ + } + +class IAccelerationStructure : public IResourceView +{ +public: + enum class Kind + { + TopLevel, + BottomLevel + }; + + struct BuildFlags + { + // The enum values are intentionally consistent with + // D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS. + enum Enum + { + None, + AllowUpdate = 1, + AllowCompaction = 2, + PreferFastTrace = 4, + PreferFastBuild = 8, + MinimizeMemory = 16, + PerformUpdate = 32 + }; + }; + + enum class GeometryType + { + Triangles, + ProcedurePrimitives + }; + + struct GeometryFlags + { + // The enum values are intentionally consistent with + // D3D12_RAYTRACING_GEOMETRY_FLAGS. + enum Enum + { + None, + Opaque = 1, + NoDuplicateAnyHitInvocation = 2 + }; + }; + + struct TriangleDesc + { + DeviceAddress transform3x4; + Format indexFormat; + Format vertexFormat; + GfxCount indexCount; + GfxCount vertexCount; + DeviceAddress indexData; + DeviceAddress vertexData; + Size vertexStride; + }; + + struct ProceduralAABB + { + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; + }; + + struct ProceduralAABBDesc + { + /// Number of AABBs. + GfxCount count; + + /// Pointer to an array of `ProceduralAABB` values in device memory. + DeviceAddress data; + + /// Stride in bytes of the AABB values array. + Size stride; + }; + + struct GeometryDesc + { + GeometryType type; + GeometryFlags::Enum flags; + union + { + TriangleDesc triangles; + ProceduralAABBDesc proceduralAABBs; + } content; + }; + + struct GeometryInstanceFlags + { + // The enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS + // and VkGeometryInstanceFlagBitsKHR. + enum Enum : uint32_t + { + None = 0, + TriangleFacingCullDisable = 0x00000001, + TriangleFrontCounterClockwise = 0x00000002, + ForceOpaque = 0x00000004, + NoOpaque = 0x00000008 + }; + }; + + // TODO: Should any of these be changed? + // The layout of this struct is intentionally consistent with D3D12_RAYTRACING_INSTANCE_DESC + // and VkAccelerationStructureInstanceKHR. + struct InstanceDesc + { + float transform[3][4]; + uint32_t instanceID : 24; + uint32_t instanceMask : 8; + uint32_t instanceContributionToHitGroupIndex : 24; + uint32_t flags : 8; // Combination of GeometryInstanceFlags::Enum values. + DeviceAddress accelerationStructure; + }; + + struct PrebuildInfo + { + Size resultDataMaxSize; + Size scratchDataSize; + Size updateScratchDataSize; + }; + + struct BuildInputs + { + Kind kind; + + BuildFlags::Enum flags; + + GfxCount descCount; + + /// Array of `InstanceDesc` values in device memory. + /// Used when `kind` is `TopLevel`. + DeviceAddress instanceDescs; + + /// Array of `GeometryDesc` values. + /// Used when `kind` is `BottomLevel`. + const GeometryDesc* geometryDescs; + }; + + struct CreateDesc + { + Kind kind; + IBufferResource* buffer; + Offset offset; + Size size; + }; + + struct BuildDesc + { + BuildInputs inputs; + IAccelerationStructure* source; + IAccelerationStructure* dest; + DeviceAddress scratchData; + }; + + virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0; +}; +#define SLANG_UUID_IAccelerationStructure \ + { \ + 0xa5cdda3c, 0x1d4e, 0x4df7, \ + { \ + 0x8e, 0xf2, 0xb7, 0x3f, 0xce, 0x4, 0xde, 0x3b \ + } \ + } + +class IFence : public ISlangUnknown +{ +public: + struct Desc + { + uint64_t initialValue = 0; + bool isShared = false; + }; + + /// Returns the currently signaled value on the device. + virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) = 0; + + /// Signals the fence from the host with the specified value. + virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) = 0; + + 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 \ + } \ + } + +struct ShaderOffset +{ + SlangInt uniformOffset = 0; // TODO: Change to Offset? + GfxIndex bindingRangeIndex = 0; + GfxIndex bindingArrayIndex = 0; + uint32_t getHashCode() const + { + return (uint32_t)(((bindingRangeIndex << 20) + bindingArrayIndex) ^ uniformOffset); + } + 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); } + bool operator<(const ShaderOffset& other) const + { + if (bindingRangeIndex < other.bindingRangeIndex) + return true; + if (bindingRangeIndex > other.bindingRangeIndex) + return false; + if (bindingArrayIndex < other.bindingArrayIndex) + return true; + if (bindingArrayIndex > other.bindingArrayIndex) + return false; + return uniformOffset < other.uniformOffset; + } + bool operator<=(const ShaderOffset& other) const { return (*this == other) || (*this) < other; } + bool operator>(const ShaderOffset& other) const { return other < *this; } + bool operator>=(const ShaderOffset& other) const { return other <= *this; } +}; + +enum class ShaderObjectContainerType +{ + None, + Array, + StructuredBuffer +}; + +class IShaderObject : public ISlangUnknown +{ +public: + virtual SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL getElementTypeLayout() = 0; + 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; + virtual SLANG_NO_THROW Result SLANG_MCALL + setData(ShaderOffset const& offset, void const* data, Size size) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getObject(ShaderOffset const& offset, IShaderObject** object) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + setObject(ShaderOffset const& offset, IShaderObject* object) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + setResource(ShaderOffset const& offset, IResourceView* resourceView) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + setSampler(ShaderOffset const& offset, ISamplerState* sampler) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler( + 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. + 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 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; + + + inline ComPtr getObject(ShaderOffset const& offset) + { + ComPtr object = nullptr; + SLANG_RETURN_NULL_ON_FAIL(getObject(offset, object.writeRef())); + return object; + } + inline ComPtr getEntryPoint(GfxIndex index) + { + ComPtr entryPoint = nullptr; + SLANG_RETURN_NULL_ON_FAIL(getEntryPoint(index, entryPoint.writeRef())); + return entryPoint; + } +}; +#define SLANG_UUID_IShaderObject \ + { \ + 0xc1fa997e, 0x5ca2, 0x45ae, \ + { \ + 0x9b, 0xcb, 0xc4, 0x35, 0x9e, 0x85, 0x5, 0x85 \ + } \ + } + +enum class StencilOp : uint8_t +{ + Keep, + Zero, + Replace, + IncrementSaturate, + DecrementSaturate, + Invert, + IncrementWrap, + DecrementWrap, +}; + +enum class FillMode : uint8_t +{ + Solid, + Wireframe, +}; + +enum class CullMode : uint8_t +{ + None, + Front, + Back, +}; + +enum class FrontFaceMode : uint8_t +{ + CounterClockwise, + Clockwise, +}; + +struct DepthStencilOpDesc +{ + 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 stencilEnable = false; + uint32_t stencilReadMask = 0xFFFFFFFF; + uint32_t stencilWriteMask = 0xFFFFFFFF; + DepthStencilOpDesc frontFace; + DepthStencilOpDesc backFace; + + uint32_t stencilRef = 0; // TODO: this should be removed +}; + +struct RasterizerDesc +{ + FillMode fillMode = FillMode::Solid; + CullMode cullMode = CullMode::None; + FrontFaceMode frontFace = FrontFaceMode::CounterClockwise; + int32_t depthBias = 0; + float depthBiasClamp = 0.0f; + float slopeScaledDepthBias = 0.0f; + bool depthClipEnable = true; + bool scissorEnable = false; + bool multisampleEnable = false; + bool antialiasedLineEnable = false; + bool enableConservativeRasterization = false; + uint32_t forcedSampleCount = 0; +}; + +enum class LogicOp +{ + NoOp, +}; + +enum class BlendOp +{ + Add, + Subtract, + ReverseSubtract, + Min, + Max, +}; + +enum class BlendFactor +{ + Zero, + One, + SrcColor, + InvSrcColor, + SrcAlpha, + InvSrcAlpha, + DestAlpha, + InvDestAlpha, + DestColor, + InvDestColor, + SrcAlphaSaturate, + BlendColor, + InvBlendColor, + SecondarySrcColor, + InvSecondarySrcColor, + SecondarySrcAlpha, + InvSecondarySrcAlpha, +}; + +namespace RenderTargetWriteMask +{ +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; +}; + +struct TargetBlendDesc +{ + AspectBlendDesc color; + AspectBlendDesc alpha; + bool enableBlend = false; + LogicOp logicOp = LogicOp::NoOp; + RenderTargetWriteMaskT writeMask = RenderTargetWriteMask::EnableAll; +}; + +struct BlendDesc +{ + TargetBlendDesc targets[kMaxRenderTargetCount]; + GfxCount targetCount = 0; + + bool alphaToCoverageEnable = false; +}; + +class IFramebufferLayout : public ISlangUnknown +{ +public: + struct TargetLayout + { + Format format; + GfxCount sampleCount; + }; + struct Desc + { + GfxCount renderTargetCount; + TargetLayout* renderTargets = nullptr; + TargetLayout* depthStencil = nullptr; + }; +}; +#define SLANG_UUID_IFramebufferLayout \ + { \ + 0xa838785, 0xc13a, 0x4832, \ + { \ + 0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba \ + } \ + } + +struct GraphicsPipelineStateDesc +{ + IShaderProgram* program = nullptr; + + IInputLayout* inputLayout = nullptr; + IFramebufferLayout* framebufferLayout = nullptr; + PrimitiveType primitiveType = PrimitiveType::Triangle; + DepthStencilDesc depthStencil; + RasterizerDesc rasterizer; + BlendDesc blend; +}; + +struct ComputePipelineStateDesc +{ + IShaderProgram* program = nullptr; + void* d3d12RootSignatureOverride = nullptr; +}; + +struct RayTracingPipelineFlags +{ + enum Enum : uint32_t + { + None = 0, + SkipTriangles = 1, + SkipProcedurals = 2, + }; +}; + +struct HitGroupDesc +{ + const char* hitGroupName = nullptr; + const char* closestHitEntryPoint = nullptr; + const char* anyHitEntryPoint = nullptr; + const char* intersectionEntryPoint = nullptr; +}; + +struct RayTracingPipelineStateDesc +{ + IShaderProgram* program = nullptr; + GfxCount hitGroupCount = 0; + const HitGroupDesc* hitGroups = nullptr; + int maxRecursion = 0; + Size maxRayPayloadSize = 0; + Size maxAttributeSizeInBytes = 8; + RayTracingPipelineFlags::Enum flags = RayTracingPipelineFlags::None; +}; + +class IShaderTable : public ISlangUnknown +{ +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. + uint8_t data[8]; // Content to overwrite. + }; + + struct Desc + { + GfxCount rayGenShaderCount; + const char** rayGenShaderEntryPointNames; + const ShaderRecordOverwrite* rayGenShaderRecordOverwrites; + + GfxCount missShaderCount; + const char** missShaderEntryPointNames; + const ShaderRecordOverwrite* missShaderRecordOverwrites; + + GfxCount hitGroupCount; + const char** hitGroupNames; + const ShaderRecordOverwrite* hitGroupRecordOverwrites; + + GfxCount callableShaderCount; + const char** callableShaderEntryPointNames; + const ShaderRecordOverwrite* callableShaderRecordOverwrites; + + IShaderProgram* program; + }; +}; +#define SLANG_UUID_IShaderTable \ + { \ + 0xa721522c, 0xdf31, 0x4c2f, \ + { \ + 0xa5, 0xe7, 0x3b, 0xe0, 0x12, 0x4b, 0x31, 0x78 \ + } \ + } + +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 \ + } \ + } + + +struct ScissorRect +{ + int32_t minX; + int32_t minY; + int32_t maxX; + int32_t maxY; +}; + +struct Viewport +{ + float originX = 0.0f; + float originY = 0.0f; + float extentX = 0.0f; + float extentY = 0.0f; + float minZ = 0.0f; + float maxZ = 1.0f; +}; + +class IFramebuffer : public ISlangUnknown +{ +public: + struct Desc + { + GfxCount renderTargetCount; + IResourceView* const* renderTargetViews; + IResourceView* depthStencilView; + IFramebufferLayout* layout; + }; +}; +#define SLANG_UUID_IFrameBuffer \ + { \ + 0xf0c0d9a, 0x4ef3, 0x4e18, \ + { \ + 0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 \ + } \ + } + +struct WindowHandle +{ + enum class Type + { + Unknown, + Win32Handle, + NSWindowHandle, + XLibHandle, + }; + Type type; + intptr_t handleValues[2]; + static WindowHandle FromHwnd(void* hwnd) + { + WindowHandle handle = {}; + handle.type = WindowHandle::Type::Win32Handle; + handle.handleValues[0] = (intptr_t)(hwnd); + return handle; + } + static WindowHandle FromNSWindow(void* nswindow) + { + WindowHandle handle = {}; + handle.type = WindowHandle::Type::NSWindowHandle; + handle.handleValues[0] = (intptr_t)(nswindow); + return handle; + } + static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow) + { + WindowHandle handle = {}; + handle.type = WindowHandle::Type::XLibHandle; + handle.handleValues[0] = (intptr_t)(xdisplay); + handle.handleValues[1] = xwindow; + return handle; + } +}; + +struct FaceMask +{ + enum Enum + { + Front = 1, + Back = 2 + }; +}; + +class IRenderPassLayout : public ISlangUnknown +{ +public: + enum class TargetLoadOp + { + Load, + Clear, + DontCare + }; + enum class TargetStoreOp + { + Store, + DontCare + }; + struct TargetAccessDesc + { + TargetLoadOp loadOp; + TargetLoadOp stencilLoadOp; + TargetStoreOp storeOp; + TargetStoreOp stencilStoreOp; + ResourceState initialState; + ResourceState finalState; + }; + struct Desc + { + IFramebufferLayout* framebufferLayout = nullptr; + GfxCount renderTargetCount; + TargetAccessDesc* renderTargetAccess = nullptr; + TargetAccessDesc* depthStencilAccess = nullptr; + }; +}; +#define SLANG_UUID_IRenderPassLayout \ + { \ + 0xdaab0b1a, 0xf45d, 0x4ae9, \ + { \ + 0xbf, 0x2c, 0xe0, 0xbb, 0x76, 0x7d, 0xfa, 0xd1 \ + } \ + } + +enum class QueryType +{ + Timestamp, + AccelerationStructureCompactedSize, + AccelerationStructureSerializedSize, + AccelerationStructureCurrentSize, +}; + +class IQueryPool : public ISlangUnknown +{ +public: + struct Desc + { + 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 reset() = 0; +}; +#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}); + +public: + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0; +}; + +struct IndirectDispatchArguments +{ + GfxCount ThreadGroupCountX; + GfxCount ThreadGroupCountY; + GfxCount ThreadGroupCountZ; +}; + +struct IndirectDrawArguments +{ + GfxCount VertexCountPerInstance; + GfxCount InstanceCount; + GfxIndex StartVertexLocation; + GfxIndex StartInstanceLocation; +}; + +struct IndirectDrawIndexedArguments +{ + GfxCount IndexCountPerInstance; + GfxCount InstanceCount; + GfxIndex StartIndexLocation; + GfxIndex BaseVertexLocation; + GfxIndex StartInstanceLocation; +}; + +struct SamplePosition +{ + int8_t x; + int8_t y; +}; + +struct ClearResourceViewFlags +{ + enum Enum : uint32_t + { + None = 0, + ClearDepth = 1, + ClearStencil = 2, + FloatClearValues = 4 + }; +}; + +enum class CooperativeVectorComponentType +{ + Float16 = 0, + Float32 = 1, + Float64 = 2, + SInt8 = 3, + SInt16 = 4, + SInt32 = 5, + SInt64 = 6, + UInt8 = 7, + UInt16 = 8, + UInt32 = 9, + UInt64 = 10, + SInt8Packed = 11, + UInt8Packed = 12, + FloatE4M3 = 13, + FloatE5M2 = 14, +}; + +struct CooperativeVectorProperties +{ + CooperativeVectorComponentType inputType; + CooperativeVectorComponentType inputInterpretation; + CooperativeVectorComponentType matrixInterpretation; + CooperativeVectorComponentType biasInterpretation; + CooperativeVectorComponentType resultType; + bool transpose; +}; + + +class IResourceCommandEncoder : public ICommandEncoder +{ + // {F99A00E9-ED50-4088-8A0E-3B26755031EA} + SLANG_COM_INTERFACE( + 0xf99a00e9, + 0xed50, + 0x4088, + {0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea}); + +public: + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( + IBufferResource* dst, + Offset dstOffset, + IBufferResource* src, + Offset srcOffset, + Size size) = 0; + + /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0 + /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent + /// arguments are ignored. + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( + ITextureResource* dst, + ResourceState dstState, + SubresourceRange dstSubresource, + ITextureResource::Offset3D dstOffset, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Extents extent) = 0; + + /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment. + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( + IBufferResource* dst, + Offset dstOffset, + Size dstSize, + Size dstRowStride, + ITextureResource* src, + ResourceState srcState, + SubresourceRange srcSubresource, + ITextureResource::Offset3D srcOffset, + ITextureResource::Extents extent) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( + ITextureResource* dst, + SubresourceRange subResourceRange, + ITextureResource::Offset3D offset, + ITextureResource::Extents extent, + ITextureResource::SubresourceData* subResourceData, + GfxCount subResourceDataCount) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + 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; + 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; + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( + IResourceView* view, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( + ITextureResource* source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource* dest, + ResourceState destState, + SubresourceRange destRange) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( + IQueryPool* queryPool, + GfxIndex index, + 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 endDebugEvent() = 0; + inline void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst) + { + textureBarrier(1, &texture, src, dst); + } + inline void bufferBarrier(IBufferResource* buffer, ResourceState src, ResourceState dst) + { + bufferBarrier(1, &buffer, src, dst); + } +}; + +class IRenderCommandEncoder : public IResourceCommandEncoder +{ + // {7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE} + 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 + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // 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; + inline IShaderObject* bindPipeline(IPipelineState* state) + { + IShaderObject* rootObject = nullptr; + SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject)); + return rootObject; + } + + // 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; + + 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) + { + setViewports(1, &viewport); + ScissorRect rect = {}; + rect.maxX = static_cast(viewport.extentX); + rect.maxY = static_cast(viewport.extentY); + setScissorRects(1, &rect); + } + + virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( + GfxIndex startSlot, + GfxCount slotCount, + IBufferResource* const* buffers, + const Offset* offsets) = 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; + virtual SLANG_NO_THROW Result SLANG_MCALL + draw(GfxCount vertexCount, GfxIndex startVertex = 0) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL drawIndirect( + GfxCount maxDrawCount, + IBufferResource* argBuffer, + Offset argOffset, + IBufferResource* countBuffer = nullptr, + Offset countOffset = 0) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedIndirect( + GfxCount maxDrawCount, + IBufferResource* argBuffer, + Offset argOffset, + IBufferResource* countBuffer = nullptr, + 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; + virtual SLANG_NO_THROW Result SLANG_MCALL drawInstanced( + GfxCount vertexCount, + GfxCount instanceCount, + GfxIndex startVertex, + GfxIndex startInstanceLocation) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedInstanced( + GfxCount indexCount, + GfxCount instanceCount, + GfxIndex startIndexLocation, + GfxIndex baseVertexLocation, + GfxIndex startInstanceLocation) = 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}) + +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 + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // 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; + inline IShaderObject* bindPipeline(IPipelineState* state) + { + IShaderObject* rootObject = nullptr; + SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject)); + return rootObject; + } + // 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; + 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; +}; + +enum class AccelerationStructureCopyMode +{ + Clone, + Compact +}; + +struct AccelerationStructureQueryDesc +{ + QueryType queryType; + + IQueryPool* queryPool; + + GfxIndex firstQueryIndex; +}; + +class IRayTracingCommandEncoder : public IResourceCommandEncoder +{ + 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, + GfxCount propertyQueryCount, + AccelerationStructureQueryDesc* queryDescs) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure( + IAccelerationStructure* dest, + IAccelerationStructure* src, + AccelerationStructureCopyMode mode) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties( + GfxCount accelerationStructureCount, + IAccelerationStructure* const* accelerationStructures, + GfxCount queryCount, + AccelerationStructureQueryDesc* queryDescs) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL + 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; + + /// 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. + virtual SLANG_NO_THROW Result SLANG_MCALL dispatchRays( + GfxIndex rayGenShaderIndex, + IShaderTable* shaderTable, + GfxCount width, + GfxCount height, + GfxCount depth) = 0; +}; + +class ICommandBuffer : public ISlangUnknown +{ +public: + // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding` + // before calling other `encode*Commands` methods. + // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is + // invalid for further use. To continue recording, the user must request a new encoder + // object by calling one of the `encode*Commands` methods again. + virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands( + IRenderPassLayout* renderPass, + IFramebuffer* framebuffer, + IRenderCommandEncoder** outEncoder) = 0; + inline IRenderCommandEncoder* encodeRenderCommands( + IRenderPassLayout* renderPass, + IFramebuffer* framebuffer) + { + IRenderCommandEncoder* result; + encodeRenderCommands(renderPass, framebuffer, &result); + return result; + } + + virtual SLANG_NO_THROW void SLANG_MCALL + encodeComputeCommands(IComputeCommandEncoder** outEncoder) = 0; + inline IComputeCommandEncoder* encodeComputeCommands() + { + IComputeCommandEncoder* result; + encodeComputeCommands(&result); + return result; + } + + virtual SLANG_NO_THROW void SLANG_MCALL + encodeResourceCommands(IResourceCommandEncoder** outEncoder) = 0; + inline IResourceCommandEncoder* encodeResourceCommands() + { + IResourceCommandEncoder* result; + encodeResourceCommands(&result); + return result; + } + + virtual SLANG_NO_THROW void SLANG_MCALL + encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) = 0; + inline IRayTracingCommandEncoder* encodeRayTracingCommands() + { + IRayTracingCommandEncoder* result; + encodeRayTracingCommands(&result); + return result; + } + + virtual SLANG_NO_THROW void SLANG_MCALL close() = 0; + + 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 \ + } \ + } + +class ICommandBufferD3D12 : public ICommandBuffer +{ +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 \ + } \ + } + +class ICommandQueue : public ISlangUnknown +{ +public: + enum class QueueType + { + Graphics + }; + struct Desc + { + QueueType type; + }; + + // For D3D12, this is the pointer to the queue. For Vulkan, this is the queue itself. + typedef uint64_t NativeHandle; + + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers( + GfxCount count, + ICommandBuffer* const* commandBuffers, + IFence* fenceToSignal, + uint64_t newFenceValue) = 0; + inline void executeCommandBuffer( + ICommandBuffer* commandBuffer, + IFence* fenceToSignal = nullptr, + uint64_t newFenceValue = 0) + { + executeCommandBuffers(1, &commandBuffer, fenceToSignal, newFenceValue); + } + + virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() = 0; + + /// 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; +}; +#define SLANG_UUID_ICommandQueue \ + { \ + 0x14e2bed0, 0xad0, 0x4dc8, \ + { \ + 0xb3, 0x41, 0x6, 0x3f, 0xe7, 0x2d, 0xbf, 0xe \ + } \ + } + +class ITransientResourceHeap : public ISlangUnknown +{ +public: + struct Flags + { + enum Enum + { + None = 0, + AllowResizing = 0x1, + }; + }; + struct Desc + { + Flags::Enum flags; + Size constantBufferSize; + GfxCount samplerDescriptorCount; + GfxCount uavDescriptorCount; + GfxCount srvDescriptorCount; + GfxCount constantBufferDescriptorCount; + GfxCount accelerationStructureDescriptorCount; + }; + + // Waits until GPU commands issued before last call to `finish()` has been completed, and resets + // all transient resources holds by the heap. + // This method must be called before using the transient heap to issue new GPU commands. + // 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. + virtual SLANG_NO_THROW Result SLANG_MCALL finish() = 0; + + // Command buffers are one-time use. Once it is submitted to the queue via + // `executeCommandBuffers` a command buffer is no longer valid to be used any more. Command + // buffers must be closed before submission. The current D3D12 implementation has a limitation + // 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; + inline ComPtr createCommandBuffer() + { + ComPtr result; + SLANG_RETURN_NULL_ON_FAIL(createCommandBuffer(result.writeRef())); + return result; + } +}; +#define SLANG_UUID_ITransientResourceHeap \ + { \ + 0xcd48bd29, 0xee72, 0x41b8, \ + { \ + 0xbc, 0xff, 0xa, 0x2b, 0x3a, 0xaa, 0x6d, 0xeb \ + } \ + } + +class ITransientResourceHeapD3D12 : public ISlangUnknown +{ +public: + enum class DescriptorType + { + ResourceView, + Sampler + }; + virtual SLANG_NO_THROW Result SLANG_MCALL allocateTransientDescriptorTable( + DescriptorType type, + GfxCount count, + Offset& outDescriptorOffset, + void** outD3DDescriptorHeapHandle) = 0; +}; +#define SLANG_UUID_ITransientResourceHeapD3D12 \ + { \ + 0x9bc6a8bc, 0x5f7a, 0x454a, \ + { \ + 0x93, 0xef, 0x3b, 0x10, 0x5b, 0xb7, 0x63, 0x7e \ + } \ + } + +class ISwapchain : public ISlangUnknown +{ +public: + struct Desc + { + Format format; + GfxCount width, height; + GfxCount imageCount; + ICommandQueue* queue; + bool enableVSync; + }; + virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; + + /// Returns the back buffer image at `index`. + virtual SLANG_NO_THROW Result SLANG_MCALL + getImage(GfxIndex index, ITextureResource** outResource) = 0; + + /// Present the next image in the swapchain. + virtual SLANG_NO_THROW Result SLANG_MCALL present() = 0; + + /// Returns the index of next back buffer image that will be presented in the next + /// `present` call. If the swapchain is invalid/out-of-date, this method returns -1. + virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() = 0; + + /// Resizes the back buffers of this swapchain. All render target views and framebuffers + /// referencing the back buffer images must be freed before calling this method. + virtual SLANG_NO_THROW Result SLANG_MCALL resize(GfxCount width, GfxCount height) = 0; + + // Check if the window is occluded. + virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded() = 0; + + // 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 \ + } \ + } + +struct AdapterLUID +{ + uint8_t luid[16]; + + bool operator==(const AdapterLUID& other) const + { + for (size_t i = 0; i < sizeof(AdapterLUID::luid); ++i) + if (luid[i] != other.luid[i]) + return false; + return true; + } + bool operator!=(const AdapterLUID& other) const { return !this->operator==(other); } +}; + +struct AdapterInfo +{ + // Descriptive name of the adapter. + char name[128]; + + // 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) + uint32_t deviceID; + + // Logically unique identifier of the adapter. + AdapterLUID luid; +}; + +class AdapterList +{ +public: + AdapterList(ISlangBlob* blob) + : m_blob(blob) + { + } + + const AdapterInfo* getAdapters() const + { + return reinterpret_cast(m_blob ? m_blob->getBufferPointer() : nullptr); + } + + GfxCount getCount() const + { + return (GfxCount)(m_blob ? m_blob->getBufferSize() / sizeof(AdapterInfo) : 0); + } + +private: + ComPtr m_blob; +}; + +struct DeviceLimits +{ + /// Maximum dimension for 1D textures. + uint32_t maxTextureDimension1D; + /// Maximum dimensions for 2D textures. + uint32_t maxTextureDimension2D; + /// Maximum dimensions for 3D textures. + uint32_t maxTextureDimension3D; + /// Maximum dimensions for cube textures. + uint32_t maxTextureDimensionCube; + /// Maximum number of texture layers. + uint32_t maxTextureArrayLayers; + + /// Maximum number of vertex input elements in a graphics pipeline. + uint32_t maxVertexInputElements; + /// Maximum offset of a vertex input element in the vertex stream. + uint32_t maxVertexInputElementOffset; + /// Maximum number of vertex streams in a graphics pipeline. + uint32_t maxVertexStreams; + /// Maximum stride of a vertex stream. + uint32_t maxVertexStreamStride; + + /// Maximum number of threads per thread group. + uint32_t maxComputeThreadsPerGroup; + /// Maximum dimensions of a thread group. + uint32_t maxComputeThreadGroupSize[3]; + /// Maximum number of thread groups per dimension in a single dispatch. + uint32_t maxComputeDispatchThreadGroups[3]; + + /// Maximum number of viewports per pipeline. + uint32_t maxViewports; + /// Maximum viewport dimensions. + uint32_t maxViewportDimensions[2]; + /// Maximum framebuffer dimensions. + uint32_t maxFramebufferDimensions[3]; + + /// Maximum samplers visible in a shader stage. + uint32_t maxShaderVisibleSamplers; +}; + +struct DeviceInfo +{ + DeviceType deviceType; + + DeviceLimits limits; + + BindingStyle bindingStyle; + + ProjectionStyle projectionStyle; + + /// An projection matrix that ensures x, y mapping to pixels + /// is the same on all targets + float identityProjectionMatrix[16]; + + /// The name of the graphics API being used by this device. + const char* apiName = nullptr; + + /// The name of the graphics adapter. + const char* adapterName = nullptr; + + /// The clock frequency used in timestamp queries. + uint64_t timestampFrequency = 0; +}; + +enum class DebugMessageType +{ + Info, + Warning, + Error +}; +enum class DebugMessageSource +{ + Layer, + Driver, + Slang +}; +class IDebugCallback +{ +public: + virtual SLANG_NO_THROW void SLANG_MCALL + handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) = 0; +}; + +class IDevice : public ISlangUnknown +{ +public: + struct SlangDesc + { + 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; + + slang::PreprocessorMacroDesc const* preprocessorMacros = nullptr; + GfxCount preprocessorMacroCount = 0; + + 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; + }; + + struct ShaderCacheDesc + { + // The root directory for the shader cache. If not set, shader cache is disabled. + const char* shaderCachePath = nullptr; + // The maximum number of entries stored in the cache. By default, there is no limit. + GfxCount maxEntryCount = 0; + }; + + struct InteropHandles + { + InteropHandle handles[3] = {}; + }; + + struct Desc + { + // 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. + InteropHandles existingDeviceHandles; + // LUID of the adapter to use. Use getGfxAdapters() to get a list of available adapters. + const AdapterLUID* adapterLUID = nullptr; + // Number of required features. + GfxCount requiredFeatureCount = 0; + // Array of required feature names, whose size is `requiredFeatureCount`. + const char** requiredFeatures = nullptr; + // A command dispatcher object that intercepts and handles actual low-level API call. + ISlangUnknown* apiCommandDispatcher = nullptr; + // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required. + GfxIndex nvapiExtnSlot = -1; + // Configurations for the shader cache. + ShaderCacheDesc shaderCache = {}; + // Configurations for Slang compiler. + SlangDesc slang = {}; + + GfxCount extendedDescCount = 0; + void** extendedDescs = nullptr; + }; + + 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; + + 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; + + inline ComPtr getSlangSession() + { + ComPtr result; + getSlangSession(result.writeRef()); + return result; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap( + const ITransientResourceHeap::Desc& desc, + ITransientResourceHeap** outHeap) = 0; + inline ComPtr createTransientResourceHeap( + const ITransientResourceHeap::Desc& desc) + { + ComPtr result; + createTransientResourceHeap(desc, result.writeRef()); + 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); + /// + 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. + inline SLANG_NO_THROW ComPtr createTextureResource( + const ITextureResource::Desc& desc, + const ITextureResource::SubresourceData* initData = nullptr) + { + ComPtr resource; + SLANG_RETURN_NULL_ON_FAIL(createTextureResource(desc, initData, resource.writeRef())); + return resource; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + ITextureResource** outResource) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle( + InteropHandle handle, + const ITextureResource::Desc& srcDesc, + const Size size, + ITextureResource** outResource) = 0; + + /// Create a buffer resource + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( + const IBufferResource::Desc& desc, + const void* initData, + IBufferResource** outResource) = 0; + + inline SLANG_NO_THROW ComPtr createBufferResource( + const IBufferResource::Desc& desc, + const void* initData = nullptr) + { + ComPtr resource; + SLANG_RETURN_NULL_ON_FAIL(createBufferResource(desc, initData, resource.writeRef())); + return resource; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle( + InteropHandle handle, + const IBufferResource::Desc& srcDesc, + IBufferResource** outResource) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL + createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) = 0; + + inline ComPtr createSamplerState(ISamplerState::Desc const& desc) + { + ComPtr sampler; + SLANG_RETURN_NULL_ON_FAIL(createSamplerState(desc, sampler.writeRef())); + return sampler; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( + ITextureResource* texture, + IResourceView::Desc const& desc, + IResourceView** outView) = 0; + + inline ComPtr createTextureView( + ITextureResource* texture, + IResourceView::Desc const& desc) + { + ComPtr view; + SLANG_RETURN_NULL_ON_FAIL(createTextureView(texture, desc, view.writeRef())); + return view; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView( + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc, + IResourceView** outView) = 0; + + inline ComPtr createBufferView( + 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; + inline ComPtr createFramebufferLayout(IFramebufferLayout::Desc const& desc) + { + ComPtr fb; + SLANG_RETURN_NULL_ON_FAIL(createFramebufferLayout(desc, fb.writeRef())); + return fb; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL + createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0; + inline ComPtr createFramebuffer(IFramebuffer::Desc const& desc) + { + ComPtr fb; + SLANG_RETURN_NULL_ON_FAIL(createFramebuffer(desc, fb.writeRef())); + return fb; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createRenderPassLayout( + const IRenderPassLayout::Desc& desc, + IRenderPassLayout** outRenderPassLayout) = 0; + inline ComPtr createRenderPassLayout(const IRenderPassLayout::Desc& desc) + { + ComPtr rs; + SLANG_RETURN_NULL_ON_FAIL(createRenderPassLayout(desc, rs.writeRef())); + return rs; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain( + ISwapchain::Desc const& desc, + WindowHandle window, + ISwapchain** outSwapchain) = 0; + inline ComPtr createSwapchain(ISwapchain::Desc const& desc, WindowHandle window) + { + ComPtr swapchain; + SLANG_RETURN_NULL_ON_FAIL(createSwapchain(desc, window, swapchain.writeRef())); + return swapchain; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL + createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) = 0; + + inline ComPtr createInputLayout(IInputLayout::Desc const& desc) + { + ComPtr layout; + SLANG_RETURN_NULL_ON_FAIL(createInputLayout(desc, layout.writeRef())); + return layout; + } + + inline Result createInputLayout( + Size vertexSize, + InputElementDesc const* inputElements, + GfxCount inputElementCount, + IInputLayout** outLayout) + { + VertexStreamDesc streamDesc = {vertexSize, InputSlotClass::PerVertex, 0}; + + IInputLayout::Desc inputLayoutDesc = {}; + inputLayoutDesc.inputElementCount = inputElementCount; + inputLayoutDesc.inputElements = inputElements; + inputLayoutDesc.vertexStreamCount = 1; + inputLayoutDesc.vertexStreams = &streamDesc; + return createInputLayout(inputLayoutDesc, outLayout); + } + + inline ComPtr createInputLayout( + Size vertexSize, + InputElementDesc const* inputElements, + GfxCount inputElementCount) + { + ComPtr layout; + 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; + inline ComPtr createCommandQueue(const ICommandQueue::Desc& desc) + { + ComPtr queue; + SLANG_RETURN_NULL_ON_FAIL(createCommandQueue(desc, queue.writeRef())); + return queue; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject( + slang::TypeReflection* type, + ShaderObjectContainerType container, + IShaderObject** outObject) = 0; + + inline ComPtr createShaderObject(slang::TypeReflection* type) + { + ComPtr object; + SLANG_RETURN_NULL_ON_FAIL( + createShaderObject(type, ShaderObjectContainerType::None, object.writeRef())); + return object; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject( + slang::TypeReflection* type, + ShaderObjectContainerType container, + IShaderObject** outObject) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectFromTypeLayout( + 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, 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, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob = nullptr) = 0; + + inline ComPtr createProgram(const IShaderProgram::Desc& desc) + { + ComPtr program; + SLANG_RETURN_NULL_ON_FAIL(createProgram(desc, program.writeRef())); + return program; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram2( + const IShaderProgram::CreateDesc2& createDesc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob = nullptr) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( + const GraphicsPipelineStateDesc& desc, + IPipelineState** outState) = 0; + + 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; + + inline ComPtr createComputePipelineState(const ComputePipelineStateDesc& desc) + { + ComPtr state; + SLANG_RETURN_NULL_ON_FAIL(createComputePipelineState(desc, state.writeRef())); + return state; + } + + virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState( + const RayTracingPipelineStateDesc& desc, + IPipelineState** outState) = 0; + + /// Read back texture resource and stores the result in `outBlob`. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource( + ITextureResource* resource, + ResourceState state, + ISlangBlob** outBlob, + Size* outRowPitch, + Size* outPixelSize) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + readBufferResource(IBufferResource* buffer, Offset offset, Size size, ISlangBlob** outBlob) = 0; + + /// 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 getAccelerationStructurePrebuildInfo( + const IAccelerationStructure::BuildInputs& buildInputs, + IAccelerationStructure::PrebuildInfo* outPrebuildInfo) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure( + const IAccelerationStructure::CreateDesc& desc, + IAccelerationStructure** outView) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL + 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`. + virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences( + GfxCount fenceCount, + IFence** fences, + uint64_t* values, + bool waitForAll, + uint64_t timeout) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo( + const ITextureResource::Desc& desc, + Size* outSize, + Size* outAlignment) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(Size* outAlignment) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL getCooperativeVectorProperties( + CooperativeVectorProperties* properties, + uint32_t* propertyCount) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject2( + slang::ISession* slangSession, + slang::TypeReflection* type, + ShaderObjectContainerType container, + IShaderObject** outObject) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject2( + slang::ISession* slangSession, + slang::TypeReflection* type, + ShaderObjectContainerType container, + IShaderObject** outObject) = 0; +}; + +#define SLANG_UUID_IDevice \ + { \ + 0x715bdf26, 0x5135, 0x11eb, \ + { \ + 0xAE, 0x93, 0x02, 0x42, 0xAC, 0x13, 0x00, 0x02 \ + } \ + } + +struct ShaderCacheStats +{ + GfxCount hitCount; + GfxCount missCount; + GfxCount entryCount; +}; + +// These are exclusively used to track hit/miss counts for shader cache entries. Entry hit and +// miss counts specifically indicate if the file containing relevant shader code was found in +// the cache, while the general hit and miss counts indicate whether the file was both found and +// up-to-date. +class IShaderCache : public ISlangUnknown +{ +public: + virtual SLANG_NO_THROW Result SLANG_MCALL clearShaderCache() = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL getShaderCacheStats(ShaderCacheStats* outStats) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL resetShaderCacheStats() = 0; +}; + +#define SLANG_UUID_IShaderCache \ + { \ + 0x8eccc8ec, 0x5c04, 0x4a51, \ + { \ + 0x99, 0x75, 0x13, 0xf8, 0xfe, 0xa1, 0x59, 0xf3 \ + } \ + } + +class IPipelineCreationAPIDispatcher : public ISlangUnknown +{ +public: + virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState( + IDevice* device, + slang::IComponentType* program, + void* pipelineDesc, + void** outPipelineState) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( + IDevice* device, + slang::IComponentType* program, + void* pipelineDesc, + void** outPipelineState) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createMeshPipelineState( + IDevice* device, + slang::IComponentType* program, + void* pipelineDesc, + void** outPipelineState) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + beforeCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + 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_IVulkanPipelineCreationAPIDispatcher \ + { \ + 0x4fcf1274, 0x8752, 0x4743, \ + { \ + 0xb3, 0x51, 0x47, 0xcb, 0x83, 0x71, 0xef, 0x99 \ + } \ + } + +// Global public functions + +extern "C" +{ + /// Checks if format is compressed + SLANG_GFX_API bool SLANG_MCALL gfxIsCompressedFormat(Format format); + + /// Checks if format is typeless + SLANG_GFX_API bool SLANG_MCALL gfxIsTypelessFormat(Format format); + + /// Gets information about the format + 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); + + /// 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); + + /// Reports current set of live objects in gfx. + /// Currently this only calls D3D's ReportLiveObjects. + SLANG_GFX_API SlangResult SLANG_MCALL gfxReportLiveObjects(); + + /// 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); + + /// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are + /// valid. + SLANG_GFX_API void SLANG_MCALL gfxEnableDebugLayer(bool enable); + + SLANG_GFX_API const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type); +} + +/// Gets a list of available adapters for a given device type +inline AdapterList gfxGetAdapters(DeviceType type) +{ + ComPtr blob; + gfxGetAdapters(type, blob.writeRef()); + return AdapterList(blob); +} + +// Extended descs. +struct D3D12ExperimentalFeaturesDesc +{ + StructType structType = StructType::D3D12ExperimentalFeaturesDesc; + uint32_t numFeatures; + const void* featureIIDs; + void* configurationStructs; + uint32_t* configurationStructSizes; +}; + +struct D3D12DeviceExtendedDesc +{ + StructType structType = StructType::D3D12DeviceExtendedDesc; + const char* rootParameterShaderAttributeName = nullptr; + bool debugBreakOnD3D12Error = false; + uint32_t highestShaderModel = 0; +}; + +struct SlangSessionExtendedDesc +{ + StructType structType = StructType::SlangSessionExtendedDesc; + uint32_t compilerOptionEntryCount = 0; + slang::CompilerOptionEntry* compilerOptionEntries = nullptr; +}; + +/// 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/lib/All/slang/include/slang-hlsl-prelude.h b/lib/All/slang/include/slang-hlsl-prelude.h new file mode 100644 index 0000000..8e77201 --- /dev/null +++ b/lib/All/slang/include/slang-hlsl-prelude.h @@ -0,0 +1,8 @@ +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif + +#ifndef __DXC_VERSION_MAJOR +// warning X3557: loop doesn't seem to do anything, forcing loop to unroll +#pragma warning(disable : 3557) +#endif diff --git a/lib/All/slang/include/slang-image-format-defs.h b/lib/All/slang/include/slang-image-format-defs.h new file mode 100644 index 0000000..5e7922f --- /dev/null +++ b/lib/All/slang/include/slang-image-format-defs.h @@ -0,0 +1,50 @@ +// slang-image-format-defs.h +#ifndef SLANG_FORMAT + #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(bgra8, (UINT8, 4, sizeof(uint32_t))) + +#undef SLANG_FORMAT diff --git a/lib/All/slang/include/slang-llvm.h b/lib/All/slang/include/slang-llvm.h new file mode 100644 index 0000000..e0bbbd1 --- /dev/null +++ b/lib/All/slang/include/slang-llvm.h @@ -0,0 +1,404 @@ +#ifndef SLANG_LLVM_H +#define SLANG_LLVM_H + +// 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 +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 +#endif + +/* +Taken from stddef.h +*/ + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +typedef __SIZE_TYPE__ rsize_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 +#else +#define NULL ((void*)0) +#endif +#ifdef __cplusplus +#if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED) +namespace std +{ +typedef decltype(nullptr) nullptr_t; +} +using ::std::nullptr_t; +#endif +#endif +#undef __need_NULL +#endif /* defined(__need_NULL) */ + + +/* +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*/ +typedef __INT64_TYPE__ int64_t; +#endif /* __int8_t_defined */ +typedef __UINT64_TYPE__ uint64_t; +#define __int_least64_t int64_t +#define __uint_least64_t uint64_t +#endif /* __INT64_TYPE__ */ + +#ifdef __int_least64_t +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; +typedef __int_least64_t int_fast64_t; +typedef __uint_least64_t uint_fast64_t; +#endif /* __int_least64_t */ + +#ifdef __INT32_TYPE__ + +#ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/ +typedef __INT32_TYPE__ int32_t; +#endif /* __int8_t_defined */ + +#ifndef __uint32_t_defined /* more glibc compatibility */ +#define __uint32_t_defined +typedef __UINT32_TYPE__ uint32_t; +#endif /* __uint32_t_defined */ + +#define __int_least32_t int32_t +#define __uint_least32_t uint32_t +#endif /* __INT32_TYPE__ */ + +#ifdef __int_least32_t +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least32_t int_fast32_t; +typedef __uint_least32_t uint_fast32_t; +#endif /* __int_least32_t */ + +#ifdef __INT16_TYPE__ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int16_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 +#endif /* __INT16_TYPE__ */ + +#ifdef __int_least16_t +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least16_t int_fast16_t; +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*/ +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 +#endif /* __INT8_TYPE__ */ + +#ifdef __int_least8_t +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least8_t int_fast8_t; +typedef __uint_least8_t uint_fast8_t; +#endif /* __int_least8_t */ + +/* prevent glibc sys/types.h from defining conflicting types */ +#ifndef __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 + +#ifndef _INTPTR_T +#ifndef __intptr_t_defined +typedef __INTPTR_TYPE__ intptr_t; +#define __intptr_t_defined +#define _INTPTR_T +#endif +#endif + +#ifndef _UINTPTR_T +typedef __UINTPTR_TYPE__ uintptr_t; +#define _UINTPTR_T +#endif + +/* C99 7.18.1.5 Greatest-width integer types. + */ +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +/* C99 7.18.4 Macros for minimum-width integer constants. + * + * The standard requires that integer constant macros be defined for all the + * minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width + * types are required, the corresponding integer constant macros are defined + * here. This implementation also defines minimum-width types for every other + * integer width that the target implements, so corresponding macros are + * defined below, too. + * + * These macros are defined using the same successive-shrinking approach as + * the type definitions above. It is likewise important that macros are defined + * in order of decending width. + * + * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the + * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]). + */ + +#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__ */ +#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 */ +#endif /* __int_least64_t */ + + +#ifdef __INT32_TYPE__ +#ifdef __INT32_C_SUFFIX__ +#define __int32_c_suffix __INT32_C_SUFFIX__ +#else +#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 */ +#endif /* __int_least32_t */ + +#ifdef __INT16_TYPE__ +#ifdef __INT16_C_SUFFIX__ +#define __int16_c_suffix __INT16_C_SUFFIX__ +#else +#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 */ +#endif /* __int_least16_t */ + + +#ifdef __INT8_TYPE__ +#ifdef __INT8_C_SUFFIX__ +#define __int8_c_suffix __INT8_C_SUFFIX__ +#else +#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 */ +#endif /* __int_least8_t */ + +/* C99 7.18.2.1 Limits of exact-width integer types. + * C99 7.18.2.2 Limits of minimum-width integer types. + * C99 7.18.2.3 Limits of fastest minimum-width integer types. + * + * The presence of limit macros are completely optional in C99. This + * implementation defines limits for all of the types (exact- and + * minimum-width) that it defines above, using the limits of the minimum-width + * type for any types that do not have exact-width representations. + * + * As in the type definitions, this section takes an approach of + * successive-shrinking to determine which limits to use for the standard (8, + * 16, 32, 64) bit widths when they don't have exact representations. It is + * therefore important that the definitions be kept in order of decending + * widths. + * + * Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the + * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]). + */ + +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 +#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 __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__ + +/* 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) +#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__ + +/* 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__) +#else +#define WINT_MIN __INTN_MIN(__WINT_WIDTH__) +#define WINT_MAX __INTN_MAX(__WINT_WIDTH__) +#endif + +#ifndef 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 +#endif + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#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/lib/All/slang/include/slang-tag-version.h b/lib/All/slang/include/slang-tag-version.h new file mode 100644 index 0000000..22466c5 --- /dev/null +++ b/lib/All/slang/include/slang-tag-version.h @@ -0,0 +1,2 @@ +#define SLANG_TAG_VERSION "2026.3.1" +#define SLANG_VERSION_NUMERIC "2026.3.1" diff --git a/lib/All/slang/include/slang-torch-prelude.h b/lib/All/slang/include/slang-torch-prelude.h new file mode 100644 index 0000000..e1a0e08 --- /dev/null +++ b/lib/All/slang/include/slang-torch-prelude.h @@ -0,0 +1,183 @@ +// Prelude for PyTorch cpp binding. + +// clang-format off +#include +// clang-format on + +#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 +#endif // SLANG_LLVM + +#include "../source/core/slang-string.h" + +#if defined(_MSC_VER) +#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 } +#else +#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 +#endif +#ifndef SLANG_STDCALL +#define SLANG_STDCALL +#endif +#ifndef SLANG_MCALL +#define SLANG_MCALL SLANG_STDCALL +#endif +#ifndef SLANG_FORCE_INLINE +#define SLANG_FORCE_INLINE inline +#endif +#include "slang-cpp-scalar-intrinsics.h" +#include "slang-cpp-types-core.h" + + +static const int kSlangTorchTensorMaxDim = 5; + +// NOTE: If you change this struct's layout, also update the hard-coded size/alignment +// in _createTypeLayout() in slang-type-layout.cpp. +struct TensorView +{ + uint8_t* data; + uint32_t strides[kSlangTorchTensorMaxDim]; + uint32_t sizes[kSlangTorchTensorMaxDim]; + uint32_t dimensionCount; +}; + + +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. + // 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()); + + // 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()); + + // Check that the tensor is contiguous + if (requireContiguous && !val.is_contiguous()) + throw std::runtime_error(std::string(name).append(": tensor is not contiguous.").c_str()); + + TensorView res = {}; + res.dimensionCount = val.dim(); + res.data = nullptr; + size_t elementSize = 4; + + switch (val.scalar_type()) + { + case torch::kInt8: + case torch::kUInt8: + elementSize = 1; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kBFloat16: + elementSize = 2; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kFloat16: + elementSize = 2; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kInt16: + elementSize = 2; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kFloat32: + elementSize = 4; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kInt32: + elementSize = 4; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kFloat64: + elementSize = 8; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kInt64: + elementSize = 8; + res.data = (uint8_t*)val.data_ptr(); + break; + case torch::kBool: + elementSize = 1; + res.data = (uint8_t*)val.data_ptr(); + break; + } + + 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()); + + 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()); + + res.sizes[i] = val.size(i); + if (res.sizes[i] > 0) + isEmpty = false; + } + + if (!res.data && !isEmpty) + throw std::runtime_error(std::string(name).append(": data pointer is invalid.").c_str()); + + return res; +} + +#define SLANG_PRELUDE_EXPORT diff --git a/lib/All/slang/include/slang.h b/lib/All/slang/include/slang.h new file mode 100644 index 0000000..f2e1d72 --- /dev/null +++ b/lib/All/slang/include/slang.h @@ -0,0 +1,5181 @@ +#ifndef SLANG_H +#define SLANG_H + +#ifdef SLANG_USER_CONFIG + #include SLANG_USER_CONFIG +#endif + +/** \file slang.h + +The Slang API provides services to compile, reflect, and specialize code +written in the Slang shading language. +*/ + +/* +The following section attempts to detect the compiler and version in use. + +If an application defines `SLANG_COMPILER` before including this header, +they take responsibility for setting any compiler-dependent macros +used later in the file. + +Most applications should not need to touch this section. +*/ +#ifndef 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 +#endif /* SLANG_COMPILER */ + +/* +The following section attempts to detect the target platform being compiled for. + +If an application defines `SLANG_PLATFORM` before including this header, +they take responsibility for setting any compiler-dependent macros +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 + #ifndef SLANG_WASM + #define SLANG_WASM 0 + #endif +#endif /* SLANG_PLATFORM */ + +/* Shorthands for "families" of compilers/platforms */ +#define SLANG_GCC_FAMILY (SLANG_CLANG || SLANG_SNC || SLANG_GHS || SLANG_GCC) +#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 */ + +/* 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 +#else + #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 +#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 +#else + #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 +#endif +#ifndef 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 +#endif +#ifndef SLANG_MCALL + #define SLANG_MCALL SLANG_STDCALL +#endif + + +#if !defined(SLANG_STATIC) && !defined(SLANG_DYNAMIC) + #define SLANG_DYNAMIC +#endif + +#if defined(_MSC_VER) + #define SLANG_DLL_EXPORT __declspec(dllexport) +#else + #if SLANG_WINDOWS_FAMILY + #define SLANG_DLL_EXPORT \ + __attribute__((dllexport)) __attribute__((__visibility__("default"))) + #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 + // TODO: need to consider compiler capabilities + // # ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_API SLANG_DLL_EXPORT + // # endif + #endif +#endif + +#ifndef 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(); +#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) +#endif + +#ifndef SLANG_OFFSET_OF + #define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1) +#endif + +// Microsoft VC specific +#if SLANG_VC + #define SLANG_NO_INLINE __declspec(noinline) + #define SLANG_FORCE_INLINE __forceinline + #define SLANG_BREAKPOINT(id) __debugbreak(); + + #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 +#endif +#ifndef SLANG_NO_INLINE + #define SLANG_NO_INLINE +#endif + +#ifndef SLANG_COMPILE_TIME_ASSERT + #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)); +#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]))) +/// SLANG_INLINE exists to have a way to inline consistent with SLANG_ALWAYS_INLINE +#define SLANG_INLINE inline + +// If explicitly disabled and not set, set to not available +#if !defined(SLANG_HAS_EXCEPTIONS) && defined(SLANG_DISABLE_EXCEPTIONS) + #define SLANG_HAS_EXCEPTIONS 0 +#endif + +// If not set, the default is exceptions are available +#ifndef SLANG_HAS_EXCEPTIONS + #define SLANG_HAS_EXCEPTIONS 1 +#endif + +// Other defines +#define SLANG_STRINGIZE_HELPER(X) #X +#define SLANG_STRINGIZE(X) SLANG_STRINGIZE_HELPER(X) + +#define SLANG_CONCAT_HELPER(X, Y) X##Y +#define SLANG_CONCAT(X, Y) SLANG_CONCAT_HELPER(X, Y) + +#ifndef SLANG_UNUSED + #define SLANG_UNUSED(v) (void)v; +#endif + +#if defined(__llvm__) + #define SLANG_MAYBE_UNUSED [[maybe_unused]] +#else + #define SLANG_MAYBE_UNUSED +#endif + +// Used for doing constant literals +#ifndef SLANG_INT64 + #define SLANG_INT64(x) (x##ll) +#endif +#ifndef SLANG_UINT64 + #define SLANG_UINT64(x) (x##ull) +#endif + + +#ifdef __cplusplus + #define SLANG_EXTERN_C extern "C" +#else + #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 + +#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 +#elif defined(__i386__) || defined(_M_IX86) + #define SLANG_PROCESSOR_X86 1 +#elif defined(_M_AMD64) || defined(_M_X64) || defined(__amd64) || defined(__x86_64) + #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 +#elif defined(__arm__) + #define SLANG_PROCESSOR_ARM 1 +#elif defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) + #define SLANG_PROCESSOR_ARM_64 1 +#elif defined(__EMSCRIPTEN__) + #define SLANG_PROCESSOR_WASM 1 +#endif + +#ifndef SLANG_PROCESSOR_ARM + #define SLANG_PROCESSOR_ARM 0 +#endif + +#ifndef SLANG_PROCESSOR_ARM_64 + #define SLANG_PROCESSOR_ARM_64 0 +#endif + +#ifndef SLANG_PROCESSOR_X86 + #define SLANG_PROCESSOR_X86 0 +#endif + +#ifndef SLANG_PROCESSOR_X86_64 + #define SLANG_PROCESSOR_X86_64 0 +#endif + +#ifndef SLANG_PROCESSOR_POWER_PC + #define SLANG_PROCESSOR_POWER_PC 0 +#endif + +#ifndef SLANG_PROCESSOR_POWER_PC_64 + #define SLANG_PROCESSOR_POWER_PC_64 0 +#endif + +#ifndef SLANG_PROCESSOR_WASM + #define SLANG_PROCESSOR_WASM 0 +#endif + +// Processor families + +#define SLANG_PROCESSOR_FAMILY_X86 (SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_X86) +#define SLANG_PROCESSOR_FAMILY_ARM (SLANG_PROCESSOR_ARM | SLANG_PROCESSOR_ARM_64) +#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_32 (SLANG_PTR_IS_64 ^ 1) + +// Processor features +#if SLANG_PROCESSOR_FAMILY_X86 + #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 +#elif SLANG_PROCESSOR_FAMILY_POWER_PC + #define SLANG_BIG_ENDIAN 1 +#elif SLANG_WASM + #define SLANG_LITTLE_ENDIAN 1 +#endif + +#ifndef SLANG_LITTLE_ENDIAN + #define SLANG_LITTLE_ENDIAN 0 +#endif + +#ifndef SLANG_BIG_ENDIAN + #define SLANG_BIG_ENDIAN 0 +#endif + +#ifndef SLANG_UNALIGNED_ACCESS + #define SLANG_UNALIGNED_ACCESS 0 +#endif + +// Backtrace +#if SLANG_LINUX_FAMILY + #include // for __GLIBC__ define, if using GNU libc + #if defined(__GLIBC__) || (__ANDROID_API__ >= 33) + #define SLANG_HAS_BACKTRACE 1 + #else + #define SLANG_HAS_BACKTRACE 0 + #endif +#else + #define SLANG_HAS_BACKTRACE 0 +#endif + +// One endianness must be set +#if ((SLANG_BIG_ENDIAN | SLANG_LITTLE_ENDIAN) == 0) + #error "Couldn't determine endianness" +#endif + +#ifndef SLANG_NO_INTTYPES + #include +#endif // ! SLANG_NO_INTTYPES + +#ifndef SLANG_NO_STDDEF + #include +#endif // ! SLANG_NO_STDDEF + +#ifdef SLANG_NO_DEPRECATION + #define SLANG_DEPRECATED +#else + #define SLANG_DEPRECATED [[deprecated]] +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + /*! + @mainpage Introduction + + API Reference: slang.h + + @file slang.h + */ + + 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. + // + // 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 SlangSSizeT; + typedef uint64_t SlangSizeT; +#else +typedef int32_t SlangInt; +typedef uint32_t SlangUInt; + +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 + conditions, and all values >= SLANG_SEVERITY_ERROR indicating compilation + failure. + */ + typedef int SlangSeverityIntegral; + enum SlangSeverity : SlangSeverityIntegral + { + SLANG_SEVERITY_DISABLED = 0, /**< A message that is disabled, filtered out. */ + SLANG_SEVERITY_NOTE, /**< An informative message. */ + SLANG_SEVERITY_WARNING, /**< A warning, which indicates a possible problem. */ + 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. + */ + }; + + typedef int SlangDiagnosticFlags; + enum + { + SLANG_DIAGNOSTIC_FLAG_VERBOSE_PATHS = 0x01, + SLANG_DIAGNOSTIC_FLAG_TREAT_WARNINGS_AS_ERRORS = 0x02 + }; + + typedef int SlangBindableResourceIntegral; + enum SlangBindableResourceType : SlangBindableResourceIntegral + { + SLANG_NON_BINDABLE = 0, + SLANG_TEXTURE, + SLANG_SAMPLER, + SLANG_UNIFORM_BUFFER, + SLANG_STORAGE_BUFFER, + }; + + /* NOTE! To keep binary compatibility care is needed with this enum! + + * 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. + */ + typedef int SlangCompileTargetIntegral; + enum SlangCompileTarget : SlangCompileTargetIntegral + { + 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_HLSL, + SLANG_SPIRV, + SLANG_SPIRV_ASM, + SLANG_DXBC, + 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 (kernel/shader) + 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_HOST_VM, ///< Bytecode that can be interpreted by the Slang VM + SLANG_CPP_HEADER, ///< C++ header for shader kernels. + SLANG_CUDA_HEADER, ///< Cuda header + + SLANG_HOST_OBJECT_CODE, ///< Host object code + SLANG_HOST_LLVM_IR, ///< Host LLVM IR assembly + SLANG_SHADER_LLVM_IR, ///< Host LLVM IR assembly (kernel/shader) + + SLANG_TARGET_COUNT_OF, + }; + + /* A "container format" describes the way that the outputs + for multiple files, entry points, targets, etc. should be + combined into a single artifact for output. */ + typedef int SlangContainerFormatIntegral; + enum SlangContainerFormat : SlangContainerFormatIntegral + { + /* Don't generate a container. */ + SLANG_CONTAINER_FORMAT_NONE, + + /* Generate a container in the `.slang-module` format, + which includes reflection information, compiled kernels, etc. */ + SLANG_CONTAINER_FORMAT_SLANG_MODULE, + }; + + typedef int SlangPassThroughIntegral; + enum SlangPassThrough : SlangPassThroughIntegral + { + SLANG_PASS_THROUGH_NONE, + SLANG_PASS_THROUGH_FXC, + 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_SPIRV_LINK, ///< SPIRV-link + SLANG_PASS_THROUGH_COUNT_OF, + }; + + /* Defines an archive type used to holds a 'file system' type structure. */ + typedef int SlangArchiveTypeIntegral; + enum SlangArchiveType : SlangArchiveTypeIntegral + { + SLANG_ARCHIVE_TYPE_UNDEFINED, + SLANG_ARCHIVE_TYPE_ZIP, + SLANG_ARCHIVE_TYPE_RIFF, ///< Riff container with no compression + SLANG_ARCHIVE_TYPE_RIFF_DEFLATE, + SLANG_ARCHIVE_TYPE_RIFF_LZ4, + SLANG_ARCHIVE_TYPE_COUNT_OF, + }; + + /*! + Flags to control compilation behavior. + */ + typedef unsigned int SlangCompileFlags; + enum + { + /* Do as little mangling of names as possible, to try to preserve original names */ + 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, + + /* Obfuscate shader names on release products */ + SLANG_COMPILE_FLAG_OBFUSCATE = 1 << 5, + + /* 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, + }; + + /*! + @brief Flags to control code generation behavior of a compilation target */ + typedef unsigned int SlangTargetFlags; + enum + { + /* When compiling for a D3D Shader Model 5.1 or higher target, allocate + distinct register spaces for parameter blocks. + + @deprecated This behavior is now enabled unconditionally. + */ + SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES = 1 << 4, + + /* When set, will generate target code that contains all entrypoints defined + in the input source or specified via the `spAddEntryPoint` function in a + single output module (library/source file). + */ + SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM = 1 << 8, + + /* When set, will dump out the IR between intermediate compilation steps.*/ + SLANG_TARGET_FLAG_DUMP_IR = 1 << 9, + + /* When set, will generate SPIRV directly rather than via glslang. */ + // This flag will be deprecated, use CompilerOption instead. + SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY = 1 << 10, + }; + inline constexpr SlangTargetFlags kDefaultTargetFlags = + SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; + + /*! + @brief Options to control floating-point precision guarantees for a target. + */ + typedef unsigned int SlangFloatingPointModeIntegral; + enum SlangFloatingPointMode : SlangFloatingPointModeIntegral + { + SLANG_FLOATING_POINT_MODE_DEFAULT = 0, + SLANG_FLOATING_POINT_MODE_FAST, + SLANG_FLOATING_POINT_MODE_PRECISE, + }; + + /*! + @brief Options to control floating-point denormal handling mode for a target. + */ + typedef unsigned int SlangFpDenormalModeIntegral; + enum SlangFpDenormalMode : SlangFpDenormalModeIntegral + { + SLANG_FP_DENORM_MODE_ANY = 0, + SLANG_FP_DENORM_MODE_PRESERVE, + SLANG_FP_DENORM_MODE_FTZ, + }; + + /*! + @brief Options to control emission of `#line` directives + */ + 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) */ + }; + + typedef int SlangSourceLanguageIntegral; + enum SlangSourceLanguage : SlangSourceLanguageIntegral + { + SLANG_SOURCE_LANGUAGE_UNKNOWN, + SLANG_SOURCE_LANGUAGE_SLANG, + SLANG_SOURCE_LANGUAGE_HLSL, + SLANG_SOURCE_LANGUAGE_GLSL, + SLANG_SOURCE_LANGUAGE_C, + SLANG_SOURCE_LANGUAGE_CPP, + SLANG_SOURCE_LANGUAGE_CUDA, + SLANG_SOURCE_LANGUAGE_SPIRV, + SLANG_SOURCE_LANGUAGE_METAL, + SLANG_SOURCE_LANGUAGE_WGSL, + SLANG_SOURCE_LANGUAGE_LLVM, + SLANG_SOURCE_LANGUAGE_COUNT_OF, + }; + + typedef unsigned int SlangProfileIDIntegral; + enum SlangProfileID : SlangProfileIDIntegral + { + SLANG_PROFILE_UNKNOWN, + }; + + + typedef SlangInt32 SlangCapabilityIDIntegral; + enum SlangCapabilityID : SlangCapabilityIDIntegral + { + SLANG_CAPABILITY_UNKNOWN = 0, + }; + + typedef unsigned int SlangMatrixLayoutModeIntegral; + enum SlangMatrixLayoutMode : SlangMatrixLayoutModeIntegral + { + SLANG_MATRIX_LAYOUT_MODE_UNKNOWN = 0, + SLANG_MATRIX_LAYOUT_ROW_MAJOR, + SLANG_MATRIX_LAYOUT_COLUMN_MAJOR, + }; + + typedef SlangUInt32 SlangStageIntegral; + enum SlangStage : SlangStageIntegral + { + SLANG_STAGE_NONE, + SLANG_STAGE_VERTEX, + SLANG_STAGE_HULL, + SLANG_STAGE_DOMAIN, + SLANG_STAGE_GEOMETRY, + SLANG_STAGE_FRAGMENT, + SLANG_STAGE_COMPUTE, + SLANG_STAGE_RAY_GENERATION, + SLANG_STAGE_INTERSECTION, + SLANG_STAGE_ANY_HIT, + SLANG_STAGE_CLOSEST_HIT, + SLANG_STAGE_MISS, + SLANG_STAGE_CALLABLE, + SLANG_STAGE_MESH, + SLANG_STAGE_AMPLIFICATION, + SLANG_STAGE_DISPATCH, + // + SLANG_STAGE_COUNT, + + // alias: + SLANG_STAGE_PIXEL = SLANG_STAGE_FRAGMENT, + }; + + 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 trackers. */ + 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 information 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 information + ///< 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, + }; + + 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 */ + }; + + enum SlangEmitSpirvMethod + { + SLANG_EMIT_SPIRV_DEFAULT = 0, + SLANG_EMIT_SPIRV_VIA_GLSL, + SLANG_EMIT_SPIRV_DIRECTLY, + }; + + enum SlangEmitCPUMethod + { + SLANG_EMIT_CPU_DEFAULT = 0, + SLANG_EMIT_CPU_VIA_CPP, + SLANG_EMIT_CPU_VIA_LLVM, + }; + + enum SlangDiagnosticColor + { + SLANG_DIAGNOSTIC_COLOR_AUTO = 0, // Use color if output sink is a tty + SLANG_DIAGNOSTIC_COLOR_ALWAYS, // Always use color + SLANG_DIAGNOSTIC_COLOR_NEVER, // Never use color + }; + + // 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 (will be deprecated) + EmitSpirvDirectly, // bool (will be deprecated) + 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, + REMOVED_SerialIR, // deprecated and removed + SkipCodeGen, // bool + ValidateIr, // bool + VerbosePaths, + VerifyDebugSerialIr, + NoCodeGen, // Not used. + + // Experimental + + FileSystem, + Heterogeneous, + NoMangle, + NoHLSLBinding, + NoHLSLPackConstantBufferElements, + ValidateUniformity, + AllowGLSL, + EnableExperimentalPasses, + BindlessSpaceIndex, // int + + // Internal + + ArchiveType, + CompileCoreModule, + Doc, + + IrCompression, //< deprecated + + LoadCoreModule, + ReferenceModule, + SaveCoreModule, + SaveCoreModuleBinSource, + TrackLiveness, + LoopInversion, // bool, enable loop inversion optimization + + ParameterBlocksUseRegisterSpaces, // Deprecated + LanguageVersion, // intValue0: SlangLanguageVersion + TypeConformance, // stringValue0: additional type conformance to link, in the format of + // ":[=]", for example + // "Impl:IFoo=3" or "Impl:IFoo". + EnableExperimentalDynamicDispatch, // bool, experimental + EmitReflectionJSON, // bool + + 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 + + // Add this new option to the end of the list to avoid breaking ABI as much as possible. + // Setting of EmitSpirvDirectly or EmitSpirvViaGLSL will turn into this option internally. + EmitSpirvMethod, // enum SlangEmitSpirvMethod + + SaveGLSLModuleBinSource, + + SkipDownstreamLinking, // bool, experimental + DumpModule, + + GetModuleInfo, // Print serialized module version and name + GetSupportedModuleVersions, // Print the min and max module versions this compiler supports + + EmitSeparateDebug, // bool + + // Floating point denormal handling modes + DenormalModeFp16, + DenormalModeFp32, + DenormalModeFp64, + + // Bitfield options + UseMSVCStyleBitfieldPacking, // bool + + ForceCLayout, // bool + + ExperimentalFeature, // bool, enable experimental features + + ReportDetailedPerfBenchmark, // bool, reports detailed compiler performance benchmark + // results + ValidateIRDetailed, // bool, enable detailed IR validation + DumpIRBefore, // string, pass name to dump IR before + DumpIRAfter, // string, pass name to dump IR after + + EmitCPUMethod, // enum SlangEmitCPUMethod + EmitCPUViaCPP, // bool + EmitCPUViaLLVM, // bool + LLVMTargetTriple, // string + LLVMCPU, // string + LLVMFeatures, // string + + EnableRichDiagnostics, // bool, enable the experimental rich diagnostics + + ReportDynamicDispatchSites, // bool + + EnableMachineReadableDiagnostics, // bool, enable machine-readable diagnostic output + // (implies EnableRichDiagnostics) + + DiagnosticColor, // intValue0: SlangDiagnosticColor (always, never, auto) + + CountOf, + }; + + 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 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. + + 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. + + SlangResult is designed to be compatible with COM HRESULT. + + It's layout in bits is as follows + + Severity | Facility | Code + ---------|----------|----- + 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. + + Result codes have the following styles, + 1) SLANG_name + 2) SLANG_s_f_name + 3) SLANG_s_name + + where s is S for success, E for error + f is the short version of the facility name + + 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 + */ + + 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. +#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. +#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)) + //! Get the result code for the facility +#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))) + + /*************************** 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 + + /// Base for external facilities. Facilities should be unique across modules. +#define SLANG_FACILITY_EXTERNAL_BASE 0x210 + + /* ************************ 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) + +#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) + //! Interface not be found +#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) + + //! 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) + //! 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) + //! Operation could not complete - ran out of memory +#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) + + // Supplied buffer is too small to be able to complete +#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) + //! Indicates a file/resource could not be opened +#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) + //! 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) + + /** A "Universally Unique Identifier" (UUID) + + The Slang API uses UUIDs to identify interfaces when + using `queryInterface`. + + This type is compatible with the `GUID` type defined + by the Component Object Model (COM), but Slang is + not dependent on COM. + */ + struct SlangUUID + { + uint32_t data1; + uint16_t data2; + uint16_t data3; + 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. +#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}; \ + } + +// 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}; \ + } + +// 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? +// +// 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)) + + + /** Base interface for components exchanged through the API. + + This interface definition is compatible with the COM `IUnknown`, + and uses the same UUID, but Slang does not require applications + to use or initialize COM. + */ + struct ISlangUnknown + { + 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 uint32_t SLANG_MCALL addRef() = 0; + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0; + + /* + 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); + } + uint32_t AddRef() { return addRef(); } + uint32_t Release() { return release(); } + }; +#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. + 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_NO_THROW virtual void* SLANG_MCALL clone(const SlangUUID& guid) = 0; + }; + + /** A "blob" of binary data. + + This interface definition is compatible with the `ID3DBlob` and `ID3D10Blob` interfaces. + */ + struct ISlangBlob : public ISlangUnknown + { + 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() + + /* 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}); + operator const char*() const { return chars; } + char chars[1]; + }; + + /** A (real or virtual) file system. + + Slang can make use of this interface whenever it would otherwise try to load files + 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 + longer used (using 'release'). + */ + + struct ISlangFileSystem : public ISlangCastable + { + 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. + @param outBlob A destination pointer to receive the blob of the file contents. + @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. + + 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; + }; +#define SLANG_UUID_ISlangFileSystem ISlangFileSystem::getTypeGuid() + + + typedef void (*SlangFuncPtr)(void); + + /** + (DEPRECATED) ISlangSharedLibrary + */ + struct ISlangSharedLibrary_Dep1 : public ISlangUnknown + { + 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() + + /** 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}) + + /** 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); + } + + /** Get a symbol by name. If the library is unloaded will only return nullptr. + @param name The name of the symbol + @return The pointer related to the name or nullptr if not found + */ + virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) = 0; + }; +#define SLANG_UUID_ISlangSharedLibrary ISlangSharedLibrary::getTypeGuid() + + 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; + }; +#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. */ + }; + + /* 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); + + /* 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 + }; + + /* 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. + 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 + Display, + + /// 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'. + + 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}) + + /** 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. + + 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. + + @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; + + /** 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 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. + @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. + @param path + @param pathTypeOut + @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; + + /** 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) + */ + 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. + + @param The path to enumerate + @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 + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents( + const char* path, + FileSystemContentsCallBack callback, + 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() + + struct ISlangMutableFileSystem : public ISlangFileSystemExt + { + 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) + */ + 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. + + 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) + */ + 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. + + @param path The path to remove + @returns SLANG_OK if successful + */ + 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 + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) = 0; + }; + +#define SLANG_UUID_ISlangMutableFileSystem ISlangMutableFileSystem::getTypeGuid() + + /* Identifies different types of writer target*/ + typedef unsigned int SlangWriterChannelIntegral; + enum SlangWriterChannel : SlangWriterChannelIntegral + { + SLANG_WRITER_CHANNEL_DIAGNOSTIC, + SLANG_WRITER_CHANNEL_STD_OUTPUT, + SLANG_WRITER_CHANNEL_STD_ERROR, + SLANG_WRITER_CHANNEL_COUNT_OF, + }; + + typedef unsigned int SlangWriterModeIntegral; + enum SlangWriterMode : SlangWriterModeIntegral + { + SLANG_WRITER_MODE_TEXT, + SLANG_WRITER_MODE_BINARY, + }; + + /** 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. */ + 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 */ + 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 */ + 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 */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL setMode(SlangWriterMode mode) = 0; + }; + +#define SLANG_UUID_ISlangWriter ISlangWriter::getTypeGuid() + + struct ISlangProfiler : public ISlangUnknown + { + 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() + + namespace slang + { + struct IGlobalSession; + struct ICompileRequest; + + } // namespace slang + + /*! + @brief An instance of the Slang library. + */ + typedef slang::IGlobalSession SlangSession; + + + typedef struct SlangProgramLayout SlangProgramLayout; + + /*! + @brief A request for one or more compilation actions to be performed. + */ + typedef struct slang::ICompileRequest SlangCompileRequest; + + + /*! +@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 + produced via `git describe --tags --match v*` for the project. If such a + version could not be determined at build time then the contents will be + 0.0.0-unknown. Any string can be set by passing + -DSLANG_VERSION_FULL=whatever during the cmake invocation. + + This function will return exactly the same result as the method + getBuildTagString on IGlobalSession. + + An advantage of using this function over the method is that doing so does + not require the creation of a session, which can be a fairly costly + operation. + + @return The build tag string + */ + SLANG_API const char* spGetBuildTagString(); + + /* + Forward declarations of types used in the reflection interface; + */ + + typedef struct SlangProgramLayout SlangProgramLayout; + 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 SlangReflectionUserAttribute SlangReflectionAttribute; + typedef struct SlangReflectionFunction SlangReflectionFunction; + typedef struct SlangReflectionGeneric SlangReflectionGeneric; + + union SlangReflectionGenericArg + { + SlangReflectionType* typeVal; + int64_t intVal; + bool boolVal; + }; + + enum SlangReflectionGenericArgType + { + SLANG_GENERIC_ARG_TYPE = 0, + SLANG_GENERIC_ARG_INT = 1, + SLANG_GENERIC_ARG_BOOL = 2 + }; + + /* + Type aliases to maintain backward compatibility. + */ + typedef SlangProgramLayout SlangReflection; + typedef SlangEntryPointLayout SlangReflectionEntryPoint; + + // type reflection + + typedef unsigned int SlangTypeKindIntegral; + enum SlangTypeKind : SlangTypeKindIntegral + { + SLANG_TYPE_KIND_NONE, + SLANG_TYPE_KIND_STRUCT, + SLANG_TYPE_KIND_ARRAY, + SLANG_TYPE_KIND_MATRIX, + SLANG_TYPE_KIND_VECTOR, + SLANG_TYPE_KIND_SCALAR, + SLANG_TYPE_KIND_CONSTANT_BUFFER, + SLANG_TYPE_KIND_RESOURCE, + SLANG_TYPE_KIND_SAMPLER_STATE, + SLANG_TYPE_KIND_TEXTURE_BUFFER, + SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER, + SLANG_TYPE_KIND_PARAMETER_BLOCK, + SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER, + SLANG_TYPE_KIND_INTERFACE, + SLANG_TYPE_KIND_OUTPUT_STREAM, + SLANG_TYPE_KIND_MESH_OUTPUT, + SLANG_TYPE_KIND_SPECIALIZED, + SLANG_TYPE_KIND_FEEDBACK, + SLANG_TYPE_KIND_POINTER, + SLANG_TYPE_KIND_DYNAMIC_RESOURCE, + SLANG_TYPE_KIND_ENUM, + SLANG_TYPE_KIND_COUNT, + }; + + typedef unsigned int SlangScalarTypeIntegral; + enum SlangScalarType : SlangScalarTypeIntegral + { + SLANG_SCALAR_TYPE_NONE, + SLANG_SCALAR_TYPE_VOID, + SLANG_SCALAR_TYPE_BOOL, + SLANG_SCALAR_TYPE_INT32, + SLANG_SCALAR_TYPE_UINT32, + SLANG_SCALAR_TYPE_INT64, + SLANG_SCALAR_TYPE_UINT64, + SLANG_SCALAR_TYPE_FLOAT16, + SLANG_SCALAR_TYPE_FLOAT32, + SLANG_SCALAR_TYPE_FLOAT64, + SLANG_SCALAR_TYPE_INT8, + SLANG_SCALAR_TYPE_UINT8, + SLANG_SCALAR_TYPE_INT16, + SLANG_SCALAR_TYPE_UINT16, + SLANG_SCALAR_TYPE_INTPTR, + SLANG_SCALAR_TYPE_UINTPTR + }; + + // abstract decl reflection + typedef unsigned int SlangDeclKindIntegral; + enum SlangDeclKind : SlangDeclKindIntegral + { + SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION, + SLANG_DECL_KIND_STRUCT, + SLANG_DECL_KIND_FUNC, + SLANG_DECL_KIND_MODULE, + SLANG_DECL_KIND_GENERIC, + SLANG_DECL_KIND_VARIABLE, + SLANG_DECL_KIND_NAMESPACE, + SLANG_DECL_KIND_ENUM, + }; + +#ifndef SLANG_RESOURCE_SHAPE + #define SLANG_RESOURCE_SHAPE + typedef unsigned int SlangResourceShapeIntegral; + enum SlangResourceShape : SlangResourceShapeIntegral + { + SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F, + + 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_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 = 0x1F0, + + SLANG_TEXTURE_FEEDBACK_FLAG = 0x10, + SLANG_TEXTURE_SHADOW_FLAG = 0x20, + SLANG_TEXTURE_ARRAY_FLAG = 0x40, + SLANG_TEXTURE_MULTISAMPLE_FLAG = 0x80, + SLANG_TEXTURE_COMBINED_FLAG = 0x100, + + 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, + }; +#endif + typedef unsigned int SlangResourceAccessIntegral; + enum SlangResourceAccess : SlangResourceAccessIntegral + { + SLANG_RESOURCE_ACCESS_NONE, + SLANG_RESOURCE_ACCESS_READ, + SLANG_RESOURCE_ACCESS_READ_WRITE, + SLANG_RESOURCE_ACCESS_RASTER_ORDERED, + SLANG_RESOURCE_ACCESS_APPEND, + SLANG_RESOURCE_ACCESS_CONSUME, + SLANG_RESOURCE_ACCESS_WRITE, + SLANG_RESOURCE_ACCESS_FEEDBACK, + SLANG_RESOURCE_ACCESS_UNKNOWN = 0x7FFFFFFF, + }; + + typedef unsigned int SlangParameterCategoryIntegral; + enum SlangParameterCategory : SlangParameterCategoryIntegral + { + SLANG_PARAMETER_CATEGORY_NONE, + SLANG_PARAMETER_CATEGORY_MIXED, + SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, + SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE, + SLANG_PARAMETER_CATEGORY_UNORDERED_ACCESS, + SLANG_PARAMETER_CATEGORY_VARYING_INPUT, + SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT, + SLANG_PARAMETER_CATEGORY_SAMPLER_STATE, + SLANG_PARAMETER_CATEGORY_UNIFORM, + SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT, + SLANG_PARAMETER_CATEGORY_SPECIALIZATION_CONSTANT, + SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER, + + // HLSL register `space`, Vulkan GLSL `set` + SLANG_PARAMETER_CATEGORY_REGISTER_SPACE, + + // TODO: Ellie, Both APIs treat mesh outputs as more or less varying output, + // Does it deserve to be represented here?? + + // A parameter whose type is to be specialized by a global generic type argument + SLANG_PARAMETER_CATEGORY_GENERIC, + + SLANG_PARAMETER_CATEGORY_RAY_PAYLOAD, + SLANG_PARAMETER_CATEGORY_HIT_ATTRIBUTES, + SLANG_PARAMETER_CATEGORY_CALLABLE_PAYLOAD, + SLANG_PARAMETER_CATEGORY_SHADER_RECORD, + + // An existential type parameter represents a "hole" that + // needs to be filled with a concrete type to enable + // generation of specialized code. + // + // Consider this example: + // + // struct MyParams + // { + // IMaterial material; + // ILight lights[3]; + // }; + // + // This `MyParams` type introduces two existential type parameters: + // one for `material` and one for `lights`. Even though `lights` + // is an array, it only introduces one type parameter, because + // we need to have a *single* concrete type for all the array + // elements to be able to generate specialized code. + // + SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM, + + // An existential object parameter represents a value + // that needs to be passed in to provide data for some + // interface-type shader parameter. + // + // Consider this example: + // + // struct MyParams + // { + // IMaterial material; + // ILight lights[3]; + // }; + // + // This `MyParams` type introduces four existential object parameters: + // one for `material` and three for `lights` (one for each array + // element). This is consistent with the number of interface-type + // "objects" that are being passed through to the shader. + // + SLANG_PARAMETER_CATEGORY_EXISTENTIAL_OBJECT_PARAM, + + // The register space offset for the sub-elements that occupies register spaces. + SLANG_PARAMETER_CATEGORY_SUB_ELEMENT_REGISTER_SPACE, + + // The input_attachment_index subpass occupancy tracker + SLANG_PARAMETER_CATEGORY_SUBPASS, + + // Metal tier-1 argument buffer element [[id]]. + SLANG_PARAMETER_CATEGORY_METAL_ARGUMENT_BUFFER_ELEMENT, + + // Metal [[attribute]] inputs. + SLANG_PARAMETER_CATEGORY_METAL_ATTRIBUTE, + + // Metal [[payload]] inputs + SLANG_PARAMETER_CATEGORY_METAL_PAYLOAD, + + // + SLANG_PARAMETER_CATEGORY_COUNT, + + // Aliases for Metal-specific categories. + SLANG_PARAMETER_CATEGORY_METAL_BUFFER = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, + SLANG_PARAMETER_CATEGORY_METAL_TEXTURE = SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE, + SLANG_PARAMETER_CATEGORY_METAL_SAMPLER = SLANG_PARAMETER_CATEGORY_SAMPLER_STATE, + + // DEPRECATED: + SLANG_PARAMETER_CATEGORY_VERTEX_INPUT = SLANG_PARAMETER_CATEGORY_VARYING_INPUT, + SLANG_PARAMETER_CATEGORY_FRAGMENT_OUTPUT = SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT, + SLANG_PARAMETER_CATEGORY_COUNT_V1 = SLANG_PARAMETER_CATEGORY_SUBPASS, + }; + + /** 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` + defined by the Vulkan API. Note however that the values of this enumeration + are not the same as those of any particular API. + + The `SlangBindingType` enumeration is distinct from `SlangParameterCategory` + because `SlangParameterCategory` differentiates the types of parameters for + the purposes of layout, where the layout rules of some targets will treat + parameters of different types as occupying the same binding space for layout + (e.g., in SPIR-V both a `Texture2D` and `SamplerState` use the same space of + `binding` indices, and are not allowed to overlap), while those same types + map to different types of bindings in the API (e.g., both textures and samplers + use different `VkDescriptorType` values). + + When you want to answer "what register/binding did this parameter use?" you + should use `SlangParameterCategory`. + + When you want to answer "what type of descriptor range should this parameter use?" + you should use `SlangBindingType`. + */ + typedef SlangUInt32 SlangBindingTypeIntegral; + enum SlangBindingType : SlangBindingTypeIntegral + { + SLANG_BINDING_TYPE_UNKNOWN = 0, + + SLANG_BINDING_TYPE_SAMPLER, + SLANG_BINDING_TYPE_TEXTURE, + SLANG_BINDING_TYPE_CONSTANT_BUFFER, + SLANG_BINDING_TYPE_PARAMETER_BLOCK, + SLANG_BINDING_TYPE_TYPED_BUFFER, + SLANG_BINDING_TYPE_RAW_BUFFER, + SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER, + SLANG_BINDING_TYPE_INPUT_RENDER_TARGET, + SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA, + SLANG_BINDING_TYPE_RAY_TRACING_ACCELERATION_STRUCTURE, + + SLANG_BINDING_TYPE_VARYING_INPUT, + SLANG_BINDING_TYPE_VARYING_OUTPUT, + + SLANG_BINDING_TYPE_EXISTENTIAL_VALUE, + SLANG_BINDING_TYPE_PUSH_CONSTANT, + + 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_BASE_MASK = 0x00FF, + SLANG_BINDING_TYPE_EXT_MASK = 0xFF00, + }; + + typedef SlangUInt32 SlangLayoutRulesIntegral; + enum SlangLayoutRules : SlangLayoutRulesIntegral + { + SLANG_LAYOUT_RULES_DEFAULT, + SLANG_LAYOUT_RULES_METAL_ARGUMENT_BUFFER_TIER_2, + SLANG_LAYOUT_RULES_DEFAULT_STRUCTURED_BUFFER, + SLANG_LAYOUT_RULES_DEFAULT_CONSTANT_BUFFER, + }; + + typedef SlangUInt32 SlangModifierIDIntegral; + enum SlangModifierID : SlangModifierIDIntegral + { + SLANG_MODIFIER_SHARED, + SLANG_MODIFIER_NO_DIFF, + SLANG_MODIFIER_STATIC, + SLANG_MODIFIER_CONST, + SLANG_MODIFIER_EXPORT, + SLANG_MODIFIER_EXTERN, + SLANG_MODIFIER_DIFFERENTIABLE, + SLANG_MODIFIER_MUTATING, + SLANG_MODIFIER_IN, + SLANG_MODIFIER_OUT, + SLANG_MODIFIER_INOUT + }; + + typedef SlangUInt32 SlangImageFormatIntegral; + enum SlangImageFormat : SlangImageFormatIntegral + { +#define SLANG_FORMAT(NAME, DESC) SLANG_IMAGE_FORMAT_##NAME, +#include "slang-image-format-defs.h" +#undef SLANG_FORMAT + }; + +#define SLANG_UNBOUNDED_SIZE (~size_t(0)) +#define SLANG_UNKNOWN_SIZE (SLANG_UNBOUNDED_SIZE - 1) + + // Shader Parameter Reflection + + typedef SlangReflectionVariableLayout SlangReflectionParameter; + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +namespace slang +{ +struct ISession; +} +#endif + +#include "slang-deprecated.h" + +#ifdef __cplusplus + +/* 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 Attribute +{ + char const* getName() + { + return spReflectionUserAttribute_GetName((SlangReflectionAttribute*)this); + } + uint32_t getArgumentCount() + { + return (uint32_t)spReflectionUserAttribute_GetArgumentCount( + (SlangReflectionAttribute*)this); + } + TypeReflection* getArgumentType(uint32_t index) + { + return (TypeReflection*)spReflectionUserAttribute_GetArgumentType( + (SlangReflectionAttribute*)this, + index); + } + SlangResult getArgumentValueInt(uint32_t index, int* value) + { + return spReflectionUserAttribute_GetArgumentValueInt( + (SlangReflectionAttribute*)this, + index, + value); + } + SlangResult getArgumentValueFloat(uint32_t index, float* value) + { + return spReflectionUserAttribute_GetArgumentValueFloat( + (SlangReflectionAttribute*)this, + index, + value); + } + const char* getArgumentValueString(uint32_t index, size_t* outSize) + { + return spReflectionUserAttribute_GetArgumentValueString( + (SlangReflectionAttribute*)this, + index, + outSize); + } +}; + +typedef Attribute UserAttribute; + +struct TypeReflection +{ + 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, + MeshOutput = SLANG_TYPE_KIND_MESH_OUTPUT, + Enum = SLANG_TYPE_KIND_ENUM, + }; + + 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); } + + // 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); + } + + bool isArray() { return getKind() == TypeReflection::Kind::Array; } + + TypeReflection* unwrapArray() + { + TypeReflection* type = this; + while (type->isArray()) + { + type = type->getElementType(); + } + return type; + } + + /** Get the number of elements in an array or vector type. + * + * Only useful if `getKind() == Kind::Array` or `Kind::Vector`. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded-size arrays. + * Returns `SLANG_UNKNOWN_SIZE` when size depends on unresolved generic parameters or link-time + * constants. The `reflection` parameter can help resolve link-time constants if available. + */ + size_t getElementCount(SlangReflection* reflection = nullptr) + { + return spReflectionType_GetSpecializedElementCount((SlangReflectionType*)this, reflection); + } + + /** Get the total number of elements in a multi-dimensional array type. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded-size arrays. + * Returns `SLANG_UNKNOWN_SIZE` when size depends on unresolved generic parameters or link-time + * constants. + */ + size_t getTotalArrayElementCount() + { + if (!isArray()) + return 0; + size_t result = 1; + TypeReflection* type = this; + for (;;) + { + if (!type->isArray()) + return result; + + const auto c = type->getElementCount(); + if (c == SLANG_UNKNOWN_SIZE) + return SLANG_UNKNOWN_SIZE; + if (c == SLANG_UNBOUNDED_SIZE) + return SLANG_UNBOUNDED_SIZE; + result *= c; + type = type->getElementType(); + } + } + + TypeReflection* getElementType() + { + return (TypeReflection*)spReflectionType_GetElementType((SlangReflectionType*)this); + } + + unsigned getRowCount() { return spReflectionType_GetRowCount((SlangReflectionType*)this); } + + unsigned getColumnCount() + { + return spReflectionType_GetColumnCount((SlangReflectionType*)this); + } + + ScalarType getScalarType() + { + return (ScalarType)spReflectionType_GetScalarType((SlangReflectionType*)this); + } + + TypeReflection* getResourceResultType() + { + return (TypeReflection*)spReflectionType_GetResourceResultType((SlangReflectionType*)this); + } + + SlangResourceShape getResourceShape() + { + return spReflectionType_GetResourceShape((SlangReflectionType*)this); + } + + SlangResourceAccess getResourceAccess() + { + return spReflectionType_GetResourceAccess((SlangReflectionType*)this); + } + + char const* getName() { return spReflectionType_GetName((SlangReflectionType*)this); } + + SlangResult getFullName(ISlangBlob** outNameBlob) + { + return spReflectionType_GetFullName((SlangReflectionType*)this, outNameBlob); + } + + unsigned int getUserAttributeCount() + { + return spReflectionType_GetUserAttributeCount((SlangReflectionType*)this); + } + + UserAttribute* getUserAttributeByIndex(unsigned int index) + { + return (UserAttribute*)spReflectionType_GetUserAttribute((SlangReflectionType*)this, index); + } + + UserAttribute* findAttributeByName(char const* name) + { + return (UserAttribute*)spReflectionType_FindUserAttributeByName( + (SlangReflectionType*)this, + name); + } + + UserAttribute* findUserAttributeByName(char const* name) { return findAttributeByName(name); } + + TypeReflection* applySpecializations(GenericReflection* generic) + { + return (TypeReflection*)spReflectionType_applySpecializations( + (SlangReflectionType*)this, + (SlangReflectionGeneric*)generic); + } + + 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 ShaderReflection; + +struct TypeLayoutReflection +{ + TypeReflection* getType() + { + return (TypeReflection*)spReflectionTypeLayout_GetType((SlangReflectionTypeLayout*)this); + } + + TypeReflection::Kind getKind() + { + return (TypeReflection::Kind)spReflectionTypeLayout_getKind( + (SlangReflectionTypeLayout*)this); + } + + /** Get the size of this type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources (e.g., unsized arrays). + * Returns `SLANG_UNKNOWN_SIZE` when the size depends on unresolved generic parameters or + * link-time constants. + */ + size_t getSize(SlangParameterCategory category) + { + return spReflectionTypeLayout_GetSize((SlangReflectionTypeLayout*)this, category); + } + + /** Get the stride of this type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when stride depends on unresolved generic parameters or + * link-time constants. + */ + size_t getStride(SlangParameterCategory category) + { + return spReflectionTypeLayout_GetStride((SlangReflectionTypeLayout*)this, category); + } + + int32_t getAlignment(SlangParameterCategory category) + { + return spReflectionTypeLayout_getAlignment((SlangReflectionTypeLayout*)this, category); + } + + /** Get the size of this type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources (e.g., unsized arrays). + * Returns `SLANG_UNKNOWN_SIZE` when the size depends on unresolved generic parameters or + * link-time constants. + */ + size_t getSize(slang::ParameterCategory category = slang::ParameterCategory::Uniform) + { + return spReflectionTypeLayout_GetSize( + (SlangReflectionTypeLayout*)this, + (SlangParameterCategory)category); + } + + /** Get the stride of this type layout in the specified parameter category. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when stride depends on unresolved generic parameters or + * link-time constants. + */ + size_t getStride(slang::ParameterCategory category = slang::ParameterCategory::Uniform) + { + return spReflectionTypeLayout_GetStride( + (SlangReflectionTypeLayout*)this, + (SlangParameterCategory)category); + } + + int32_t getAlignment(slang::ParameterCategory category = slang::ParameterCategory::Uniform) + { + return spReflectionTypeLayout_getAlignment( + (SlangReflectionTypeLayout*)this, + (SlangParameterCategory)category); + } + + + unsigned int getFieldCount() + { + return spReflectionTypeLayout_GetFieldCount((SlangReflectionTypeLayout*)this); + } + + VariableLayoutReflection* getFieldByIndex(unsigned int index) + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetFieldByIndex( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangInt findFieldIndexByName(char const* nameBegin, char const* nameEnd = nullptr) + { + return spReflectionTypeLayout_findFieldIndexByName( + (SlangReflectionTypeLayout*)this, + nameBegin, + nameEnd); + } + + VariableLayoutReflection* getExplicitCounter() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetExplicitCounter( + (SlangReflectionTypeLayout*)this); + } + + bool isArray() { return getType()->isArray(); } + + TypeLayoutReflection* unwrapArray() + { + TypeLayoutReflection* typeLayout = this; + while (typeLayout->isArray()) + { + typeLayout = typeLayout->getElementTypeLayout(); + } + return typeLayout; + } + + /** Get the number of elements in an array variable. + * + * Only useful if `getKind() == Kind::Array`. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded-size arrays. + * Returns `SLANG_UNKNOWN_SIZE` when size depends on unresolved generic parameters or link-time + * constants. + */ + size_t getElementCount(ShaderReflection* reflection = nullptr) + { + return getType()->getElementCount((SlangReflection*)reflection); + } + + /** Get the total number of elements in a multi-dimensional array variable. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded-size arrays. + * Returns `SLANG_UNKNOWN_SIZE` when size depends on unresolved generic parameters or link-time + * constants. + */ + size_t getTotalArrayElementCount() { return getType()->getTotalArrayElementCount(); } + + /** Get the stride between elements of an array type layout. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when element stride depends on unresolved generic parameters or + * link-time constants. + */ + size_t getElementStride(SlangParameterCategory category) + { + return spReflectionTypeLayout_GetElementStride((SlangReflectionTypeLayout*)this, category); + } + + TypeLayoutReflection* getElementTypeLayout() + { + return (TypeLayoutReflection*)spReflectionTypeLayout_GetElementTypeLayout( + (SlangReflectionTypeLayout*)this); + } + + VariableLayoutReflection* getElementVarLayout() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetElementVarLayout( + (SlangReflectionTypeLayout*)this); + } + + VariableLayoutReflection* getContainerVarLayout() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_getContainerVarLayout( + (SlangReflectionTypeLayout*)this); + } + + // How is this type supposed to be bound? + ParameterCategory getParameterCategory() + { + return (ParameterCategory)spReflectionTypeLayout_GetParameterCategory( + (SlangReflectionTypeLayout*)this); + } + + unsigned int getCategoryCount() + { + return spReflectionTypeLayout_GetCategoryCount((SlangReflectionTypeLayout*)this); + } + + ParameterCategory getCategoryByIndex(unsigned int index) + { + return (ParameterCategory)spReflectionTypeLayout_GetCategoryByIndex( + (SlangReflectionTypeLayout*)this, + index); + } + + unsigned getRowCount() { return getType()->getRowCount(); } + + unsigned getColumnCount() { return getType()->getColumnCount(); } + + TypeReflection::ScalarType getScalarType() { return getType()->getScalarType(); } + + TypeReflection* getResourceResultType() { return getType()->getResourceResultType(); } + + SlangResourceShape getResourceShape() { return getType()->getResourceShape(); } + + SlangResourceAccess getResourceAccess() { return getType()->getResourceAccess(); } + + char const* getName() { return getType()->getName(); } + + SlangMatrixLayoutMode getMatrixLayoutMode() + { + return spReflectionTypeLayout_GetMatrixLayoutMode((SlangReflectionTypeLayout*)this); + } + + int getGenericParamIndex() + { + return spReflectionTypeLayout_getGenericParamIndex((SlangReflectionTypeLayout*)this); + } + + // Pending Type Layout functionality has been removed + [[deprecated]] TypeLayoutReflection* getPendingDataTypeLayout() { return nullptr; } + + // Pending Type Layout functionality has been removed + [[deprecated]] VariableLayoutReflection* getSpecializedTypePendingDataVarLayout() + { + return nullptr; + } + + SlangInt getBindingRangeCount() + { + return spReflectionTypeLayout_getBindingRangeCount((SlangReflectionTypeLayout*)this); + } + + BindingType getBindingRangeType(SlangInt index) + { + return (BindingType)spReflectionTypeLayout_getBindingRangeType( + (SlangReflectionTypeLayout*)this, + index); + } + + bool isBindingRangeSpecializable(SlangInt index) + { + return (bool)spReflectionTypeLayout_isBindingRangeSpecializable( + (SlangReflectionTypeLayout*)this, + index); + } + + /** Get the binding count for a binding range at the specified index. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the count depends on unresolved generic parameters or + * link-time constants. + */ + SlangInt getBindingRangeBindingCount(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeBindingCount( + (SlangReflectionTypeLayout*)this, + index); + } + + /* + SlangInt getBindingRangeIndexOffset(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeIndexOffset( + (SlangReflectionTypeLayout*) this, + index); + } + + SlangInt getBindingRangeSpaceOffset(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeSpaceOffset( + (SlangReflectionTypeLayout*) this, + index); + } + */ + + SlangInt getFieldBindingRangeOffset(SlangInt fieldIndex) + { + return spReflectionTypeLayout_getFieldBindingRangeOffset( + (SlangReflectionTypeLayout*)this, + fieldIndex); + } + + SlangInt getExplicitCounterBindingRangeOffset() + { + return spReflectionTypeLayout_getExplicitCounterBindingRangeOffset( + (SlangReflectionTypeLayout*)this); + } + + TypeLayoutReflection* getBindingRangeLeafTypeLayout(SlangInt index) + { + return (TypeLayoutReflection*)spReflectionTypeLayout_getBindingRangeLeafTypeLayout( + (SlangReflectionTypeLayout*)this, + index); + } + + VariableReflection* getBindingRangeLeafVariable(SlangInt index) + { + return (VariableReflection*)spReflectionTypeLayout_getBindingRangeLeafVariable( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangImageFormat getBindingRangeImageFormat(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeImageFormat( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangInt getBindingRangeDescriptorSetIndex(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeDescriptorSetIndex( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangInt getBindingRangeFirstDescriptorRangeIndex(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangInt getBindingRangeDescriptorRangeCount(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeDescriptorRangeCount( + (SlangReflectionTypeLayout*)this, + index); + } + + SlangInt getDescriptorSetCount() + { + return spReflectionTypeLayout_getDescriptorSetCount((SlangReflectionTypeLayout*)this); + } + + SlangInt getDescriptorSetSpaceOffset(SlangInt setIndex) + { + return spReflectionTypeLayout_getDescriptorSetSpaceOffset( + (SlangReflectionTypeLayout*)this, + setIndex); + } + + SlangInt getDescriptorSetDescriptorRangeCount(SlangInt setIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount( + (SlangReflectionTypeLayout*)this, + setIndex); + } + + /** Get the index offset for a descriptor range within a descriptor set. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + SlangInt getDescriptorSetDescriptorRangeIndexOffset(SlangInt setIndex, SlangInt rangeIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } + + /** Get the descriptor count for a descriptor range within a descriptor set. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the count depends on unresolved generic parameters or + * link-time constants. + */ + SlangInt getDescriptorSetDescriptorRangeDescriptorCount(SlangInt setIndex, SlangInt rangeIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } + + BindingType getDescriptorSetDescriptorRangeType(SlangInt setIndex, SlangInt rangeIndex) + { + return (BindingType)spReflectionTypeLayout_getDescriptorSetDescriptorRangeType( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } + + ParameterCategory getDescriptorSetDescriptorRangeCategory( + SlangInt setIndex, + SlangInt rangeIndex) + { + return (ParameterCategory)spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } + + SlangInt getSubObjectRangeCount() + { + return spReflectionTypeLayout_getSubObjectRangeCount((SlangReflectionTypeLayout*)this); + } + + SlangInt getSubObjectRangeBindingRangeIndex(SlangInt subObjectRangeIndex) + { + return spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } + + /** Get the space offset for a sub-object range. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + SlangInt getSubObjectRangeSpaceOffset(SlangInt subObjectRangeIndex) + { + return spReflectionTypeLayout_getSubObjectRangeSpaceOffset( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } + + VariableLayoutReflection* getSubObjectRangeOffset(SlangInt subObjectRangeIndex) + { + return (VariableLayoutReflection*)spReflectionTypeLayout_getSubObjectRangeOffset( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } +}; + +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 + }; +}; + +struct VariableReflection +{ + char const* getName() { return spReflectionVariable_GetName((SlangReflectionVariable*)this); } + + TypeReflection* getType() + { + return (TypeReflection*)spReflectionVariable_GetType((SlangReflectionVariable*)this); + } + + Modifier* findModifier(Modifier::ID id) + { + return (Modifier*)spReflectionVariable_FindModifier( + (SlangReflectionVariable*)this, + (SlangModifierID)id); + } + + unsigned int getUserAttributeCount() + { + return spReflectionVariable_GetUserAttributeCount((SlangReflectionVariable*)this); + } + + Attribute* getUserAttributeByIndex(unsigned int index) + { + return (UserAttribute*)spReflectionVariable_GetUserAttribute( + (SlangReflectionVariable*)this, + index); + } + + Attribute* findAttributeByName(SlangSession* globalSession, char const* name) + { + return (UserAttribute*)spReflectionVariable_FindUserAttributeByName( + (SlangReflectionVariable*)this, + globalSession, + name); + } + + Attribute* findUserAttributeByName(SlangSession* globalSession, char const* name) + { + return findAttributeByName(globalSession, name); + } + + bool hasDefaultValue() + { + return spReflectionVariable_HasDefaultValue((SlangReflectionVariable*)this); + } + + SlangResult getDefaultValueInt(int64_t* value) + { + return spReflectionVariable_GetDefaultValueInt((SlangReflectionVariable*)this, value); + } + + SlangResult getDefaultValueFloat(float* value) + { + return spReflectionVariable_GetDefaultValueFloat((SlangReflectionVariable*)this, value); + } + + GenericReflection* getGenericContainer() + { + return (GenericReflection*)spReflectionVariable_GetGenericContainer( + (SlangReflectionVariable*)this); + } + + VariableReflection* applySpecializations(GenericReflection* generic) + { + return (VariableReflection*)spReflectionVariable_applySpecializations( + (SlangReflectionVariable*)this, + (SlangReflectionGeneric*)generic); + } +}; + +struct VariableLayoutReflection +{ + VariableReflection* getVariable() + { + return (VariableReflection*)spReflectionVariableLayout_GetVariable( + (SlangReflectionVariableLayout*)this); + } + + char const* getName() + { + if (auto var = getVariable()) + return var->getName(); + return nullptr; + } + + Modifier* findModifier(Modifier::ID id) { return getVariable()->findModifier(id); } + + TypeLayoutReflection* getTypeLayout() + { + return (TypeLayoutReflection*)spReflectionVariableLayout_GetTypeLayout( + (SlangReflectionVariableLayout*)this); + } + + ParameterCategory getCategory() { return getTypeLayout()->getParameterCategory(); } + + unsigned int getCategoryCount() { return getTypeLayout()->getCategoryCount(); } + + ParameterCategory getCategoryByIndex(unsigned int index) + { + return getTypeLayout()->getCategoryByIndex(index); + } + + + /** Get the offset of this variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + size_t getOffset(SlangParameterCategory category) + { + return spReflectionVariableLayout_GetOffset((SlangReflectionVariableLayout*)this, category); + } + + /** Get the offset of this variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the offset depends on unresolved generic parameters or + * link-time constants. + */ + size_t getOffset(slang::ParameterCategory category = slang::ParameterCategory::Uniform) + { + return spReflectionVariableLayout_GetOffset( + (SlangReflectionVariableLayout*)this, + (SlangParameterCategory)category); + } + + + TypeReflection* getType() { return getVariable()->getType(); } + + /** Get the binding index for this variable layout. + * + * Returns `SLANG_UNKNOWN_SIZE` when the index depends on unresolved generic parameters or + * link-time constants. + */ + unsigned getBindingIndex() + { + return spReflectionParameter_GetBindingIndex((SlangReflectionVariableLayout*)this); + } + + /** Get the binding space for this variable layout. + * + * Returns `SLANG_UNKNOWN_SIZE` when the space depends on unresolved generic parameters or + * link-time constants. + */ + unsigned getBindingSpace() + { + return spReflectionParameter_GetBindingSpace((SlangReflectionVariableLayout*)this); + } + + /** Get the register space/set of this variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the space depends on unresolved generic parameters or + * link-time constants. + */ + size_t getBindingSpace(SlangParameterCategory category) + { + return spReflectionVariableLayout_GetSpace((SlangReflectionVariableLayout*)this, category); + } + + /** Get the register space/set of this variable in the specified parameter category. + * + * Returns `SLANG_UNKNOWN_SIZE` when the space depends on unresolved generic parameters or + * link-time constants. + */ + size_t getBindingSpace(slang::ParameterCategory category) + { + return spReflectionVariableLayout_GetSpace( + (SlangReflectionVariableLayout*)this, + (SlangParameterCategory)category); + } + + SlangImageFormat getImageFormat() + { + return spReflectionVariableLayout_GetImageFormat((SlangReflectionVariableLayout*)this); + } + + char const* getSemanticName() + { + return spReflectionVariableLayout_GetSemanticName((SlangReflectionVariableLayout*)this); + } + + size_t getSemanticIndex() + { + return spReflectionVariableLayout_GetSemanticIndex((SlangReflectionVariableLayout*)this); + } + + SlangStage getStage() + { + return spReflectionVariableLayout_getStage((SlangReflectionVariableLayout*)this); + } + + // Pending Type Layout functionality has been removed + [[deprecated]] VariableLayoutReflection* getPendingDataLayout() { return nullptr; } +}; + +struct FunctionReflection +{ + char const* getName() { return spReflectionFunction_GetName((SlangReflectionFunction*)this); } + + TypeReflection* getReturnType() + { + return (TypeReflection*)spReflectionFunction_GetResultType((SlangReflectionFunction*)this); + } + + unsigned int getParameterCount() + { + return spReflectionFunction_GetParameterCount((SlangReflectionFunction*)this); + } + + VariableReflection* getParameterByIndex(unsigned int index) + { + return (VariableReflection*)spReflectionFunction_GetParameter( + (SlangReflectionFunction*)this, + index); + } + + unsigned int getUserAttributeCount() + { + return spReflectionFunction_GetUserAttributeCount((SlangReflectionFunction*)this); + } + Attribute* getUserAttributeByIndex(unsigned int index) + { + return ( + Attribute*)spReflectionFunction_GetUserAttribute((SlangReflectionFunction*)this, index); + } + Attribute* findAttributeByName(SlangSession* globalSession, char const* name) + { + return (Attribute*)spReflectionFunction_FindUserAttributeByName( + (SlangReflectionFunction*)this, + globalSession, + name); + } + Attribute* findUserAttributeByName(SlangSession* globalSession, char const* name) + { + return findAttributeByName(globalSession, name); + } + Modifier* findModifier(Modifier::ID id) + { + return (Modifier*)spReflectionFunction_FindModifier( + (SlangReflectionFunction*)this, + (SlangModifierID)id); + } + + GenericReflection* getGenericContainer() + { + return (GenericReflection*)spReflectionFunction_GetGenericContainer( + (SlangReflectionFunction*)this); + } + + FunctionReflection* applySpecializations(GenericReflection* generic) + { + return (FunctionReflection*)spReflectionFunction_applySpecializations( + (SlangReflectionFunction*)this, + (SlangReflectionGeneric*)generic); + } + + FunctionReflection* specializeWithArgTypes(unsigned int argCount, TypeReflection* const* types) + { + return (FunctionReflection*)spReflectionFunction_specializeWithArgTypes( + (SlangReflectionFunction*)this, + argCount, + (SlangReflectionType* const*)types); + } + + bool isOverloaded() + { + return spReflectionFunction_isOverloaded((SlangReflectionFunction*)this); + } + + unsigned int getOverloadCount() + { + return spReflectionFunction_getOverloadCount((SlangReflectionFunction*)this); + } + + FunctionReflection* getOverload(unsigned int index) + { + return (FunctionReflection*)spReflectionFunction_getOverload( + (SlangReflectionFunction*)this, + index); + } +}; + +struct GenericReflection +{ + + DeclReflection* asDecl() + { + return (DeclReflection*)spReflectionGeneric_asDecl((SlangReflectionGeneric*)this); + } + + char const* getName() { return spReflectionGeneric_GetName((SlangReflectionGeneric*)this); } + + unsigned int getTypeParameterCount() + { + return spReflectionGeneric_GetTypeParameterCount((SlangReflectionGeneric*)this); + } + + VariableReflection* getTypeParameter(unsigned index) + { + return (VariableReflection*)spReflectionGeneric_GetTypeParameter( + (SlangReflectionGeneric*)this, + index); + } + + unsigned int getValueParameterCount() + { + return spReflectionGeneric_GetValueParameterCount((SlangReflectionGeneric*)this); + } + + VariableReflection* getValueParameter(unsigned index) + { + return (VariableReflection*)spReflectionGeneric_GetValueParameter( + (SlangReflectionGeneric*)this, + index); + } + + unsigned int getTypeParameterConstraintCount(VariableReflection* typeParam) + { + return spReflectionGeneric_GetTypeParameterConstraintCount( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam); + } + + TypeReflection* getTypeParameterConstraintType(VariableReflection* typeParam, unsigned index) + { + return (TypeReflection*)spReflectionGeneric_GetTypeParameterConstraintType( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam, + index); + } + + DeclReflection* getInnerDecl() + { + return (DeclReflection*)spReflectionGeneric_GetInnerDecl((SlangReflectionGeneric*)this); + } + + SlangDeclKind getInnerKind() + { + return spReflectionGeneric_GetInnerKind((SlangReflectionGeneric*)this); + } + + GenericReflection* getOuterGenericContainer() + { + return (GenericReflection*)spReflectionGeneric_GetOuterGenericContainer( + (SlangReflectionGeneric*)this); + } + + TypeReflection* getConcreteType(VariableReflection* typeParam) + { + return (TypeReflection*)spReflectionGeneric_GetConcreteType( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam); + } + + int64_t getConcreteIntVal(VariableReflection* valueParam) + { + return spReflectionGeneric_GetConcreteIntVal( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)valueParam); + } + + GenericReflection* applySpecializations(GenericReflection* generic) + { + return (GenericReflection*)spReflectionGeneric_applySpecializations( + (SlangReflectionGeneric*)this, + (SlangReflectionGeneric*)generic); + } +}; + +struct EntryPointReflection +{ + char const* getName() + { + return spReflectionEntryPoint_getName((SlangReflectionEntryPoint*)this); + } + + char const* getNameOverride() + { + return spReflectionEntryPoint_getNameOverride((SlangReflectionEntryPoint*)this); + } + + unsigned getParameterCount() + { + return spReflectionEntryPoint_getParameterCount((SlangReflectionEntryPoint*)this); + } + + FunctionReflection* getFunction() + { + return (FunctionReflection*)spReflectionEntryPoint_getFunction( + (SlangReflectionEntryPoint*)this); + } + + VariableLayoutReflection* getParameterByIndex(unsigned index) + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getParameterByIndex( + (SlangReflectionEntryPoint*)this, + index); + } + + SlangStage getStage() + { + return spReflectionEntryPoint_getStage((SlangReflectionEntryPoint*)this); + } + + void getComputeThreadGroupSize(SlangUInt axisCount, SlangUInt* outSizeAlongAxis) + { + return spReflectionEntryPoint_getComputeThreadGroupSize( + (SlangReflectionEntryPoint*)this, + axisCount, + outSizeAlongAxis); + } + + void getComputeWaveSize(SlangUInt* outWaveSize) + { + return spReflectionEntryPoint_getComputeWaveSize( + (SlangReflectionEntryPoint*)this, + outWaveSize); + } + + bool usesAnySampleRateInput() + { + return 0 != spReflectionEntryPoint_usesAnySampleRateInput((SlangReflectionEntryPoint*)this); + } + + VariableLayoutReflection* getVarLayout() + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getVarLayout( + (SlangReflectionEntryPoint*)this); + } + + TypeLayoutReflection* getTypeLayout() { return getVarLayout()->getTypeLayout(); } + + VariableLayoutReflection* getResultVarLayout() + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getResultVarLayout( + (SlangReflectionEntryPoint*)this); + } + + bool hasDefaultConstantBuffer() + { + return spReflectionEntryPoint_hasDefaultConstantBuffer((SlangReflectionEntryPoint*)this) != + 0; + } +}; + +typedef EntryPointReflection EntryPointLayout; + +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, + DefaultStructuredBuffer = SLANG_LAYOUT_RULES_DEFAULT_STRUCTURED_BUFFER, + DefaultConstantBuffer = SLANG_LAYOUT_RULES_DEFAULT_CONSTANT_BUFFER, +}; + +typedef struct ShaderReflection ProgramLayout; +typedef enum SlangReflectionGenericArgType GenericArgType; + +struct ShaderReflection +{ + unsigned getParameterCount() { return spReflection_GetParameterCount((SlangReflection*)this); } + + unsigned getTypeParameterCount() + { + return spReflection_GetTypeParameterCount((SlangReflection*)this); + } + + slang::ISession* getSession() { return spReflection_GetSession((SlangReflection*)this); } + + TypeParameterReflection* getTypeParameterByIndex(unsigned index) + { + return (TypeParameterReflection*)spReflection_GetTypeParameterByIndex( + (SlangReflection*)this, + index); + } + + TypeParameterReflection* findTypeParameter(char const* name) + { + return ( + TypeParameterReflection*)spReflection_FindTypeParameter((SlangReflection*)this, name); + } + + VariableLayoutReflection* getParameterByIndex(unsigned index) + { + return (VariableLayoutReflection*)spReflection_GetParameterByIndex( + (SlangReflection*)this, + index); + } + + static ProgramLayout* get(SlangCompileRequest* request) + { + return (ProgramLayout*)spGetReflection(request); + } + + SlangUInt getEntryPointCount() + { + return spReflection_getEntryPointCount((SlangReflection*)this); + } + + EntryPointReflection* getEntryPointByIndex(SlangUInt index) + { + return ( + EntryPointReflection*)spReflection_getEntryPointByIndex((SlangReflection*)this, index); + } + + /** Get the binding index for the global constant buffer. + * + * Returns `SLANG_UNKNOWN_SIZE` when the binding depends on unresolved generic parameters or + * link-time constants. + */ + SlangUInt getGlobalConstantBufferBinding() + { + return spReflection_getGlobalConstantBufferBinding((SlangReflection*)this); + } + + /** Get the size of the global constant buffer. + * + * Returns `SLANG_UNBOUNDED_SIZE` for unbounded resources. + * Returns `SLANG_UNKNOWN_SIZE` when the size depends on unresolved generic parameters or + * link-time constants. + */ + 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); + } + + SLANG_DEPRECATED FunctionReflection* tryResolveOverloadedFunction( + uint32_t candidateCount, + FunctionReflection** candidates) + { + return (FunctionReflection*)spReflection_TryResolveOverloadedFunction( + (SlangReflection*)this, + candidateCount, + (SlangReflectionFunction**)candidates); + } + + 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); + } + + SlangResult toJson(ISlangBlob** outBlob) + { + return spReflection_ToJson((SlangReflection*)this, nullptr, outBlob); + } + + /** Get the descriptor set/space index allocated for the bindless resource heap. + * Returns -1 if the program does not use bindless resource heap. + */ + SlangInt getBindlessSpaceIndex() + { + return spReflection_getBindlessSpaceIndex((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, + Enum = SLANG_DECL_KIND_ENUM, + }; + + 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); + } + + FunctionReflection* asFunction() + { + return (FunctionReflection*)spReflectionDecl_castToFunction((SlangReflectionDecl*)this); + } + + GenericReflection* asGeneric() + { + return (GenericReflection*)spReflectionDecl_castToGeneric((SlangReflectionDecl*)this); + } + + DeclReflection* getParent() + { + return (DeclReflection*)spReflectionDecl_getParent((SlangReflectionDecl*)this); + } + + Modifier* findModifier(Modifier::ID id) + { + return (Modifier*)spReflectionDecl_findModifier( + (SlangReflectionDecl*)this, + (SlangModifierID)id); + } + + template + struct FilteredList + { + unsigned int count; + DeclReflection* parent; + + struct FilteredIterator + { + DeclReflection* parent; + unsigned int count; + unsigned int index; + + 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}; + } + + FilteredIterator end() { return FilteredIterator{parent, count, count}; } + }; + + template + FilteredList getChildrenOfKind() + { + return FilteredList{getChildrenCount(), (DeclReflection*)this}; + } + + struct IteratedList + { + unsigned int count; + DeclReflection* parent; + + 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}; } + }; + + IteratedList getChildren() { return IteratedList{getChildrenCount(), (DeclReflection*)this}; } +}; + +typedef uint32_t CompileCoreModuleFlags; +struct CompileCoreModuleFlag +{ + enum Enum : CompileCoreModuleFlags + { + WriteDocumentation = 0x1, + }; +}; + +typedef ISlangBlob IBlob; + +struct IComponentType; +struct ITypeConformance; +struct IGlobalSession; +struct IModule; + +struct SessionDesc; +struct SpecializationArg; +struct TargetDesc; + +enum class BuiltinModuleName +{ + Core, + GLSL +}; + +/** A global session for interaction with the Slang library. + +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). + +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 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 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 Auxiliary memory allocated to hold data used in the session 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; + + /** Compile from (embedded source) the builtin module on the session. + Will return a failure if there is already a builtin module available. + NOTE! API is experimental and not ready for production code. + @param module The builtin module name. + @param flags to control compilation + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compileBuiltinModule(BuiltinModuleName module, CompileCoreModuleFlags flags) = 0; + + /** Load a builtin module. Currently loads modules from the file system. + @param module The builtin module name + @param moduleData Start address of the serialized core module + @param sizeInBytes The size in bytes of the serialized builtin module + + NOTE! API is experimental and not ready for production code + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadBuiltinModule(BuiltinModuleName module, const void* moduleData, size_t sizeInBytes) = 0; + + /** Save the builtin module to the file system + @param module The builtin module name + @param archiveType The type of archive used to hold the builtin module + @param outBlob The serialized blob containing the builtin module + + NOTE! API is experimental and not ready for production code */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveBuiltinModule( + BuiltinModuleName module, + SlangArchiveType archiveType, + ISlangBlob** outBlob) = 0; +}; + + #define SLANG_UUID_IGlobalSession IGlobalSession::getTypeGuid() + +/** Description of a code generation target. + */ +struct TargetDesc +{ + /** The size of this structure, in bytes. + */ + size_t structureSize = sizeof(TargetDesc); + + /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.) + */ + SlangCompileTarget format = SLANG_TARGET_UNKNOWN; + + /** The compilation profile supported by the target (e.g., "Shader Model 5.1") + */ + SlangProfileID profile = SLANG_PROFILE_UNKNOWN; + + /** Flags for the code generation target. Currently unused. */ + SlangTargetFlags flags = kDefaultTargetFlags; + + /** Default mode to use for floating-point operations on the target. + */ + SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT; + + /** The line directive mode for output source code. + */ + SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; + + /** Whether to force `scalar` layout for glsl shader storage buffers. + */ + bool forceGLSLScalarBufferLayout = false; + + /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. + */ + const CompilerOptionEntry* compilerOptionEntries = nullptr; + + /** Number of additional compiler option entries. + */ + uint32_t compilerOptionEntryCount = 0; +}; + +typedef uint32_t SessionFlags; +enum +{ + kSessionFlags_None = 0 +}; + +struct PreprocessorMacroDesc +{ + const char* name; + const char* value; +}; + +struct SessionDesc +{ + /** The size of this structure, in bytes. + */ + size_t structureSize = sizeof(SessionDesc); + + /** Code generation targets to include in the session. + */ + TargetDesc const* targets = nullptr; + SlangInt targetCount = 0; + + /** Flags to configure the session. + */ + SessionFlags flags = kSessionFlags_None; + + /** Default layout to assume for variables with matrix types. + */ + SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + /** 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; + + ISlangFileSystem* fileSystem = nullptr; + + bool enableEffectAnnotations = false; + bool allowGLSLSyntax = false; + + /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. + */ + CompilerOptionEntry* compilerOptionEntries = nullptr; + + /** Number of additional compiler option entries. + */ + uint32_t compilerOptionEntryCount = 0; + + /** Whether to skip SPIRV validation. + */ + bool skipSPIRVValidation = false; +}; + +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` declarations, 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 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. + The sequential ID is part of the RTTI bytes returned by `getDynamicObjectRTTIBytes`. + */ + 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 explicitly 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; + + + /** Get the 16-byte RTTI header to fill into a dynamic object. + This header is used to identify the type of the object for dynamic dispatch purpose. + For example, given the following shader: + + ```slang + [anyValueSize(32)] dyn interface IFoo { int eval(); } + struct Impl : IFoo { int eval() { return 1; } } + + ConstantBuffer cb0; + + [numthreads(1,1,1) + void main() + { + cb0.eval(); + } + ``` + + The constant buffer `cb0` should be filled with 16+32=48 bytes of data, where the first + 16 bytes should be the RTTI bytes returned by calling `getDynamicObjectRTTIBytes(type_Impl, + type_IFoo)`, and the rest 32 bytes should hold the actual data of the dynamic object (in + this case, fields in the `Impl` type). + + `bufferSizeInBytes` must be greater than 16. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getDynamicObjectRTTIBytes( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + uint32_t* outRTTIDataBuffer, + uint32_t bufferSizeInBytes) = 0; + + /** Read module info (name and version) from a module blob + * + * The returned pointers are valid for as long as the session. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadModuleInfoFromIRBlob( + slang::IBlob* source, + SlangInt& outModuleVersion, + const char*& outModuleCompilerVersion, + const char*& outModuleName) = 0; +}; + + #define SLANG_UUID_ISession ISession::getTypeGuid() + +struct IMetadata : public ISlangCastable +{ + SLANG_COM_INTERFACE(0x8044a8a3, 0xddc0, 0x4b7f, {0xaf, 0x8e, 0x2, 0x6e, 0x90, 0x5d, 0x73, 0x32}) + + /* + Returns whether a resource parameter at the specified 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; + + /* + Returns the debug build identifier for a base and debug spirv pair. + */ + virtual const char* SLANG_MCALL getDebugBuildIdentifier() = 0; +}; + #define SLANG_UUID_IMetadata IMetadata::getTypeGuid() + +/** Compile result for storing and retrieving multiple output blobs. + This is needed for features such as separate debug compilation which + output both base and debug spirv. + */ +struct ICompileResult : public ISlangCastable +{ + SLANG_COM_INTERFACE( + 0x5fa9380e, + 0xb62f, + 0x41e5, + {0x9f, 0x12, 0x4b, 0xad, 0x4d, 0x9e, 0xaa, 0xe4}) + + virtual uint32_t SLANG_MCALL getItemCount() = 0; + virtual SlangResult SLANG_MCALL getItemData(uint32_t index, IBlob** outblob) = 0; + virtual SlangResult SLANG_MCALL getMetadata(IMetadata** outMetadata) = 0; +}; + #define SLANG_UUID_ICompileResult ICompileResult::getTypeGuid() + +/** A component type is a unit of shader code layout, reflection, and linking. + +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: + +* Zero or more uniform shader parameters, representing textures, + buffers, etc. that the code in the component depends on. + +* 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. + +* Zero or more *requirements*, which are other component + types on which the component type depends. + +One example of a component type is a module of Slang code: + +* The global-scope shader parameters declared in the module are + the parameters when considered as a component type. + +* Any global-scope generic or interface type parameters introduce + specialization parameters for the module. + +* 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). + +* Any other modules that are `import`ed in the source code + become requirements of the module, when considered as a + component type. + +An entry point is another example of a component type: + +* The `uniform` parameters of the entry point function are + its shader parameters when considered as a component type. + +* Any generic or interface-type parameters of the entry point + introduce specialization parameters. + +* An entry point component type exposes a single entry point (itself). + +* An entry point has one requirement for the module in which + it was defined. + +Component types can be manipulated in a few ways: + +* Multiple component types can be combined into a composite, which + combines all of their code, parameters, etc. + +* A component type can be specialized, by "plugging in" types and + values for its specialization parameters. + +* A component type can be laid out for a particular target, giving + offsets/bindings to the shader parameters it contains. + +* Generated kernel code can be requested for entry points. + +*/ +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 available 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 unsatisfied 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 perform, 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; +}; + #define SLANG_UUID_IComponentType IComponentType::getTypeGuid() + +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; +}; + + #define SLANG_UUID_IEntryPoint IEntryPoint::getTypeGuid() + +struct ITypeConformance : public IComponentType +{ + SLANG_COM_INTERFACE(0x73eb3147, 0xe544, 0x41b5, {0xb8, 0xf0, 0xa2, 0x44, 0xdf, 0x21, 0x94, 0xb}) +}; + #define SLANG_UUID_ITypeConformance ITypeConformance::getTypeGuid() + +/** IComponentType2 is a component type used for getting separate debug data. + +This interface is used for getting separate debug data, introduced here to +avoid breaking backwards compatibility of the IComponentType interface. + +The `getTargetCompileResult` and `getEntryPointCompileResult` functions +are used to get the base and debug spirv, and metadata containing the +debug build identifier. +*/ +struct IComponentType2 : public ISlangUnknown +{ + SLANG_COM_INTERFACE( + 0x9c2a4b3d, + 0x7f68, + 0x4e91, + {0xa5, 0x2c, 0x8b, 0x19, 0x3e, 0x45, 0x7a, 0x9f}) + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCompileResult( + SlangInt targetIndex, + ICompileResult** outCompileResult, + IBlob** outDiagnostics = nullptr) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCompileResult( + SlangInt entryPointIndex, + SlangInt targetIndex, + ICompileResult** outCompileResult, + IBlob** outDiagnostics = nullptr) = 0; + /** Get 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 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, + slang::IBlob** outDiagnostics = 0) = 0; +}; + #define SLANG_UUID_IComponentType2 IComponentType2::getTypeGuid() + +/** 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. + +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}) + + /// Find and an entry point by name. + /// Note that this does not work in case the function is not explicitly designated as an entry + /// point, e.g. using a `[shader("...")]` attribute. In such cases, consider using + /// `IModule::findAndCheckEntryPoint` instead. + 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 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; + + /// 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 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; + + /// 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; + + virtual SLANG_NO_THROW DeclReflection* SLANG_MCALL getModuleReflection() = 0; + + /** Disassemble a module. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + disassemble(slang::IBlob** outDisassembledBlob) = 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}) + + 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 getModuleDependency( + SlangInt dependencyIndex, + IModule** outModule, + IBlob** outDiagnostics = nullptr) = 0; +}; + + #define SLANG_UUID_IModulePrecompileService_Experimental \ + IModulePrecompileService_Experimental::getTypeGuid() + +/** Argument used for specialization to types/values. + */ +struct SpecializationArg +{ + enum class Kind : int32_t + { + Unknown, /**< An invalid specialization argument. */ + Type, /**< Specialize to a type. */ + Expr, /**< An expression representing a type or value */ + }; + + /** The kind of specialization argument. */ + Kind kind; + union + { + /** A type specialization argument, used for `Kind::Type`. */ + TypeReflection* type; + /** An expression in Slang syntax, used for `Kind::Expr`. */ + const char* expr; + }; + + static SpecializationArg fromType(TypeReflection* inType) + { + SpecializationArg rs; + rs.kind = Kind::Type; + rs.type = inType; + return rs; + } + + static SpecializationArg fromExpr(const char* inExpr) + { + SpecializationArg rs; + rs.kind = Kind::Expr; + rs.expr = inExpr; + return rs; + } +}; +} // namespace slang + + // Passed into functions to create globalSession to identify the API version client code is + // using. + #define SLANG_API_VERSION 0 + +enum SlangLanguageVersion +{ + SLANG_LANGUAGE_VERSION_UNKNOWN = 0, + SLANG_LANGUAGE_VERSION_LEGACY = 2018, + SLANG_LANGUAGE_VERSION_2025 = 2025, + SLANG_LANGUAGE_VERSION_2026 = 2026, + SLANG_LANGAUGE_VERSION_DEFAULT = SLANG_LANGUAGE_VERSION_LEGACY, + SLANG_LANGUAGE_VERSION_LATEST = SLANG_LANGUAGE_VERSION_2026, +}; + + +/* Description of a Slang global session. + */ +struct SlangGlobalSessionDesc +{ + /// Size of this struct. + uint32_t structureSize = sizeof(SlangGlobalSessionDesc); + + /// Slang API version. + uint32_t apiVersion = SLANG_API_VERSION; + + /// Specify the oldest Slang language version that any sessions will use. + uint32_t minLanguageVersion = SLANG_LANGUAGE_VERSION_2025; + + /// Whether to enable GLSL support. + bool enableGLSL = false; + + /// Reserved for future use. + uint32_t reserved[16] = {}; +}; + +/* Create a blob from binary data. + * + * @param data Pointer to the binary data to store in the blob. Must not be null. + * @param size Size of the data in bytes. Must be greater than 0. + * @return The created blob on success, or nullptr on failure. + */ +SLANG_EXTERN_C SLANG_API ISlangBlob* slang_createBlob(const void* data, size_t size); + +/* Load a module from source code with size specification. + * + * @param session The session to load the module into. + * @param moduleName The name of the module. + * @param path The path for the module. + * @param source Pointer to the source code data. + * @param sourceSize Size of the source code data in bytes. + * @param outDiagnostics (out, optional) Diagnostics output. + * @return The loaded module on success, or nullptr on failure. + */ +SLANG_EXTERN_C SLANG_API slang::IModule* slang_loadModuleFromSource( + slang::ISession* session, + const char* moduleName, + const char* path, + const char* source, + size_t sourceSize, + ISlangBlob** outDiagnostics = nullptr); + +/** Load a module from IR data. + * @param session The session to load the module into. + * @param moduleName Name of the module to load. + * @param path Path for the module (used for diagnostics). + * @param source IR data containing the module. + * @param sourceSize Size of the IR data in bytes. + * @param outDiagnostics (out, optional) Diagnostics output. + * @return The loaded module on success, or nullptr on failure. + */ +SLANG_EXTERN_C SLANG_API slang::IModule* slang_loadModuleFromIRBlob( + slang::ISession* session, + const char* moduleName, + const char* path, + const void* source, + size_t sourceSize, + ISlangBlob** outDiagnostics = nullptr); + +/** Read module info (name and version) from IR data. + * @param session The session to use for loading module info. + * @param source IR data containing the module. + * @param sourceSize Size of the IR data in bytes. + * @param outModuleVersion (out) Module version number. + * @param outModuleCompilerVersion (out) Compiler version that created the module. + * @param outModuleName (out) Name of the module. + * @return SLANG_OK on success, or an error code on failure. + */ +SLANG_EXTERN_C SLANG_API SlangResult slang_loadModuleInfoFromIRBlob( + slang::ISession* session, + const void* source, + size_t sourceSize, + SlangInt& outModuleVersion, + const char*& outModuleCompilerVersion, + const char*& outModuleName); + +/* Create a global session, with the built-in core module. + +@param apiVersion Pass in SLANG_API_VERSION +@param outGlobalSession (out)The created global session. +*/ +SLANG_EXTERN_C SLANG_API SlangResult +slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession); + + +/* Create a global session, with the built-in core module. + +@param desc Description of the global session. +@param outGlobalSession (out)The created global session. +*/ +SLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSession2( + const SlangGlobalSessionDesc* desc, + 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 + +@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 +*/ +SLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSessionWithoutCoreModule( + SlangInt apiVersion, + slang::IGlobalSession** outGlobalSession); + +/* Returns a blob that contains the serialized core module. +Returns nullptr if there isn't an embedded core module. + +NOTE! API is experimental and not ready for production code +*/ +SLANG_API ISlangBlob* slang_getEmbeddedCoreModule(); + + +/* Cleanup all global allocations used by Slang, to prevent memory leak detectors from + reporting them as leaks. This function should only be called after all Slang objects + have been released. No other Slang functions such as `createGlobalSession` + should be called after this function. + */ +SLANG_EXTERN_C SLANG_API void slang_shutdown(); + +/* Return the last signaled internal error message. + */ +SLANG_EXTERN_C SLANG_API const char* slang_getLastInternalErrorMessage(); + +// Slang VM +namespace slang +{ + +enum class OperandDataType +{ + General = 0, // General data type, can be any type. + Int32 = 1, // 32-bit integer. + Int64 = 2, // 64-bit integer. + Float32 = 3, // 32-bit floating-point number. + Float64 = 4, // 64-bit floating-point number. + String = 5, // String data type, represented as a pointer to a null-terminated string. +}; + +struct VMExecOperand +{ + uint8_t** section; // Pointer to the section start pointer. + #if SLANG_PTR_IS_32 + uint32_t padding; + #endif + uint32_t type : 8; // type of the operand data. + uint32_t size : 24; + uint32_t offset; + void* getPtr() const { return *section + offset; } + OperandDataType getType() const { return (OperandDataType)type; } +}; + +struct VMExecInstHeader; +class IByteCodeRunner; + +typedef void (*VMExtFunction)(IByteCodeRunner* context, VMExecInstHeader* inst, void* userData); +typedef void (*VMPrintFunc)(const char* message, void* userData); + +struct VMExecInstHeader +{ + VMExtFunction functionPtr; // Pointer to the function that executes this instruction. + #if SLANG_PTR_IS_32 + uint32_t padding; + #endif + uint32_t opcodeExtension; + uint32_t operandCount; + VMExecInstHeader* getNextInst() + { + return (VMExecInstHeader*)((VMExecOperand*)(this + 1) + operandCount); + } + VMExecOperand& getOperand(SlangInt index) const + { + return *((VMExecOperand*)(this + 1) + index); + } +}; + +struct ByteCodeFuncInfo +{ + uint32_t parameterCount; + uint32_t returnValueSize; +}; + +struct ByteCodeRunnerDesc +{ + /** The size of this structure, in bytes. + */ + size_t structSize = sizeof(ByteCodeRunnerDesc); +}; + +/// Represents a byte code runner that can execute Slang byte code. +class IByteCodeRunner : public ISlangUnknown +{ +public: + // {AFDAB195-361F-42CB-9513-9006261DD8CD} + SLANG_COM_INTERFACE(0xafdab195, 0x361f, 0x42cb, {0x95, 0x13, 0x90, 0x6, 0x26, 0x1d, 0xd8, 0xcd}) + + /// Load a byte code module into the execution context. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadModule(IBlob* moduleBlob) = 0; + + /// Select a function for execution. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + selectFunctionByIndex(uint32_t functionIndex) = 0; + + virtual SLANG_NO_THROW int SLANG_MCALL findFunctionByName(const char* name) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getFunctionInfo(uint32_t index, ByteCodeFuncInfo* outInfo) = 0; + + /// Obtain the current working set memory for the selected function. + virtual SLANG_NO_THROW void* SLANG_MCALL getCurrentWorkingSet() = 0; + + /// Execute the selected function. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + execute(void* argumentData, size_t argumentSize) = 0; + + /// Query the error string. + virtual SLANG_NO_THROW void SLANG_MCALL getErrorString(IBlob** outBlob) = 0; + + /// Retrieve the return value of the last executed function. + virtual SLANG_NO_THROW void* SLANG_MCALL getReturnValue(size_t* outValueSize) = 0; + + /// Set the user data for the external instruction handler. + virtual SLANG_NO_THROW void SLANG_MCALL setExtInstHandlerUserData(void* userData) = 0; + + /// Register an external function that can be called from the byte code. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + registerExtCall(const char* name, VMExtFunction functionPtr) = 0; + + /// Set a callback function to print messages from the byte code runner. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + setPrintCallback(VMPrintFunc callback, void* userData) = 0; +}; + +} // namespace slang + +/// Create a byte code runner that can execute Slang byte code. +SLANG_EXTERN_C SLANG_API SlangResult slang_createByteCodeRunner( + const slang::ByteCodeRunnerDesc* desc, + slang::IByteCodeRunner** outByteCodeRunner); + +/// Disassemble a Slang byte code blob into human-readable text. +SLANG_EXTERN_C SLANG_API SlangResult +slang_disassembleByteCode(slang::IBlob* moduleBlob, slang::IBlob** outDisassemblyBlob); + +namespace slang +{ +inline SlangResult createGlobalSession(slang::IGlobalSession** outGlobalSession) +{ + SlangGlobalSessionDesc defaultDesc = {}; + return slang_createGlobalSession2(&defaultDesc, outGlobalSession); +} +inline SlangResult createGlobalSession( + const SlangGlobalSessionDesc* desc, + slang::IGlobalSession** outGlobalSession) +{ + return slang_createGlobalSession2(desc, outGlobalSession); +} +inline void shutdown() +{ + slang_shutdown(); +} +inline const char* getLastInternalErrorMessage() +{ + return slang_getLastInternalErrorMessage(); +} +} // namespace slang + +#endif // C++ helpers + +#define SLANG_ERROR_INSUFFICIENT_BUFFER SLANG_E_BUFFER_TOO_SMALL +#define SLANG_ERROR_INVALID_PARAMETER SLANG_E_INVALID_ARG + +#endif diff --git a/lib/All/slang/lib/cmake/slang/slangConfig.cmake b/lib/All/slang/lib/cmake/slang/slangConfig.cmake new file mode 100644 index 0000000..32a506f --- /dev/null +++ b/lib/All/slang/lib/cmake/slang/slangConfig.cmake @@ -0,0 +1,44 @@ + + +####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### +####### Any changes to this file will be overwritten by the next CMake run #### +####### The input file was SlangConfig.cmake.in ######## + +get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) + +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +#################################################################################### + +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + include("${CMAKE_CURRENT_LIST_DIR}/slangTargets.cmake") + check_required_components("slang") +endif() + +if(ON) + + find_program(SLANGC_EXECUTABLE "slangc" HINTS "${PACKAGE_PREFIX_DIR}/bin" ENV PATH) + + if (NOT SLANGC_EXECUTABLE) + message(STATUS "slangc executable not found; ensure it is available in your PATH.") + endif() + + set(SLANG_EXECUTABLE ${SLANGC_EXECUTABLE} CACHE STRING "Path to the slangc executable") + +endif() + diff --git a/lib/All/slang/lib/cmake/slang/slangConfigVersion.cmake b/lib/All/slang/lib/cmake/slang/slangConfigVersion.cmake new file mode 100644 index 0000000..451f181 --- /dev/null +++ b/lib/All/slang/lib/cmake/slang/slangConfigVersion.cmake @@ -0,0 +1,65 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "2026.3.1") + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("2026.3.1" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) + string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") + endif() + else() + set(CVF_VERSION_MAJOR "2026.3.1") + endif() + + if(PACKAGE_FIND_VERSION_RANGE) + # both endpoints of the range must have the expected major version + math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") + if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR + AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/lib/All/slang/lib/cmake/slang/slangTargets-release.cmake b/lib/All/slang/lib/cmake/slang/slangTargets-release.cmake new file mode 100644 index 0000000..d422cfd --- /dev/null +++ b/lib/All/slang/lib/cmake/slang/slangTargets-release.cmake @@ -0,0 +1,90 @@ +#---------------------------------------------------------------- +# Generated CMake target import file for configuration "Release". +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Import target "slang::slang-llvm" for configuration "Release" +set_property(TARGET slang::slang-llvm APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slang-llvm PROPERTIES + IMPORTED_COMMON_LANGUAGE_RUNTIME_RELEASE "" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libslang-llvm.so" + IMPORTED_NO_SONAME_RELEASE "TRUE" + ) + +list(APPEND _cmake_import_check_targets slang::slang-llvm ) +list(APPEND _cmake_import_check_files_for_slang::slang-llvm "${_IMPORT_PREFIX}/lib/libslang-llvm.so" ) + +# Import target "slang::slang-glslang" for configuration "Release" +set_property(TARGET slang::slang-glslang APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slang-glslang PROPERTIES + IMPORTED_COMMON_LANGUAGE_RUNTIME_RELEASE "" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libslang-glslang-2026.3.1.so" + IMPORTED_NO_SONAME_RELEASE "TRUE" + ) + +list(APPEND _cmake_import_check_targets slang::slang-glslang ) +list(APPEND _cmake_import_check_files_for_slang::slang-glslang "${_IMPORT_PREFIX}/lib/libslang-glslang-2026.3.1.so" ) + +# Import target "slang::slangd" for configuration "Release" +set_property(TARGET slang::slangd APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slangd PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/slangd" + ) + +list(APPEND _cmake_import_check_targets slang::slangd ) +list(APPEND _cmake_import_check_files_for_slang::slangd "${_IMPORT_PREFIX}/bin/slangd" ) + +# Import target "slang::slangi" for configuration "Release" +set_property(TARGET slang::slangi APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slangi PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/slangi" + ) + +list(APPEND _cmake_import_check_targets slang::slangi ) +list(APPEND _cmake_import_check_files_for_slang::slangi "${_IMPORT_PREFIX}/bin/slangi" ) + +# Import target "slang::gfx" for configuration "Release" +set_property(TARGET slang::gfx APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::gfx PROPERTIES + IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE "slang::slang" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libgfx.so.0.2026.3.1" + IMPORTED_SONAME_RELEASE "libgfx.so.0.2026.3.1" + ) + +list(APPEND _cmake_import_check_targets slang::gfx ) +list(APPEND _cmake_import_check_files_for_slang::gfx "${_IMPORT_PREFIX}/lib/libgfx.so.0.2026.3.1" ) + +# Import target "slang::slang-glsl-module" for configuration "Release" +set_property(TARGET slang::slang-glsl-module APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slang-glsl-module PROPERTIES + IMPORTED_COMMON_LANGUAGE_RUNTIME_RELEASE "" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libslang-glsl-module-2026.3.1.so" + IMPORTED_NO_SONAME_RELEASE "TRUE" + ) + +list(APPEND _cmake_import_check_targets slang::slang-glsl-module ) +list(APPEND _cmake_import_check_files_for_slang::slang-glsl-module "${_IMPORT_PREFIX}/lib/libslang-glsl-module-2026.3.1.so" ) + +# Import target "slang::slang" for configuration "Release" +set_property(TARGET slang::slang APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slang PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libslang-compiler.so.0.2026.3.1" + IMPORTED_SONAME_RELEASE "libslang-compiler.so.0.2026.3.1" + ) + +list(APPEND _cmake_import_check_targets slang::slang ) +list(APPEND _cmake_import_check_files_for_slang::slang "${_IMPORT_PREFIX}/lib/libslang-compiler.so.0.2026.3.1" ) + +# Import target "slang::slangc" for configuration "Release" +set_property(TARGET slang::slangc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(slang::slangc PROPERTIES + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/slangc" + ) + +list(APPEND _cmake_import_check_targets slang::slangc ) +list(APPEND _cmake_import_check_files_for_slang::slangc "${_IMPORT_PREFIX}/bin/slangc" ) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) diff --git a/lib/All/slang/lib/cmake/slang/slangTargets.cmake b/lib/All/slang/lib/cmake/slang/slangTargets.cmake new file mode 100644 index 0000000..242ad0c --- /dev/null +++ b/lib/All/slang/lib/cmake/slang/slangTargets.cmake @@ -0,0 +1,137 @@ +# Generated by CMake + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8) + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +if(CMAKE_VERSION VERSION_LESS "2.8.3") + message(FATAL_ERROR "CMake >= 2.8.3 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.8.3...3.29) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_cmake_targets_defined "") +set(_cmake_targets_not_defined "") +set(_cmake_expected_targets "") +foreach(_cmake_expected_target IN ITEMS slang::slang-llvm slang::slang-glslang slang::slangd slang::slangi slang::gfx slang::slang-glsl-module slang::slang slang::slangc) + list(APPEND _cmake_expected_targets "${_cmake_expected_target}") + if(TARGET "${_cmake_expected_target}") + list(APPEND _cmake_targets_defined "${_cmake_expected_target}") + else() + list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}") + endif() +endforeach() +unset(_cmake_expected_target) +if(_cmake_targets_defined STREQUAL _cmake_expected_targets) + unset(_cmake_targets_defined) + unset(_cmake_targets_not_defined) + unset(_cmake_expected_targets) + unset(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT _cmake_targets_defined STREQUAL "") + string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}") + string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n") +endif() +unset(_cmake_targets_defined) +unset(_cmake_targets_not_defined) +unset(_cmake_expected_targets) + + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Create imported target slang::slang-llvm +add_library(slang::slang-llvm MODULE IMPORTED) + +set_target_properties(slang::slang-llvm PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "SLANG_DYNAMIC" +) + +# Create imported target slang::slang-glslang +add_library(slang::slang-glslang MODULE IMPORTED) + +# Create imported target slang::slangd +add_executable(slang::slangd IMPORTED) + +# Create imported target slang::slangi +add_executable(slang::slangi IMPORTED) + +# Create imported target slang::gfx +add_library(slang::gfx SHARED IMPORTED) + +set_target_properties(slang::gfx PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "SLANG_GFX_DYNAMIC" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include" +) + +# Create imported target slang::slang-glsl-module +add_library(slang::slang-glsl-module MODULE IMPORTED) + +# Create imported target slang::slang +add_library(slang::slang SHARED IMPORTED) + +set_target_properties(slang::slang PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "SLANG_DYNAMIC" + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" +) + +# Create imported target slang::slangc +add_executable(slang::slangc IMPORTED) + +# Load information for each installed configuration. +file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/slangTargets-*.cmake") +foreach(_cmake_config_file IN LISTS _cmake_config_files) + include("${_cmake_config_file}") +endforeach() +unset(_cmake_config_file) +unset(_cmake_config_files) + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(_cmake_target IN LISTS _cmake_import_check_targets) + if(CMAKE_VERSION VERSION_LESS "3.28" + OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target} + OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}") + foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}") + if(NOT EXISTS "${_cmake_file}") + message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file + \"${_cmake_file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + endif() + unset(_cmake_file) + unset("_cmake_import_check_files_for_${_cmake_target}") +endforeach() +unset(_cmake_target) +unset(_cmake_import_check_targets) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/lib/All/slang/lib/libgfx.so b/lib/All/slang/lib/libgfx.so new file mode 100755 index 0000000..e1c6c4b --- /dev/null +++ b/lib/All/slang/lib/libgfx.so @@ -0,0 +1 @@ +libgfx.so.0.2026.3.1 \ No newline at end of file diff --git a/lib/All/slang/lib/libgfx.so.0.2026.3.1 b/lib/All/slang/lib/libgfx.so.0.2026.3.1 new file mode 100644 index 0000000..a256358 Binary files /dev/null and b/lib/All/slang/lib/libgfx.so.0.2026.3.1 differ diff --git a/lib/All/slang/lib/libslang-compiler.so b/lib/All/slang/lib/libslang-compiler.so new file mode 100755 index 0000000..419dd32 --- /dev/null +++ b/lib/All/slang/lib/libslang-compiler.so @@ -0,0 +1 @@ +libslang-compiler.so.0.2026.3.1 \ No newline at end of file diff --git a/lib/All/slang/lib/libslang-compiler.so.0.2026.3.1 b/lib/All/slang/lib/libslang-compiler.so.0.2026.3.1 new file mode 100644 index 0000000..d27ebf9 Binary files /dev/null and b/lib/All/slang/lib/libslang-compiler.so.0.2026.3.1 differ diff --git a/lib/All/slang/lib/libslang-glsl-module-2026.3.1.so b/lib/All/slang/lib/libslang-glsl-module-2026.3.1.so new file mode 100644 index 0000000..3fcf6b0 Binary files /dev/null and b/lib/All/slang/lib/libslang-glsl-module-2026.3.1.so differ diff --git a/lib/All/slang/lib/libslang-glslang-2026.3.1.so b/lib/All/slang/lib/libslang-glslang-2026.3.1.so new file mode 100644 index 0000000..6973eb1 Binary files /dev/null and b/lib/All/slang/lib/libslang-glslang-2026.3.1.so differ diff --git a/lib/All/slang/lib/libslang-llvm.so b/lib/All/slang/lib/libslang-llvm.so new file mode 100644 index 0000000..fba59e1 Binary files /dev/null and b/lib/All/slang/lib/libslang-llvm.so differ diff --git a/lib/All/slang/lib/libslang-rt.so b/lib/All/slang/lib/libslang-rt.so new file mode 100755 index 0000000..3a809f4 --- /dev/null +++ b/lib/All/slang/lib/libslang-rt.so @@ -0,0 +1 @@ +libslang-rt.so.0.2026.3.1 \ No newline at end of file diff --git a/lib/All/slang/lib/libslang-rt.so.0.2026.3.1 b/lib/All/slang/lib/libslang-rt.so.0.2026.3.1 new file mode 100644 index 0000000..a712fb6 Binary files /dev/null and b/lib/All/slang/lib/libslang-rt.so.0.2026.3.1 differ diff --git a/lib/All/slang/lib/libslang.so b/lib/All/slang/lib/libslang.so new file mode 100755 index 0000000..419dd32 --- /dev/null +++ b/lib/All/slang/lib/libslang.so @@ -0,0 +1 @@ +libslang-compiler.so.0.2026.3.1 \ No newline at end of file diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/accelerate-vector-coopmat.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/accelerate-vector-coopmat.slang new file mode 100644 index 0000000..3fee462 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/accelerate-vector-coopmat.slang @@ -0,0 +1,1379 @@ +// Unit test mode is used for unit testing the tiled MMA implementation. +// So we can test this single file by providing -DUNIT_TEST to the compiler. +implementing neural; + +#include "common-def.slang" + +public enum TargetEnum : uint32_t +{ + CUDA = 0, + SPIR_V = 1, +} + +public enum ExecutionMode : uint32_t +{ + Inference = 0, + Training = 1, +} + +[ForceInline] +internal uint getWaveId() +{ + __target_switch + { + case cuda: + uint3 tid = cudaThreadIdx(); + uint3 blockDim = cudaBlockDim(); + uint flattenedTid = tid.x + tid.y * blockDim.x + tid.z * blockDim.x * blockDim.y; + return flattenedTid / WaveGetLaneCount(); + case spirv: + return spirv_asm { + OpCapability GroupNonUniform; + result:$$uint = OpLoad builtin(SubgroupId:uint); + }; + } +} + +[ForceInline] +public int getWaveCount() +{ + // Note, we always require the threads count is multiple of the subgroup size, therefore we don't need to round up the result. + __stage_switch + { + case compute: + __target_switch + { + case cuda: + uint3 blockDim = cudaBlockDim(); + int warpsPerBlock = (blockDim.x * blockDim.y * blockDim.z) >> 5; + return warpsPerBlock; + case spirv: + uint3 workGroupSize = WorkgroupSize(); + int subGroupSize = WaveGetLaneCount(); + return (workGroupSize.x * workGroupSize.y * workGroupSize.z) / subGroupSize; + } + default: + // We need this because WorkgroupSize() call requires compute stage only. + static_assert(false, "Only support compute stage"); + return 0; + } +} + +// We can't convert T* to uint4* on shared memory in slang, therefore, we will provide two versions of shared memory pointer +// and implement both of them, and document about the difference between them. +internal typealias SPtr = Ptr; + +internal struct CoopMatShape + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + static const int ROW_A = 16; + static const int COLUMN_A = 16; + + // TODO: Currently, we only support floating point data type, therefore, we can always use 16x16x16. + // Once in the future we want to extend to support integer type, we can uncomment the following code. + static const int ROW_B = 16; // (Target == TargetEnum.CUDA) ? 16 : (sizeof(T) == 1 ? 32 : 16); + static const int COLUMN_B = 16; + + static const int ROW_C = 16; + static const int COLUMN_C = 16; + + static const int SizeAInElements = ROW_A * COLUMN_A; + static const int SizeBInElements = ROW_B * COLUMN_B; + static const int SizeCInElements = ROW_C * COLUMN_C; + + // Because the vectorized load is along K dimension (row of A and column of B), so we need to check + // if K is aligned with the vector size (ElementCountPerVector), we can use the vectorized load, + // otherwise, we need to use the scalar load. + // ElementCountPerVector is measured in T. + static const uint ElementCountPerVector = sizeof(uint4) / sizeof(half); + + // Since A and B can only be half type, ElementCountPerVector is fixed. However, C can be both half and float. + static const uint ElementCountPerVectorMatC = sizeof(uint4) / sizeof(T); + + static const uint CoopMatASizeInVector = (ROW_A * COLUMN_A) / ElementCountPerVector; + static const uint CoopMatBSizeInVector = (ROW_B * COLUMN_B) / ElementCountPerVector; + static const uint CoopMatCSizeInVector = (ROW_C * COLUMN_C) / ElementCountPerVectorMatC; +} + +struct TileInfo + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + typealias MatShape = CoopMatShape; + + static const bool IsAlignedVector = (K % MatShape.ElementCountPerVector) == 0; + + // For the Tile A, how many cooperative matrices in a row + static const int NCoopMatRow = TransposeA ? (K + MatShape.COLUMN_A - 1) / MatShape.COLUMN_A : + (M + MatShape.ROW_A - 1) / MatShape.ROW_A; + + // Notice that because of our specific workload, NTilesColumn is always warp-size (as long as it's more than half warp) or half warp (<= half warp). + // For the Tile B, how many cooperative matrices in a column + static const int NCoopMatColumn = (N + MatShape.COLUMN_B - 1) / MatShape.COLUMN_B; + + // Total number of cooperative matrices that consist the result of C = A * B + static const int NCoopMat = NCoopMatRow * NCoopMatColumn; + + // When A * B, k is the shared dimension, and when A^T * B, m is the shared dimension. + static const uint SharedDimensionSize = TransposeA ? Uint4AlignedM : Uint4AlignedK; + + // `Uint4AlignedK` is the K value that is aligned with the uint4 vector size. Because we always do the vectorized load + // along K dimension, so we need to align the K value with the vector size. + // Measured in T. + static const int Uint4AlignedK = ((K + (MatShape.ElementCountPerVector - 1)) / MatShape.ElementCountPerVector) * MatShape.ElementCountPerVector; + static const int Uint4AlignedM = ((M + (MatShape.ElementCountPerVector - 1)) / MatShape.ElementCountPerVector) * MatShape.ElementCountPerVector; + + // The height of tile A measure in T and uint4. + static const uint HeightInElementsTileA = NCoopMatRow * MatShape.ROW_A; + static const uint HeightInVectorTileA = HeightInElementsTileA / MatShape.ElementCountPerVector; + + // In order to achieve the high throughput, we will write data to shared memory in vectorized way. + // e.g. if T is half, it's 2 bytes, so uint4 can store 8 elements. + // Since the size in bytes of the tile in one row is T.COLUMN * sizeof(T), + // the number of vectorized columns in one row of cooperative matrix A is T.COLUMN * sizeof(T) / sizeof(uint4). + // `1` means one element of uint4. + static const uint WidthInVectorTileA = MatShape.COLUMN_A / MatShape.ElementCountPerVector; + + // WidthInElementTileA is the number of elements in one row of the tile in original data type. + static const uint WidthInElementTileA = MatShape.COLUMN_A; + + // Similarly, the number of vectorized rows in one column of cooperative matrix B is T.ROW * sizeof(T) / sizeof(uint4). + // `1` means one element of uint4 + static const uint HeightInVectorTileB = MatShape.ROW_B / MatShape.ElementCountPerVector; + + // So HeightInElementTileB is the number of elements in one column of the tile, measured in T. + static const uint HeightInElementTileB = HeightInVectorTileB * MatShape.ElementCountPerVector; + + // The height of tile B measure in T and uint4. + static const int WidthInElementsTileB = NCoopMatColumn * MatShape.COLUMN_B; + static const int WidthInVectorTileB = WidthInElementsTileB / MatShape.ElementCountPerVector; + + static const uint HeightInVectorTileC = MatShape.ROW_C / MatShape.ElementCountPerVectorMatC; +} + +// A wrapper of matrix type to access each tile of the matrix +// Note: The reason we want to make SubgroupSize as a generic parameter instead of using WaveGetLaneCount() is that +// we need the logic to be expand as much as possible during compile time. WaveGetLaneCount() is a runtime function, +// so if we use it directly in our mma function, some of branches won't be eliminated during compile time. +[require(cooperative_matrix)] +VISIBILITY_LEVEL struct MMAHelper + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + typealias TileInfo = TileInfo; + typealias CMShape = CoopMatShape; + typealias ShMemInfo = SharedMemoryUsage; + + static const linalg.CoopMatMatrixLayout RowMajor = linalg.CoopMatMatrixLayout.RowMajor; + static const linalg.CoopMatMatrixLayout ColumnMajor = linalg.CoopMatMatrixLayout.ColumnMajor; + + // Weight matrix is in shape of M x K + // Input vector will be collected by each thread in a sub-group to form a matrix in shape of K x N + // Note, M, K, N are measured in T. + // Since Cooperative matrix is only worked for a whole subgroup (warp), so we always use the SubgroupSize as the N value. + static const int M = OutputSize; + static const int N = SubgroupSize; + static const int K = InputSize; + + VISIBILITY_LEVEL static const int Uint4AlignedK = TileInfo.Uint4AlignedK; + VISIBILITY_LEVEL static const int Uint4AlignedM = TileInfo.Uint4AlignedM; + + // NumLoadsEachThreadMatA is the number of loads each thread needs to perform. + // N is the number of active threads in the subgroup. + // For matrix A, each iteration we load a column of matrix tile of Matrix A, which is height * sizeof(elementType) x 16 bytes. + // And each thread can load 16 bytes for each load, so the number of loads each thread needs to do for half type is + // (M * 32) / (N * 16) = M * 2 / N, and we just round up the result to the nearest integer. + static const uint NumLoadsEachThreadMatA = (TileInfo.HeightInElementsTileA * 2 + N - 1) / N; + + static const uint NumStoresEachThreadMatA = (sizeof(T) == 2) ? + NumLoadsEachThreadMatA : + (TileInfo.HeightInElementsTileA * 4 + N - 1) / N; + + // OffsetPerThreadLoadMatA is the offset between each load. + // The reason is same as above, since the whole subgroup can load N * 16 bytes, and the load is consecutive, + // so the offset is the N * 16 bytes, and we measure it in uint4 units, so it's N. + static const uint OffsetPerThreadLoadMatA = N; + + // A/B can only be half, so we don't need to use generic parameter here. + typealias MatA = linalg.CoopMat; + typealias MatB = linalg.CoopMat; + typealias MatC = linalg.CoopMat; + + // TODO: This will always double the buffer usage, therefore we haven't really implemented the double buffer yet. + static const bool EnableDoubleBuffer = false; + + [ForceInline] + static uint flattenedIndex(uint2 coord) + { + if (TransposeA) + { + return coord.y + coord.x * Stride; + } + else + { + return coord.x + coord.y * Stride; + } + } + + [ForceInline] + static uint2 vectorizedTileCoordToWeightCoord(uint2 coordInTile, int tileIndex) + { + uint2 coordOut; + if (TransposeA) + { + coordOut.x = coordInTile.x + tileIndex * TileInfo.WidthInElementTileA; + coordOut.y = coordInTile.y * ElemCountPerVector; + } + else + { + coordOut.x = coordInTile.x * ElemCountPerVector + tileIndex * TileInfo.WidthInElementTileA; + coordOut.y = coordInTile.y; + } + return coordOut; + } + + [ForceInline] + static uint2 vectorizedTileIndexTo2DCoord(uint indexInVectorizedTile) + { + uint2 coordOut; + if (TransposeA) + { + coordOut.x = indexInVectorizedTile / HeightInVector; + coordOut.y = indexInVectorizedTile % HeightInVector; + } + else + { + coordOut.x = indexInVectorizedTile % WidthInVector; + coordOut.y = indexInVectorizedTile / WidthInVector; + } + return coordOut; + } + // Load a tiled column of the Matrix A into shared memory. + // We load a column of matrix tile of Matrix A each time, because our iteration is over K dimension. + // We require the Matrix A is stored as row major in the weight storage. + // Also we load the tile into shared memory in row major. + // For each workgroup (thread block), we only use the first Subgroup (warp) to load the data. + // This is just balanced decision between simplicity and bank conflict. Given that the shared memory tile + // is not that large, if the warp is full, then each thread only needs to load 2 twice, therefore there is + // no need to use more than one warp. And more warp could also make the algorithm avoiding bank conflict more + // complicated. + // So implement as this for now. We can profiling the application later, if it turns out to be a bottleneck, + // we can consider using more than one warp in the future. + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + internal static void matALoadStore( + SPtr sharedMemory, + int tileIndex, + Address weightAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + { + uint indexInVectorizedTile = WaveGetLaneIndex(); + + // In load case, since we always load the matrix into MatA, so the tile must in half type, because that is + // what MatA can only support. + // However, in store, we store the MatC which could be float type, so we need to adjust the tile height in vector + // and element count per vector. + static const int elementCountPerVector = isStore ? CMShape.ElementCountPerVectorMatC : CMShape.ElementCountPerVector; + static const int heightInVector = isStore ? + TileInfo.HeightInVectorTileA * CMShape.ElementCountPerVector / CMShape.ElementCountPerVectorMatC : + TileInfo.HeightInVectorTileA; + static const int widthInVector = isStore ? + TileInfo.WidthInVectorTileA * CMShape.ElementCountPerVector / CMShape.ElementCountPerVectorMatC : + TileInfo.WidthInVectorTileA; + static const int numLoadOrStorePerThread = isStore ? NumStoresEachThreadMatA : NumLoadsEachThreadMatA; + + // get the 2-D coordinate of the tile in the vectorized tile + const uint2 coordInTile = vectorizedTileIndexTo2DCoord(indexInVectorizedTile); + + // tx and ty are the 2-D coordinate of scalar tile. + // row coordinate ty is the same between vectorized tile and original tile. + // column coordinate tx needs to be scaled by ElementCountPerVector to get the actual column coordinate in original data type. + uint2 coordInWeight = vectorizedTileCoordToWeightCoord(coordInTile, tileIndex); + + uint4 value; + uint indexInWeight; + + [ForceUnroll] + for (uint i = 0; i < numLoadOrStorePerThread; i++) + { + if (coordInWeight.y >= TileInfo.HeightInElementsTileA) + break; + // Given the coordinate inside the tile and the tile index, we can get the index in weight matrix. + // Note, we always treat row of matrix A as uint4 aligned, so always calculate 'indexInWeight' as if it's uint4 aligned. + // though it might not. But readUint4() will handle the padding. + // We only need to provide the actual boundary and the aligned boundary. + indexInWeight = flattenedIndex(coordInWeight); + + // Bounds check on global memory. + bool isOutOfRange = TransposeA ? + ((coordInWeight.y >= K) | (coordInWeight.x >= M)) : + ((coordInWeight.y >= M) | (coordInWeight.x >= K)); + + if (isStore == false) + { + if (isOutOfRange) + { + // If the coordinate is out of range of Matrix A, just padding with 0. + value = uint4(0, 0, 0, 0); + } + else + { + // Though the weight matrix is not necessarily aligned with the uint4 vector size, readUint4() will handle the padding + // if the reading is cross the boundary of the uint4 vector size. + // MatA can only be half type, so we can always read it as half type no matter what the data type of the weight matrix is. + value = weightAddress.readUint4(int(indexInWeight)); + } + + sharedMemory[indexInVectorizedTile] = value; + } + else + { + // We don't need padding when store back to global memory, because the padding is only needed when construct the cooperative matrix. + // So if there is out of range, we don't need to store anything. + if (!isOutOfRange) + { + value = sharedMemory[indexInVectorizedTile]; + weightAddress.writeUint4Atomic(int(indexInWeight), value); + } + } + + indexInVectorizedTile += OffsetPerThreadLoadMatA; + + // Given the index in the tile, get the 2-D coordinate in the matrix A. + // Note that, when TransposeA is true, this is 2-D coordinate in the matrix A^T. We don't change the semantics of the 2-D coordinate + // in matrix, but we change the way to calculate the 1-D index in the matrix. But we can still use the same function to get the 2-D coordinate. + coordInWeight = vectorizedTileCoordToWeightCoord( + vectorizedTileIndexTo2DCoord(indexInVectorizedTile), + tileIndex); + } + } + + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static void loadShA( + SPtr sharedMemory, + int tileIndex, + Address weightAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + { + matALoadStore(sharedMemory, tileIndex, weightAddress); + } + + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static void storeShA( + SPtr sharedMemory, + int tileIndex, + Address weightAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + { + matALoadStore(sharedMemory, tileIndex, weightAddress); + } + + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + internal static void vectorLoadStore( + SPtr sharedMemoryB, + int tileIndex, + int subgroupIndex, + inout InputArray inoutVector) + where U : __BuiltinFloatingPointType + where InputArray : IArrayAccessor + { + const uint laneId = WaveGetLaneIndex(); + + // select the correct shared memory layout configurations. + // In store case, we actually store the MatC, whose data type could not be `half`. + const uint elementPerVector = Op != AccessOp.READ ? CMShape.ElementCountPerVectorMatC : CMShape.ElementCountPerVector; + const uint heightInVectorTile = Op != AccessOp.READ ? TileInfo.HeightInVectorTileC : TileInfo.HeightInVectorTileB; + const uint sharedMemSizeInVector = Op != AccessOp.READ ? ShMemInfo.SharedMemSizeInVectorMatC : ShMemInfo.SharedMemSizeInVectorMatB; + + // In store case, we actually store the MatC. So the shared memory size could be different from MatB. + SPtr sharedMemoryBSubgroup = sharedMemoryB + subgroupIndex * sharedMemSizeInVector; + + // start index in vectorized tile for current thread: x * column_stride + const uint indexInVectorizedTile = laneId * heightInVectorTile; + const uint yOffset = (tileIndex * heightInVectorTile) * elementPerVector; + + [ForceUnroll] + for (uint yInTile = 0; yInTile < heightInVectorTile; yInTile++) + { + const int startIndex = yInTile * elementPerVector + yOffset; + + // Bounds check on Y direction. If y coordinate out of the input vector length, just padding with 0. + // No need to check the X direction, because the X direction is bound by the thread count, so any active + // thread will definitely have its thread-local vector available. + + bool isOutOfRange; + + if (Op == AccessOp.READ) + { + // For vector load, we are performing MMA, so the input vector has length of K + // in normal case, and M in transpose case. + isOutOfRange = TransposeA ? (startIndex >= M) : (startIndex >= K); + if (isOutOfRange) + { + sharedMemoryBSubgroup[indexInVectorizedTile + yInTile] = uint4(0, 0, 0, 0); + continue; + } + + // It's fine that we only use the aligned version of readUint4() here, because the inputVector is the internal data which we can always + // create it as an aligned array. + uint4 value; + + // Note we can only use half type for matrix A and B, the value must be packed by 8 half type elements. + accessUint4Aligned(inoutVector, startIndex, value); + sharedMemoryBSubgroup[indexInVectorizedTile + yInTile] = value; + } + else + { + // for vector store, the length of output vector has length of M in normal case + // and K in transpose case. + isOutOfRange = TransposeA ? (startIndex >= K) : (startIndex >= M); + + // No padding needs for writing back to local vector. + if (isOutOfRange) + return; + + // in store case, we always store MatC, so the data type is T. + uint4 value = sharedMemoryBSubgroup[indexInVectorizedTile + yInTile]; + accessUint4Aligned(inoutVector, startIndex, value); + } + } +# if 0 + // TODO: In most case (on AMD and NVIDIA GPU), N (SubgroupSize) >= AlignedN (aligned to tile width of matrix B), as + // subgroup size is usually larger than the tile width of matrix B. + // But in some corner cases (e.g. intel GPU), where the hardware only support very small subgroup size, N could be less than AlignedN. + // Not sure if we want to support this case! + if (N < AlignedN) + { + // If the active thread count is less than the aligned N, we need to pad the remaining columns with 0. + const uint numPaddingColumns = AlignedN - N; + + // The number of vectors to load == numPaddingColumns * HeightInVectorTileB. + // The number of vectors to load per thread == (numPaddingColumns * HeightInVectorTileB / N). + const uint numLoadsEachThreadMatB = (numPaddingColumns * HeightInVectorTileB + N - 1) / N; + const uint offsetPerThreadLoadMatB = N; + + // Because we already load N columns, the starting index is N * HeightInVectorTileB. + SPtr paddingShmPtr = sharedMemoryBSubgroup + N * HeightInVectorTileB; + + uint index = laneId; + for (uint i = 0; i < numLoadsEachThreadMatB; i++) + { + const uint xIndex = index / HeightInVectorTileB; + if (xIndex >= numPaddingColumns) + break; + paddingShmPtr[index] = uint4(0, 0, 0, 0); + index += offsetPerThreadLoadMatB; + } + } +# endif + } + + // Load the input vector into shared memory. Each input vector is a column of the matrix B. + // Since the input vector is loaded from thread local memory, one thread can only load one + // column of the matrix B. + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static void loadVectorToShB( + SPtr sharedMemoryB, + int tileIndex, + int subgroupIndex, + InputArray inputVector) + where U : __BuiltinFloatingPointType + where InputArray : IArrayAccessor + { + vectorLoadStore(sharedMemoryB, tileIndex, subgroupIndex, inputVector); + } + + // Load the input vector into shared memory. Each input vector is a column of the matrix B. + // Since the input vector is loaded from thread local memory, one thread can only load one + // column of the matrix B. + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static void storeVectorFromShB( + SPtr sharedMemoryB, + int tileIndex, + int subgroupIndex, + inout InputArray inoutVector) + where U : __BuiltinFloatingPointType + where InputArray : IArrayAccessor + { + vectorLoadStore(sharedMemoryB, tileIndex, subgroupIndex, inoutVector); + } + + // Read one complete vector into the shared memory. Different from the loadVectorToShB, + // this function is used to load the input vector into the shared memory for the transpose case, where each + // tile will not contain the all the vectors in a warp. Instead, only partial warp will load the complete vector + // into the shared memory. Compared to the LoadSharedMemoryFromLocalVector, where it loads partial vectors by every thread + // in a warp. + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static void loadVectorForOuterProduct( + SPtr sharedMemory, + int tileIndex, + InputArray inputVector) + where U : __BuiltinFloatingPointType + where U.Differential == U + where InputArray : IArrayAccessor + { + const uint laneId = WaveGetLaneIndex(); + + // Due the limitation of the size of shared memory, we cannot load all the vectors in a warp to the shared memory. Instead, + // we can only load it in smaller batches (batch size is the WMMA tile in column or row). + if ((laneId / BatchSize) != tileIndex) + return; + + uint index = (laneId % BatchSize) * TileStrideInVector; + + [ForceUnroll] + for (uint i = 0; i < TileStrideInVector; i++) + { + uint4 value; + if (i >= ArraySizeInVector) + { + value = uint4(0, 0, 0, 0); + } + else + { + accessUint4Aligned(inputVector, i * CMShape.ElementCountPerVector, value); + } + sharedMemory[index + i] = value; + } + } + + [require(cooperative_matrix, subgroup_basic)] + internal static void sumReduceTiles(inout MatC matC[ROW*COLUMN], in int subgroupId, SPtr sharedMemory) + { + const int subgroupCount = getWaveCount(); + + // perform n/2 sum reduces, so each iteration will perform a 2-way reduce operation, + // totally log2(n) steps, where n is the number of subgroups. + for (int k = 1; k < subgroupCount; k <<= 1) + { + // (subgroupId / k<< 1 ) calculate which cooperative matrix tile this warp will write to. + // The whole shared memory is divided into subgroupCount/2 parts. So each two neighboring subgroups + // will use one shared memory. And left subgroup loads, right subgroup stores. + uint subgroupOffset = (subgroupId / (k<<1)) * (CMShape.CoopMatCSizeInVector * COLUMN); + let ptrPerWarp = sharedMemory + subgroupOffset; + [ForceUnroll] + for (int i = 0; i < ROW; i++) + { + // Store one row of cooperative matrix to the shared memory. + [ForceUnroll] + for (int j = 0; j < COLUMN; j++) + { + // This is the right node in the 2-way merge operation. + if (subgroupId % (k<<1) == k) + { + // We choose to process one row of cooperative matrices at a time, store the cooperative matrix in column major is more efficient. + // Because in column major, each column of the cooperative matrix is contiguous in the shared memory, so there will not be bank conflict. + matC[i * COLUMN + j].Store(ptrPerWarp + j * CMShape.CoopMatCSizeInVector, + CMShape.ROW_C / CMShape.ElementCountPerVectorMatC); + } + } + + // wait for all subgroups finishing store the cooperative matrix to the shared memory. + GroupMemoryBarrierWithGroupSync(); + + // This the left node in the 2-way merge operation. + if (subgroupId % (k<<1) == 0) + { + // If the left node is the last subgroup, it means that there is no right node for it, so we don't need to do any addition for this subgroup. + if (subgroupId != (subgroupCount - 1)) + { + [ForceUnroll] + for (int j = 0; j < COLUMN; j++) + { + MatC rightMatC = MatC.Load(ptrPerWarp + j * CMShape.CoopMatCSizeInVector, + CMShape.ROW_C / CMShape.ElementCountPerVectorMatC); + + matC[i * COLUMN + j] = matC[i * COLUMN + j] + rightMatC; + } + } + } + // wait for all subgroups finishing the addition. + GroupMemoryBarrierWithGroupSync(); + } + } + } + + // ========================================================================= + // Shared memory pack/unpack helpers + // + // Shared memory is typed as SPtr (16 bytes per slot). + // We cannot reinterpret-cast shared memory pointers in SPIR-V's logical + // addressing model, so we manually pack/unpack scalar values of type U + // into/from the uint4 array using bit_cast and shift operations. + // + // Layout: element index `i` of type U is stored at: + // uint4 slot: i / ElementsPerUint4 + // uint comp: (i % ElementsPerUint4) / ElementsPerUint + // sub-element: i % ElementsPerUint (shift = subIdx * sizeof(U) * 8) + // ========================================================================= + + /// Store a scalar value of type U into uint4 shared memory at flat element index. + [ForceInline] + static void smemStore(SPtr mem, int index, U value) + where U : __BuiltinFloatingPointType + { + static const int elementsPerUint = 4 / sizeof(U); + static const int elementsPerUint4 = 16 / sizeof(U); + static const int bitsPerElement = sizeof(U) * 8; + + const int slot = index / elementsPerUint4; + const int comp = (index % elementsPerUint4) / elementsPerUint; + const int sub = index % elementsPerUint; + const uint shift = sub * bitsPerElement; + + switch (sizeof(U)) + { + case 2: + { + uint packed = mem[slot][comp]; + // Clear the target bits and insert new value + packed = (packed & ~(uint(0xFFFF) << shift)) | (uint(bit_cast(value)) << shift); + mem[slot][comp] = packed; + } + break; + case 4: + mem[slot][comp] = bit_cast(value); + break; + } + } + + /// Load a scalar value of type U from uint4 shared memory at flat element index. + [ForceInline] + static U smemLoad(SPtr mem, int index) + where U : __BuiltinFloatingPointType + { + static const int elementsPerUint = 4 / sizeof(U); + static const int elementsPerUint4 = 16 / sizeof(U); + static const int bitsPerElement = sizeof(U) * 8; + + const int slot = index / elementsPerUint4; + const int comp = (index % elementsPerUint4) / elementsPerUint; + const int sub = index % elementsPerUint; + const uint shift = sub * bitsPerElement; + + switch (sizeof(U)) + { + case 2: + return bit_cast(uint16_t((mem[slot][comp] >> shift) & 0xFFFF)); + case 4: + return bit_cast(mem[slot][comp]); + default: + return U(0); + } + } + + /// Load a packed uint from uint4 shared memory at a uint-level index. + /// This is useful for reading two half values packed in a single uint. + [ForceInline] + static uint smemLoadUint(SPtr mem, int uintIndex) + { + const int slot = uintIndex / 4; + const int comp = uintIndex % 4; + return mem[slot][comp]; + } + + // Helper function: Cross-warp reduction and atomic write to global memory. + // Reads from shared memory where each warp has written its partial sums, + // reduces across warps, and atomically adds to the bias gradient. + // + // For half type: Uses vector atomics (maps to red.relaxed.gpu.global.add.noftz.f16x2 on CUDA) + // For other types: Uses scalar atomicAdd + // + // @param sharedMemory Shared memory containing partial sums from each warp + // @param subgroupId Current warp index + // @param subgroupCount Total number of warps + // @param biasAddress Pointer-like address for bias gradient + // @param MPadded M rounded up to even (for half2 alignment) + // @param ColsPacked Number of packed pairs per warp (MPadded / 2) + [ForceInline] + static void crossWarpReduceAndAtomicWrite( + SPtr sharedMemory, + int subgroupId, + int subgroupCount, + Address biasAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + { + const uint laneId = WaveGetLaneIndex(); + const int NUM_VECTORS = subgroupCount * N; + const int ColsPerThread = ColsPacked / NUM_VECTORS; + const int NumIters = (ColsPacked % NUM_VECTORS) != 0 ? ColsPerThread + 1 : ColsPerThread; + + int packed_col_idx = subgroupId * N + laneId; + + if (U is half) + { + // Half path: pack two half values into uint for efficient shared memory access + // Uses vector atomic which maps to red.relaxed.gpu.global.add.noftz.f16x2 on CUDA + + for (int j = 0; j < NumIters; j++) + { + if (packed_col_idx < ColsPacked) + { + // Sum packed half2 across all warps + half sum0 = half(0); + half sum1 = half(0); + + for (int i = 0; i < subgroupCount; i++) + { + // Each warp's data is at offset i * ColsPacked (in half2/uint units) + uint packed = smemLoadUint(sharedMemory, packed_col_idx + i * ColsPacked); + half elem0 = bit_cast(uint16_t(packed & 0xFFFF)); + half elem1 = bit_cast(uint16_t((packed >> 16) & 0xFFFF)); + sum0 = sum0 + elem0; + sum1 = sum1 + elem1; + } + + // Only write valid elements + int elemIdx0 = packed_col_idx * 2; + int elemIdx1 = elemIdx0 + 1; + + if (elemIdx1 < M) + { + // Both elements are valid - use vector atomic + // TODO: vector atomicAdd needs to be added to IPointerLikeAddress + vector sum_v2 = vector(U(sum0), U(sum1)); + let addr = biasAddress.getOffset(elemIdx0); + addr.atomicAdd(0u, sum_v2); + } + else if (elemIdx0 < M) + { + // Only first element is valid (M is odd) + biasAddress.atomicAdd(uint(elemIdx0), U(sum0)); + } + } + + packed_col_idx += NUM_VECTORS; + } + } + else + { + // Non-half path: use scalar atomicAdd (no native vector atomic support) + // Read individual elements from uint4 shared memory via smemLoad. + + for (int j = 0; j < NumIters; j++) + { + if (packed_col_idx < ColsPacked) + { + int elemIdx0 = packed_col_idx * 2; + int elemIdx1 = elemIdx0 + 1; + + // Sum elements across all warps + U sum0 = U(0); + U sum1 = U(0); + + for (int i = 0; i < subgroupCount; i++) + { + sum0 = sum0 + smemLoad(sharedMemory, i * MPadded + elemIdx0); + if (elemIdx1 < MPadded) + sum1 = sum1 + smemLoad(sharedMemory, i * MPadded + elemIdx1); + } + + if (elemIdx0 < M) + { + biasAddress.atomicAdd(uint(elemIdx0), sum0); + } + if (elemIdx1 < M) + { + biasAddress.atomicAdd(uint(elemIdx1), sum1); + } + } + + packed_col_idx += NUM_VECTORS; + } + } + } + + // Sum reduce of the dOut across the block and accumulate to bias gradient. + // + // Uses __atomic_reduce_add which maps to PTX `red` instruction on CUDA: + // red.relaxed.gpu.global.add.noftz.f16x2 for half2 + // This is faster than standard atomicAdd because: + // 1. Uses relaxed memory ordering (less synchronization overhead) + // 2. Single instruction for two half values + [ForceInline] + [require(cuda_spirv, subgroup_partitioned)] + [require(cuda_spirv, sm_6_6)] + VISIBILITY_LEVEL static void sumReduceRows( + SPtr sharedMemory, + in InArrayType dOut, + in int subgroupId, + Address biasAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + where InArrayType : IArrayAccessor + { + const uint laneId = WaveGetLaneIndex(); + const int subgroupCount = getWaveCount(); + + // Phase 1: Warp-level reduction + InArrayType localResult; + [ForceUnroll] + for (int i = 0; i < M; i++) + { + localResult[i] = WaveActiveSum(dOut[i]); + } + + // Pad M to even number for half2 alignment + static const int MPadded = (M + 1) & ~1; // Round up to even + static const int ColsPacked = MPadded / 2; // Number of half2 pairs per warp + static const int HasOddElement = M % 2; // 1 if M is odd, 0 otherwise + + // Layout: [warp0: MPadded elements][warp1: MPadded elements]... + // Shared memory stays as uint4; pack/unpack via smemStore/smemLoad helpers. + + // Phase 2: Lane 0 of each warp writes reduced result to shared memory + if (laneId == 0) + { + [ForceUnroll] + for (int i = 0; i < M; i++) + { + smemStore(sharedMemory, subgroupId * MPadded + i, localResult[i]); + } + // Pad with zero if M is odd + if (HasOddElement != 0) + { + smemStore(sharedMemory, subgroupId * MPadded + M, U(0)); + } + } + + GroupMemoryBarrierWithGroupSync(); + + // Phase 3: Cross-warp reduction and atomic write + crossWarpReduceAndAtomicWrite( + sharedMemory, subgroupId, subgroupCount, biasAddress); + } + + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + [require(spvAtomicFloat16AddEXT)] + VISIBILITY_LEVEL static void outerProductAccumulate( + SPtr sharedMemoryA, + SPtr sharedMemoryB, + InArrayTypeA inputVectorA, + InArrayTypeB inputVectorB, + Address weightAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + where TypeA : __BuiltinFloatingPointType + where TypeA.Differential == TypeA + where TypeB : __BuiltinFloatingPointType + where TypeB.Differential == TypeB + where InArrayTypeA : IArrayAccessor + where InArrayTypeB : IArrayAccessor + { + const uint subgroupIndex = getWaveId(); + + // Batch size is either CoopMatA row count or CoopMatB column count, they are the same. + static const int BatchSize = CMShape.COLUMN_A; + static const int CoopMatCRows = (M + CMShape.ROW_A - 1) / CMShape.ROW_A; + static const int CoopMatCColumns = (K + CMShape.COLUMN_A - 1) / CMShape.COLUMN_A; + static const int StrideInVectorTileB = CoopMatCColumns * CMShape.COLUMN_B / CMShape.ElementCountPerVector; + static const int StrideInVectorTileA = CoopMatCRows * CMShape.ROW_A / CMShape.ElementCountPerVector; + static const int StrideInVectorTileC = CoopMatCColumns * CMShape.COLUMN_C / CMShape.ElementCountPerVectorMatC; + + MatC matC[CoopMatCRows * CoopMatCColumns]; + [ForceUnroll] + for (int i = 0; i < CoopMatCRows * CoopMatCColumns; i++) + { + matC[i].fill(T(0.0f)); + } + + SPtr warpLocalPtrA = sharedMemoryA + subgroupIndex * StrideInVectorTileA * BatchSize; + SPtr warpLocalPtrB = sharedMemoryB + subgroupIndex * StrideInVectorTileB * BatchSize; + + // Perform outer product for each warp. + // The shared dimension is the Subgroup size N. + [ForceUnroll] + for (uint k = 0; k < N; k += CMShape.COLUMN_A) + { + uint tileIndex = k / CMShape.COLUMN_A; + loadVectorForOuterProduct(warpLocalPtrA, tileIndex, inputVectorA); + loadVectorForOuterProduct(warpLocalPtrB, tileIndex, inputVectorB); + GroupMemoryBarrierWithWaveSync(); + + MatA matA[CoopMatCRows]; + [ForceUnroll] + for (uint i = 0; i < CoopMatCRows; i++) + { + matA[i] = MatA.Load( warpLocalPtrA + i * CMShape.ROW_A / CMShape.ElementCountPerVector, StrideInVectorTileA); + } + + [ForceUnroll] + for (uint j = 0; j < CoopMatCColumns; j++) + { + // For matrix B, stride will be the width of the tile. This is different from the forward pass in A*B where the stride is height of tile B. + // Since width of the tile B in outer product is K (input vector length), so the stride will be alignedK / ElementCountPerVector. + let matB = MatB.Load(warpLocalPtrB + j * CMShape.COLUMN_B / CMShape.ElementCountPerVector, StrideInVectorTileB); + for (uint i = 0; i < CoopMatCRows; i++) + { + int index = i * CoopMatCColumns + j; + matC[index] = linalg.coopMatMulAdd(matA[i], matB, matC[index]); + } + } + } + + // sum reduce will accumulate the result cross all the warps into the cooperative matrix in the first subgroup. + sumReduceTiles(matC, subgroupIndex, sharedMemoryB); + + // Only the first subgroup need to store the result to the global memory. + + if (subgroupIndex == 0) + { + // Store the result shared memory. We store one row of the cooperative matrix at a time. + [ForceUnroll] + for (uint i = 0; i < CoopMatCRows; i++) + { + [ForceUnroll] + for (uint j = 0; j < CoopMatCColumns; j++) + { + // Save the result to shared memory in row major, because this is cache friendly for global memory access. + // As each row of the tile will be corresponding to the contiguous global memory. + matC[i * CoopMatCColumns + j].Store(sharedMemoryB + j * CMShape.COLUMN_C / CMShape.ElementCountPerVectorMatC, (uint)StrideInVectorTileC); + + } + + // We will leverage the fact that the result the outerproduct is the same shape as matrix A. But, the tile organization is different. + // In forward pass, the tile in the shared memory is in shape M x T_ROW_A, which is one column of cooperative matrices. + // while the result here is in shape T_ROW_A x K, which is one row of cooperative matrices. + // So we can use transposed version of LoadShA/StoreShA to store the result. Because in transpose version, the major-ness is along + // K dimension. Note that column major in transpose case is just the row major in non-transpose case. + + typealias MMA = MMAHelper; + MMA.storeShA(sharedMemoryB, i, weightAddress); + + // Wait until all threads in the warp finish reading the shared memory and storing to the global memory. + GroupMemoryBarrierWithWaveSync(); + } + } + + AllMemoryBarrierWithGroupSync(); + } + + // The workload is different from the large size matrix-matrix multiply, we actually perform the matrix-vector multiply + // for each thread, so the matrix-matrix multiply only needs to be performed for each warp (sub-group). + [ForceInline] + [require(cooperative_matrix, subgroup_basic)] + VISIBILITY_LEVEL static OutArrayType mma(InArrayType inputVector, + SPtr sharedMemoryA, + SPtr sharedMemoryB, + SPtr sharedMemoryC, + Address weightAddress, + Optional
biasAddress) + where U : __BuiltinFloatingPointType + where U.Differential == U + where Address : IPointerLikeAddress + where V : __BuiltinFloatingPointType + where V.Differential == V + where InArrayType : IArrayAccessor + where OutArrayType : IArrayAccessor + { + SPtr ptrA[EnableDoubleBuffer ? 2 : 1]; + SPtr ptrB[EnableDoubleBuffer ? 2 : 1]; + SPtr ptrC = sharedMemoryC; + const uint subgroupIndex = getWaveId(); + + if (!EnableDoubleBuffer) + { + ptrA[0] = sharedMemoryA; + ptrB[0] = sharedMemoryB; + } + else + { + ptrA[0] = sharedMemoryA; + ptrA[1] = sharedMemoryA + ShMemInfo.SharedMemSizeInVectorMatA; + ptrB[0] = sharedMemoryB; + ptrB[1] = sharedMemoryB + ShMemInfo.SharedMemSizeInVectorMatB; + // PreLoad for the first iteration + loadShA(ptrA[0], 0, weightAddress); + loadVectorToShB(ptrB[0], 0, subgroupIndex, inputVector); + } + + // fetch first tile of Matrix A and Matrix B into shared memory + // Iterate over the K dimension, T.COLUMN is column of Matrix A. + uint bufferIndex = 0; + MatC matC[TileInfo.NCoopMat]; + [ForceUnroll] + for (int i = 0; i < TileInfo.NCoopMat; i++) + { + matC[i].fill(T(0.0f)); + } + + OutArrayType outputVector; + if (Bias) + { + [ForceUnroll] + for (int i = 0; i < M; i++) + { + U bias = biasAddress.value[uint(i)]; + outputVector[i] = __realCast(bias); + } + } + + [ForceUnroll] + for (int k = 0; k < TileInfo.SharedDimensionSize; k += CMShape.COLUMN_A) + { + uint tileIndex = k / CMShape.COLUMN_A; + + if (EnableDoubleBuffer) + { + GroupMemoryBarrierWithGroupSync(); + + // swap to next buffer to load new data. + bufferIndex = bufferIndex ^ 1; + // Load the another buffer and do the math so we can hide the latency of the load. + loadShA(ptrA[bufferIndex], tileIndex, weightAddress); + loadVectorToShB(ptrB[bufferIndex], tileIndex, subgroupIndex, inputVector); + + // swap back to the previous buffer to perform the math. + bufferIndex = bufferIndex ^ 1; + } + else + { + loadShA(ptrA[0], tileIndex, weightAddress); + loadVectorToShB(ptrB[0], tileIndex, subgroupIndex, inputVector); + + // The reason that we have to sync the whole workgroup is that for matrix A, the tile is shared by + // whole workgroup. + + // TODO: + // The alternative solution to duplicate the tile A to each subgroup, so we will only need warp sync here. + // But that will waste lots of shared memory and increase memory transactions. We need benchmark to see + // which solution is better. + GroupMemoryBarrierWithGroupSync(); + } + + // Math loop: This operator is executed by each warp (sub-group). shA is shared by all threads in the workgroup, while + // shB is shared only by each subgroup, and each subgroup will have its own offset on shB. + // For matB, each warp could only have 1 or 2 Tiles to load according whether this warp is less (1 tile) or more than half warp (2 tiles). + MatA matA[TileInfo.NCoopMatRow]; + [ForceUnroll] + for (uint i = 0; i < TileInfo.NCoopMatRow; i ++) + { + if (TransposeA) + { + // Really be careful the stride of tile A in the transpose case. The tile is column major, and the cooperative matrix is stacked in columns of the tile. + // So the stride is actually the height the tile. The offset between two cooperative matrices is just height of the cooperative matrix. + matA[i] = MatA.Load(ptrA[bufferIndex] + i * CMShape.ROW_A/CMShape.ElementCountPerVector, TileInfo.HeightInVectorTileA); + } + else + { + matA[i] = MatA.Load(ptrA[bufferIndex] + i * CMShape.CoopMatASizeInVector, TileInfo.WidthInVectorTileA); + } + } + + [ForceUnroll] + for (uint j = 0; j < TileInfo.NCoopMatColumn; j ++) + { + // NTilesColumn * HeightInVectorTileB is the size of the shared memory for matrix B in one warp measured in vector uint4. + SPtr ptrPerWarp = ptrB[bufferIndex] + subgroupIndex * ShMemInfo.SharedMemSizeInVectorMatB; + let matB = MatB.Load(ptrPerWarp + j * CMShape.CoopMatBSizeInVector, TileInfo.HeightInVectorTileB); + + for (uint i = 0; i < TileInfo.NCoopMatRow; i ++) + { + int index = i * TileInfo.NCoopMatColumn + j; + matC[index] = linalg.coopMatMulAdd(matA[i], matB, matC[index]); + } + } + } + + // Write back the result to shared memory B. We store the result in column major because each column is + // actually the output vector of the matrix-vector multiply, which is also a thread-local vector. + + // Get start address of the shared memory for current warp. + SPtr ptrPerWarp = ptrC + subgroupIndex * ShMemInfo.SharedMemSizeInVectorMatC; + + [ForceUnroll] + for (int i = 0; i < TileInfo.NCoopMatRow; i ++) + { + [ForceUnroll] + for (int j = 0; j < TileInfo.NCoopMatColumn; j ++) + { + int index = i * TileInfo.NCoopMatColumn + j; + matC[index].Store(ptrPerWarp + j * CMShape.CoopMatCSizeInVector, + TileInfo.HeightInVectorTileC); + } + + if (Bias) + { + storeVectorFromShB(ptrC, i, subgroupIndex, outputVector); + } + else + { + storeVectorFromShB(ptrC, i, subgroupIndex, outputVector); + } + + // wati until all threads in the warp finish reading shared memory and storing to local vector. + GroupMemoryBarrierWithWaveSync(); + } + + return outputVector; + } +} + +// Cooperative matrix is only supported by CUDA and SPIR-V +// WaveTangledVector is a vector type that emulates the Cooperative Vector type by using Cooperative Matrix feature which is +// supported by CUDA and SPIR-V. +[require(cooperative_matrix, subgroup_basic)] +public struct WaveTangledVector : IVector + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public typealias Differential = WaveTangledVector; + + public static const int Size = N; + public no_diff ShMemPool shMemPool; + + private typealias DTypeMatC = half; + + // TODO: This is just an easiest solution to make the alignment work. But the disadvantage is wasting of registers. + // A better solution is that we can implement a "special" alignment rule for the vectorized reader. + // Normally, the alignment rule is that one uint4 can pack 8 half type elements, so we want our internal data + // is always 8 elements aligned. But we can have a "byte-aligned" rule such that we just need our data is 16 bytes aligned. + // So for example, float[4] is also considered as aligned. We can just pack 4 elements into a uint4, the remaining 4 elements + // just fill with 0. + // Since we always use half type for A and B, we want to follow the alignment requirement of half type. + internal static const uint ElementCountPerVector = sizeof(uint4) / sizeof(DTypeMatC); + internal static const int Uint4AlignedInputSize = ((N + (ElementCountPerVector - 1)) / ElementCountPerVector) * ElementCountPerVector; + + // [DerivativeMember(Differential.data)] + internal T[Uint4AlignedInputSize] data; + public int getCount() { return N; } + + public __init() { data = {}; } + + public __init(T value) + { + [ForceUnroll] + for (int i = 0; i < N; i++) + { + this.data[i] = value; + } + + cleanPaddingData(); + } + + public __init(T[Size] inData) + { + [ForceUnroll] + for (int i = 0; i < N; i++) + { + this.data[i] = inData[i]; + } + + cleanPaddingData(); + } + + internal __init(T[Uint4AlignedInputSize] inData) + { + this.data = inData; + } + + public __init(This other) { this.data = other.data; } + + public __init>(InputArray inData) + { + [ForceUnroll] + for (int i = 0; i < N; i++) + this.data[i] = inData[i]; + + cleanPaddingData(); + } + + [ForceInline] + [mutating] + internal void cleanPaddingData() + { + const int elementCountPerUint4 = sizeof(uint4) / sizeof(DTypeMatC); + const int alignedSize = ((N + (elementCountPerUint4 - 1)) / elementCountPerUint4) * elementCountPerUint4; + + [ForceUnroll] + for (int i = N; i < alignedSize; i++) + { + this.data[i] = T(0.0f); + } + } + + public __subscript(int index) -> T + { + [ForceInline] + get { return this.data[index]; } + + [ForceInline] + set { this.data[index] = newValue; } + } + + [ForceInline] + private OutputVector linearTransformOnTarget( + Address weightAddress, + Optional
biasAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where OutputVector : IVector + { + typealias MMA = MMAHelper; + SPtr shA = shMemPool.getPointer(); + SPtr shB = shA + MMA.ShMemInfo.SharedMemSizeInVectorMatA; + SPtr shC = shB; + const int AlignedOutSize = MMA.TileInfo.Uint4AlignedM; + let outputArray = MMA.mma( data, shA, shB, shC, weightAddress, biasAddress); + return OutputVector(outputArray); + } + + [ForceInline] + private static void linearTransformBwdOnTarget( + inout DifferentialPair dthis, + DifferentialPtrPair
dWeightAddress, + Optional> biasAddress, + OutputVector.Differential doutput) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where OutputVector : IVector + where OutputVector.Differential : IVector + { + typealias MMA = MMAHelper; + + SPtr shA = dthis.p.shMemPool.getPointer(); + SPtr shB = shA + MMA.ShMemInfo.SharedMemSizeInVectorMatA; + SPtr shC = shB; + + // In backward, output size is K dimension. + const int AlignedOutSize = MMA.TileInfo.Uint4AlignedK; + const int AlignedInputSize = MMA.TileInfo.Uint4AlignedM; + + // This.Differential is the derivative of the input vector, which is the output + // of the mma operation. + // dIn = W^T * dOut; +#if 1 + let outArray = MMA.mma( doutput, shA, shB, shC, dWeightAddress.p, none); + This.Differential dInput = This.Differential(outArray); + dthis = DifferentialPair(dthis.p, dInput); + + // dW = dOut * input^T + MMA.outerProductAccumulate( shA, shB, doutput, dthis.p.data, dWeightAddress.d); +#else + let dInput = MMA.mma( doutput, shA, shB, shC, dWeightAddress.p, none); + dthis = DifferentialPair(dthis.p, dInput); + + MMA.outerProductAccumulate( shA, shB, doutput, dthis.p, dWeightAddress.d); +#endif + + if (Bias) + { + const int subgroupIndex = getWaveId(); + MMA.sumReduceRows(shA, doutput, subgroupIndex, biasAddress.value.d); + } + } + + // Linear transformation without bias + [ForceInline] + [BackwardDerivative(linearTransformBwd)] + public OutputVector linearTransform( + Address weightAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + { + __target_switch + { + case cuda: + return no_diff linearTransformOnTarget(weightAddress, none); + case spirv: + return no_diff linearTransformOnTarget(weightAddress, none); + } + } + + // Backward of linear transformation without bias + [ForceInline] + static void linearTransformBwd( + inout DifferentialPair dthis, + DifferentialPtrPair
dWeightAddress, + OutputVector.Differential doutput) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + where OutputVector.Differential : IVector + { + Optional> biasAddress = {}; + __target_switch + { + case cuda: + linearTransformBwdOnTarget(dthis, dWeightAddress, biasAddress, doutput); + case spirv: + linearTransformBwdOnTarget(dthis, dWeightAddress, biasAddress, doutput); + } + } + + [ForceInline] + [BackwardDerivative(linearTransformBwd)] + public OutputVector linearTransform( + Address weightAddress, Address biasAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + { + __target_switch + { + case cuda: + return no_diff linearTransformOnTarget(weightAddress, biasAddress); + case spirv: + return no_diff linearTransformOnTarget(weightAddress, biasAddress); + } + } + + // Backward of linear transformation with bias + [ForceInline] + static void linearTransformBwd( + inout DifferentialPair dthis, + DifferentialPtrPair
dWeightAddress, + DifferentialPtrPair
dBiasAddress, + OutputVector.Differential doutput) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + where OutputVector.Differential : IVector + { + __target_switch + { + case cuda: + linearTransformBwdOnTarget(dthis, dWeightAddress, dBiasAddress, doutput); + case spirv: + linearTransformBwdOnTarget(dthis, dWeightAddress, dBiasAddress, doutput); + } + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/activations.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/activations.slang new file mode 100644 index 0000000..8b67be5 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/activations.slang @@ -0,0 +1,220 @@ +implementing neural; + +__include iactivation; + +/** +Identity activation: returns input unchanged. +*/ +public struct IdentityActivation : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + return input; + } +} + +/** +ReLU activation: max(x, 0). +*/ +public struct ReLU : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + output[i] = max(input[i], T(0)); + return output; + } +} + +/** +LeakyReLU activation: x < 0 ? alpha*x : x + +Construct with the leak coefficient alpha (typically 0.01). +*/ +public struct LeakyReLU : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + /// Leak coefficient for negative inputs. + public T alpha; + + /// Constructor with optional alpha value (defaults to 0.01). + public __init(T alpha = T(0.01)) + { + this.alpha = alpha; + } + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + { + let x = input[i]; + output[i] = (x < T(0)) ? alpha * x : x; + } + return output; + } +} + +/** +Sigmoid activation: 1 / (1 + exp(-x)) +*/ +public struct Sigmoid : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + { + let x = input[i]; + output[i] = T(1) / (T(1) + exp(-x)); + } + return output; + } +} + +/** +Tanh activation. +*/ +public struct TanhActivation : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + output[i] = tanh(input[i]); + return output; + } +} + +/** +Exp activation: exp(x) +*/ +public struct ExpActivation : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + output[i] = exp(input[i]); + return output; + } +} + +/** +Sine activation: sin(x) +*/ +public struct SineActivation : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + output[i] = sin(input[i]); + return output; + } +} + +/** +SiLU (Sigmoid Linear Unit) activation, also known as Swish: x * sigmoid(x) +*/ +public struct SiLU : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + { + let x = input[i]; + output[i] = x / (T(1) + exp(-x)); // x * sigmoid(x) + } + return output; + } +} + +/** +QuickGELU activation: x * sigmoid(1.702 * x) + +A fast approximation of GELU (Gaussian Error Linear Unit). +*/ +public struct QuickGELU : IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public __init() {} + + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector + { + Vector output = Vector(); + [ForceUnroll] + for (int i = 0; i < Vector.Size; i++) + { + let x = input[i]; + output[i] = x / (T(1) + exp(T(-1.702) * x)); // x * sigmoid(1.702 * x) + } + return output; + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/bindless-storage.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/bindless-storage.slang new file mode 100644 index 0000000..7d723e5 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/bindless-storage.slang @@ -0,0 +1,284 @@ +implementing neural; + +/** +Bindless address type with pointer-like semantics. +Wraps a buffer handle and base index to provide array-like access. +*/ +public struct BindlessAddress : IPointerLikeAddress + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public typealias Differential = BindlessAddress; + + internal RWStructuredBuffer.Handle handle; + internal uint baseIndex; + + public __init(RWStructuredBuffer.Handle handle) + { + this.handle = handle; + this.baseIndex = 0; + } + + public __subscript(uint index)->T + { + [nonmutating] + get { return handle[baseIndex + index]; } + + [mutating] + set { handle[baseIndex + index] = newValue; } + } + + [ForceInline] + [require(hlsl, sm_6_6)] + internal void atomicAddForHLSL(uint index, T value) + { + T compareValue; + bool success = false; + do + { + compareValue = handle[baseIndex + index]; + T newValue = compareValue + value; + success = __atomic_compare_exchange(handle[baseIndex + index], compareValue, newValue) == compareValue; + } while (!success); + } + + [ForceInline] + [require(cuda_glsl_hlsl_metal_spirv, sm_6_6)] + public void atomicAdd(uint index, T value) + { + __target_switch + { + case hlsl: + atomicAddForHLSL(index, value); + default: + __atomic_reduce_add(handle[baseIndex + index], value); + } + } + + [ForceInline] + public void atomicAdd(uint index, vector value) + { + __target_switch + { + case cuda: + // On CUDA, use packed vector atomic for types that support it (half2, bfloat16x2). + let scalarPtr = &handle[baseIndex + index]; + let vecPtr = reinterpret*>(scalarPtr); + __atomic_reduce_add(vecPtr[0], value); + default: + // On other targets, fall back to two scalar atomic adds. + atomicAdd(index, value[0]); + atomicAdd(index + 1, value[1]); + } + } + + public This getOffset(int elements) + { + uint newBaseIndex = baseIndex + elements; + + This address = This(handle); + address.baseIndex = newBaseIndex; + return address; + } + + [ForceInline] + internal uint4 readUint4(int offsetIndex) + where DstType : __BuiltinFloatingPointType + where DstType.Differential == DstType + { + uint4 value; + accessUint4.Handle, IsAligned, ActualBoundary>( + handle, int(baseIndex), int(baseIndex) + offsetIndex, value); + return value; + } + + [ForceInline] + internal void writeUint4Atomic(int offsetIndex, uint4 value) + where SrcType : __BuiltinFloatingPointType + where SrcType.Differential == SrcType + { + accessUint4.Handle, IsAligned, ActualBoundary>( + handle, int(baseIndex), int(baseIndex) + offsetIndex, value); + } +} + +public struct PointerAddress : IPointerLikeAddress + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + public typealias Differential = PointerAddress; + + T* ptr; + + public __init(T* ptr) + { + this.ptr = ptr; + } + + public __subscript(uint index)->T + { + [nonmutating] + get { return ptr[index]; } + + [mutating] + set { ptr[index] = newValue; } + } + + public This getOffset(int elements) + { + return This(ptr + elements); + } + + [ForceInline] + [require(hlsl, sm_6_6)] + internal void atomicAddForHLSL(uint index, T value) + { + T compareValue; + bool success = false; + do + { + compareValue = ptr[index]; + T newValue = compareValue + value; + success = __atomic_compare_exchange(ptr[index], compareValue, newValue) == compareValue; + } while (!success); + } + + [ForceInline] + [require(cuda_glsl_hlsl_metal_spirv, sm_6_6)] + public void atomicAdd(uint index, T value) + { + __target_switch + { + case hlsl: + atomicAddForHLSL(index, value); + default: + __atomic_reduce_add(ptr[index], value); + } + } + + [ForceInline] + public void atomicAdd(uint index, vector value) + { + __target_switch + { + case cuda: + // On CUDA, use packed vector atomic for types that support it (half2, bfloat16x2). + let vecPtr = reinterpret*>(ptr + index); + __atomic_reduce_add(vecPtr[0], value); + default: + // On other targets, fall back to two scalar atomic adds. + atomicAdd(index, value[0]); + atomicAdd(index + 1, value[1]); + } + } + + [ForceInline] + internal uint4 readUint4(int offsetIndex) + where DstType : __BuiltinFloatingPointType + where DstType.Differential == DstType + { + uint4 value; + accessUint4( + ptr, 0, offsetIndex, value); + return value; + } + + [ForceInline] + internal void writeUint4Atomic(int offsetIndex, uint4 value) + where SrcType : __BuiltinFloatingPointType + where SrcType.Differential == SrcType + { + accessUint4( + ptr, 0, offsetIndex, value); + } +} + +// We currently don't support UserPointer as an `IDifferentiablePtrType`, the issue is tracked in +// https://github.com/shader-slang/slang/issues/8834. +// So we define an internal extension for now, once we can resolve the issue, we can make it public. +internal extension Ptr : IPointerLikeAddress + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + internal typealias Differential = Ptr; + + internal __init(Ptr ptr) + { + this = ptr; + } + + internal __subscript(uint index)->T + { + [nonmutating] + get { return this[index]; } + + [mutating] + set { this[index] = newValue; } + } + + internal This getOffset(int elements) + { + return This(this + elements); + } + + [require(hlsl, sm_6_6)] + internal void atomicAddForHLSL(uint index, T value) + { + T compareValue; + bool success = false; + do + { + compareValue = this[index]; + T newValue = compareValue + value; + success = __atomic_compare_exchange(this[index], compareValue, newValue) == compareValue; + } while (!success); + } + + [ForceInline] + [require(cuda_glsl_hlsl_metal_spirv, sm_6_6)] + internal void atomicAdd(uint index, T value) + { + __target_switch + { + case hlsl: + atomicAddForHLSL(index, value); + default: + __atomic_reduce_add(this[index], value); + } + } + + [ForceInline] + internal void atomicAdd(uint index, vector value) + { + __target_switch + { + case cuda: + let vecPtr = reinterpret*>(this + index); + __atomic_reduce_add(vecPtr[0], value); + default: + atomicAdd(index, value[0]); + atomicAdd(index + 1, value[1]); + } + } + + [ForceInline] + internal uint4 readUint4(int offsetIndex) + where DstType : __BuiltinFloatingPointType + where DstType.Differential == DstType + { + uint4 value; + accessUint4( + this, 0, offsetIndex, value); + return value; + } + + [ForceInline] + internal void writeUint4Atomic(int offsetIndex, uint4 value) + where SrcType : __BuiltinFloatingPointType + where SrcType.Differential == SrcType + { + accessUint4( + this, 0, offsetIndex, value); + } +} + diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/common-def.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/common-def.slang new file mode 100644 index 0000000..b45a403 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/common-def.slang @@ -0,0 +1,7 @@ +// Common definitions for the neural module + +#ifdef UNIT_TEST +#define VISIBILITY_LEVEL public +#else +#define VISIBILITY_LEVEL internal +#endif diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/hash-function.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/hash-function.slang new file mode 100644 index 0000000..74805e5 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/hash-function.slang @@ -0,0 +1,152 @@ +implementing neural; + +#include "common-def.slang" + +VISIBILITY_LEVEL typealias uvec = Array; + +VISIBILITY_LEVEL enum HashType : uint32_t +{ + Prime, + CoherentPrime, + ReversedPrime, + Rng, + BaseConvert, +} + +VISIBILITY_LEVEL struct Pcg32 +{ + static const uint64_t DefaultState = 0x853c49e6748fea9bULL; + static const uint64_t DefaultStream = 0xda3e39cb94b95bdbULL; + static const uint64_t Mult = 0x5851f42d4c957f2dULL; + + uint64_t state; + uint64_t inc; + + VISIBILITY_LEVEL __init(uint64_t initstate, uint64_t initseq = 1) + { + state = 0; + inc = (initseq << 1) | 1; + nextUint(); + state += initstate; + nextUint(); + } + + [mutating] + VISIBILITY_LEVEL uint32_t nextUint() + { + uint64_t oldstate = state; + state = oldstate * Mult + inc; + uint32_t xorshifted = uint32_t(((oldstate >> 18) ^ oldstate) >> 27); + uint32_t rot = uint32_t(oldstate >> 59); + return (xorshifted >> rot) | (xorshifted << ((~rot + 1) & 31)); + } + + [mutating] + VISIBILITY_LEVEL void advance(int64_t delta) + { + uint64_t curMult = Mult; + uint64_t curPlus = inc; + uint64_t accMult = 1; + uint64_t accPlus = 0; + + uint64_t d = uint64_t(delta); + while (d > 0) + { + if ((d & 1) != 0) + { + accMult *= curMult; + accPlus = accPlus * curMult + curPlus; + } + curPlus = (curMult + 1) * curPlus; + curMult *= curMult; + d /= 2; + } + state = accMult * state + accPlus; + } +} + +// LCG hash: XORs position values multiplied by prime factors +[ForceInline] +VISIBILITY_LEVEL uint32_t lcgHash(uvec posGrid, uint32_t primes[PrimeCount]) +{ + uint32_t result = 0; + [ForceUnroll] + for (int i = 0; i < Dimensions; ++i) + { + result ^= posGrid[i] * primes[i]; + } + return result; +} + +[ForceInline] +VISIBILITY_LEVEL uint32_t primeHash(uvec posGrid) +{ + uint32_t factors[7] = { 1958374283u, 2654435761u, 805459861u, 3674653429u, 2097192037u, 1434869437u, 2165219737u }; + return lcgHash(posGrid, factors); +} + +[ForceInline] +VISIBILITY_LEVEL uint32_t coherentPrimeHash(uvec posGrid) +{ + uint32_t factors[7] = { 1u, 2654435761u, 805459861u, 3674653429u, 2097192037u, 1434869437u, 2165219737u }; + return lcgHash(posGrid, factors); +} + +[ForceInline] +VISIBILITY_LEVEL uint32_t reversedPrimeHash(uvec posGrid) +{ + uint32_t factors[7] = { 2165219737u, 1434869437u, 2097192037u, 3674653429u, 805459861u, 2654435761u, 1958374283u }; + return lcgHash(posGrid, factors); +} + +// Base conversion hash (used in permuto-encoding) +[ForceInline] +VISIBILITY_LEVEL uint32_t baseConvertHash(uvec posGrid) +{ + uint32_t k = 0; + [ForceUnroll] + for (int dim = 0; dim < Dimensions; ++dim) + { + k += posGrid[dim]; + k *= 2531011u; + } + return k; +} + +// RNG hash using PCG32 +[ForceInline] +VISIBILITY_LEVEL uint32_t rngHash(uvec posGrid, uint32_t seed = 1337) +{ + static const int BitsPerDim = 64 / Dimensions; + uint64_t step = 0; + + [ForceUnroll] + for (int i = 0; i < Dimensions; ++i) + { + step ^= uint64_t(posGrid[i]) << (i * BitsPerDim); + } + + Pcg32 rng = Pcg32(seed); + rng.advance(int64_t(step)); + return rng.nextUint(); +} + +[ForceInline] +VISIBILITY_LEVEL uint32_t gridHash(uvec positionGrid) +{ + switch (Type) + { + case HashType.Prime: + return primeHash(positionGrid); + case HashType.CoherentPrime: + return coherentPrimeHash(positionGrid); + case HashType.ReversedPrime: + return reversedPrimeHash(positionGrid); + case HashType.Rng: + return rngHash(positionGrid); + case HashType.BaseConvert: + return baseConvertHash(positionGrid); + default: + return 0; + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/iactivation.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/iactivation.slang new file mode 100644 index 0000000..be875fa --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/iactivation.slang @@ -0,0 +1,28 @@ +implementing neural; + +/** +Activation function interface for neural network operations. +Defines a differentiable mapping from an input vector to an output vector of the same shape. + +Activations that require parameters (e.g., LeakyReLU's alpha) store them as member fields. +Parameterless activations (e.g., ReLU, Sigmoid) can be used with the default constructor. + +@param T Scalar element type (float/half/double). +@category neural +*/ +public interface IActivation + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + /// Default constructor. Required so that activations are explicitly default-constructed + /// rather than zero-initialized when used with `Activation()` in layer constructors. + __init(); + + /// Apply activation function element-wise. + /// @param input Input vector. + /// @return Output vector with activation applied. + [NoDiffThis] + [Differentiable] + public Vector eval(Vector input) + where Vector : IVector; +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/iencoder.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/iencoder.slang new file mode 100644 index 0000000..3a56447 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/iencoder.slang @@ -0,0 +1,36 @@ +implementing neural; +#include "common-def.slang" + +public interface IStaticEncoder + where T : __BuiltinFloatingPointType + where T.Differential == T + where InArray : IArrayAccessor + where OutArray : IArrayAccessor +{ + public associatedtype HyperParameters; + + [Differentiable] + public OutArray encode(in InArray input); +} + +public interface ITrainableEncoder + where T : __BuiltinFloatingPointType + where T.Differential == T + where InArray : IArrayAccessor + where InArray : IDifferentiable + where OutArray : IArrayAccessor + where OutArray : IDifferentiable +{ + public associatedtype HyperParameters; + + [Differentiable] + public OutArray encode
(in InArray input, Address parametersAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress; +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/ilayer.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/ilayer.slang new file mode 100644 index 0000000..d9eab0e --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/ilayer.slang @@ -0,0 +1,28 @@ +implementing neural; + +/** +Layer interface (compile-time, GPU-friendly). +This interface is intended to be used as a *generic constraint* (no existential storage), +so it does not imply dynamic dispatch. + +@category neural +*/ +public interface ILayer + where T : __BuiltinFloatingPointType + where T.Differential == T + where Layout : IStorageLayout + where InputVector : IVector + where OutputVector : IVector + where Activation : IActivation +{ + /// Forward evaluation: y = f(x). + /// Address is passed as parameter to enable autodiff gradient routing. + /// @param input Input vector. + /// @param weightAddress Weight address (pointer-like). + /// @param biasAddress Bias address (pointer-like). Pass `none` if no bias. + /// @return Output vector. + [Differentiable] + public OutputVector eval(InputVector input, A weightAddress, Optional biasAddress = none) + where A : IPointerLikeAddress + where A.Differential : IPointerLikeAddress; +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/inline-vector.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/inline-vector.slang new file mode 100644 index 0000000..12bee00 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/inline-vector.slang @@ -0,0 +1,194 @@ +implementing neural; + +/** +Concrete implementation of IVector storing elements inline (on stack/registers). +InlineVector stores all elements in a fixed-size array, making it suitable for +small vectors that can fit in registers or stack memory. Supports automatic differentiation +for gradient computation in neural networks. +@param T The element type +@param N The vector size (compile-time constant). +@remarks Type constraints: +- `T` must conform to `__BuiltinFloatingPointType` (float, double, half, etc.) +- `T.Differential` must conform to `__BuiltinFloatingPointType` for automatic differentiation +@category neural +*/ +public struct InlineVector : IVector + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + /// The differential type for automatic differentiation. + public typealias Differential = InlineVector; + + /// The compile-time size of the vector. + public static const int Size = N; + + public int getCount() {return N;} + /** + Internal storage for vector elements. + @remarks Marked as derivative member to enable automatic differentiation. + */ + [DerivativeMember(Differential.data)] + internal T[N] data; + + /// Default constructor - initializes all elements to zero. + public __init() { data = {}; } + + /** + Scalar broadcast constructor - fills all elements with the same value. + @param[in] value The value to broadcast to all elements. + */ + public __init(T value) { + [ForceUnroll] + for (int i = 0; i < N; i++) + data[i] = value; + } + + /** + Array constructor - initializes from an array. + @param[in] data Array of N elements to initialize the vector. + */ + public __init(T[Size] data) { this.data = data; } + + /** + Copy constructor. + @param[in] other The vector to copy from. + */ + public __init(This other) { this.data = other.data; } + + public __init>(InputArray data) + { + static_assert(data.getCount() >= N, "The size of the input array must match the vector size"); + [ForceUnroll] + for (int i = 0; i < N; i++) + this.data[i] = data[i]; + } + + /** + Element access operator. + @param[in] index The element index (0-based). + @return Reference to the element at the given index. + */ + public __subscript(int index) -> T + { + [ForceInline] + [Differentiable] + get() { return this.data[index]; } + + [ForceInline] + [Differentiable] + set() { this.data[index] = newValue; } + } + + // Linear transformation without bias + [BackwardDerivative(linearTransformBwd)] + public OutputVector linearTransform( + Address weightAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + { + var output = OutputVector(); + + // output = W * input + [MaxIters(OutputVector.Size)] + for (int row = 0; row < OutputVector.Size; row++) + { + // get the address of each row of the weight matrix + let rowAddr = weightAddress.getOffset(row * N); + [ForceUnroll] + for (int col = 0; col < N; col++) + { + output[row] += data[col] * rowAddr[col]; + } + } + return output; + } + + // Linear transformation with bias (Bindless storage) + [BackwardDerivative(linearTransformBwd)] + public OutputVector linearTransform( + Address weightAddress, + Address biasAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + { + // Reuse the unbias matmul method + OutputVector output = this.linearTransform(weightAddress); + + [ForceUnroll] + for (int i = 0; i < OutputVector.Size; i++) + output[i] = output[i] + biasAddress[i]; + + return output; + } + + // Backward of linear transformation without bias (Bindless storage) + static public void linearTransformBwd( + inout DifferentialPair dthis, + DifferentialPtrPair
dparameters, + OutputVector.Differential doutput) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + where OutputVector.Differential : IVector + { + // dInput = dW^T * dOutput + This.Differential d = {}; + [MaxIters(OutputVector.Size)] + for (int j = 0; j < OutputVector.Size; j++) + { + let dy = doutput[j]; + [ForceUnroll] + for (int i = 0; i < N; i++) + { + T.Differential prod = T.Differential.dmul(dparameters.p[i + j * N], dy); + d[i] = T.Differential.dadd(d[i], prod); + } + } + + // Derivative of the weights is the outer product of the input and the output differential + // dW = dOutput * Input^T + [MaxIters(OutputVector.Size)] + for (int row = 0; row < OutputVector.Size; row++) + { + let rowAddr = dparameters.d.getOffset(row * N); + T.Differential dy = doutput[row]; + [ForceUnroll] + for (int col = 0; col < N; col++) + { + let x = dthis.p[col]; + T.Differential prod = T.Differential.dmul(x, dy); + rowAddr.atomicAdd(col, prod); + } + } + + dthis = DifferentialPair(dthis.p, d); + } + + // Backward of linear transformation with bias (Bindless storage) + static public void linearTransformBwd( + inout DifferentialPair dthis, + DifferentialPtrPair
dWeightAddress, + DifferentialPtrPair
dBiasAddress, + OutputVector.Differential doutput) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector + { + // Reuse the unbias backward method + linearTransformBwd(dthis, dWeightAddress, doutput); + + let biasOffset = dBiasAddress.d.getOffset(0); + // dBias = dOutput + [ForceUnroll] + for (int i = 0; i < OutputVector.Size; i++) + { + biasOffset.atomicAdd(i, doutput[i]); + } + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/istorages.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/istorages.slang new file mode 100644 index 0000000..6b35079 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/istorages.slang @@ -0,0 +1,77 @@ +implementing neural; + +public enum LayoutType : uint32_t +{ + Linear = 0, +} + +internal interface IStorageLayout +{ + internal static const LayoutType Layout; +} + +public struct LinearLayout : IStorageLayout +{ + internal static const LayoutType Layout = LayoutType.Linear; +} + +/** +Interface for pointer-like addressing with direct subscript access. +Provides array-like access patterns for storage backends that support pointer arithmetic. +@param T The element type. +@remarks Type constraints: +- `T` must conform to `__BuiltinFloatingPointType` (float, double, half, etc.) +- `T.Differential` must conform to `__BuiltinFloatingPointType` for automatic differentiation +@see `BindlessBufferStorage.BindlessAddress` +@category neural +*/ +public interface IPointerLikeAddress : IDifferentiablePtrType + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + /** + Array-style element access. + @param[in] index The element index. + @return Reference to the element at the given index. + */ + public __subscript(uint index) -> T { get; set; } + + /** + Computes an offset pointer. + @param[in] elements Number of elements to offset by. + @return The offset pointer. + */ + public This getOffset(int elements); + + /** + Atomically adds a value at an index. + @param[in] index The element index. + @param[in] value The value to add. + */ + [require(cuda_glsl_hlsl_metal_spirv, sm_6_6)] + public void atomicAdd(uint index, T value); + + /** + Atomically adds a vector of 2 values using packed atomic operations where available. + @param[in] index The element index (must be aligned to 2 elements). + @param[in] value The vector of 2 values to add. + */ + public void atomicAdd(uint index, vector value); + + /** + Reads sequential elements starting from the given offset address, packed into a uint4. + */ + [ForceInline] + internal uint4 readUint4(int offsetIndex) + where DstType : __BuiltinFloatingPointType + where DstType.Differential == DstType; + + /** + Atomically writes unpacked uint4 values back to storage. + */ + [ForceInline] + internal void writeUint4Atomic(int offsetIndex, uint4 value) + where SrcType : __BuiltinFloatingPointType + where SrcType.Differential == SrcType; + +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/ivector.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/ivector.slang new file mode 100644 index 0000000..79ea2fb --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/ivector.slang @@ -0,0 +1,97 @@ +implementing neural; + +/** +Generic vector interface for neural network operations. +Provides a differentiable vector abstraction supporting automatic differentiation +and linear algebra operations for neural network computations. +@param T The element type (must be a floating-point type). +@param N The vector size (compile-time constant). +@remarks Type constraints: +- `T` must conform to `__BuiltinFloatingPointType` (float, double, half, etc.) +- `T.Differential` must conform to `__BuiltinFloatingPointType` for automatic differentiation +@see `InlineVector` +@category neural +*/ +public interface IVector : IDifferentiable, IArrayAccessor + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + /// The compile-time size of the vector. + public static const int Size; + + /// The differential type for automatic differentiation. + /// @remarks Ensures the differential is also a vector with the same structure. + public associatedtype Differential : IVector; + + /// Default constructor - initializes vector to zero. + public __init(); + + /** + Scalar broadcast constructor - fills all elements with the same value. + @param[in] value The value to broadcast to all elements. + */ + public __init(T value); + + /** + Array constructor - initializes from an array. + @param[in] data Array of N elements to initialize the vector. + */ + public __init(T[This.Size] data); + + public __init>(InputArray data); + + /** + Copy constructor. + @param[in] other The vector to copy from. + */ + public __init(This other); + + /** + Evaluates a linear transformation: output = W * this. + Uses pointer-like addressing for direct access to weight parameters. + @param Address The address type with pointer-like access. + @param Layout The storage layout type. + @param OutputVector The output vector type. + @param[in] weightAddress The address of the weight matrix. + The weight matrix is stored in a contiguous block of memory, the size + of the weight matrix is in `OutputVector.Size` rows, and `N` columns. + @return The result of the linear transformation, `result = W * this`, whose size is `OutputVector.Size`. + @remarks Type constraints: + - `Address` must conform to `IPointerLikeAddress` + - `Address.Differential` must conform to `IPointerLikeAddress` + - `OutputVector` must conform to `IVector` + */ + [Differentiable] + public OutputVector linearTransform(Address weightAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector; + + /** + Evaluates a linear transformation: output = W * this + bias. + Performs matrix-vector multiplication with bias addition. + Uses pointer-like addressing for direct access to weight and bias parameters. + @param Address The address type with pointer-like access. + @param Layout The storage layout type. + @param OutputVector The output vector type. + @param[in] weightAddress The address of the weight matrix. + The weight matrix is stored in a contiguous block of memory, the size + of the weight matrix is in `OutputVector.Size` rows, and `N` columns. + @param[in] biasAddress The address of the bias vector. + The bias vector is stored in a contiguous block of memory, the size + of the bias vector is `OutputVector.Size`. + @return The result of the linear transformation, `result = W * this + bias`, whose size is `OutputVector.Size`. + @remarks Type constraints: + - `Address` must conform to `IPointerLikeAddress` + - `Address.Differential` must conform to `IPointerLikeAddress` + - `OutputVector` must conform to `IVector` + */ + [Differentiable] + public OutputVector linearTransform( + Address weightAddress, Address biasAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + where Layout : IStorageLayout + where OutputVector : IVector; +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/layers.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/layers.slang new file mode 100644 index 0000000..ef666c7 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/layers.slang @@ -0,0 +1,90 @@ +implementing neural; + +/** +A fully-connected (feed-forward) neural network layer that computes `y = Activation(W*x + b)`. + +`FFLayer` represents a single linear transformation followed by an activation function, +suitable for building multi-layer perceptrons (MLPs) and similar architectures. + +## Usage + +1. **Construction:** Create a layer: + ``` + let layer = FFLayer>(); + ``` + +2. **Forward pass:** Call `eval()` with address and input: + ``` + let output = layer.eval
(input, weightAddr, biasAddr); + ``` + +3. **Training (backward pass):** Use autodiff with `DifferentialPtrPair`: + ``` + var addrPair = DifferentialPtrPair
(addr, gradAddr); + bwd_diff(computeOutput)(addrPair, inputPair, layer, dOutput); + ``` + +## Parameter Layout + +Parameters are packed as a contiguous block in storage: + +- **weights:** `Out * In` scalars, row-major by output row: `W[row * In + col]` +- **bias (optional):** `Out` scalars immediately following weights +*/ +public struct FFLayer< + T, + InputVector, + OutputVector, + Layout, + Activation, + let HasBias : bool = true +> + : ILayer + where T : __BuiltinFloatingPointType + where T.Differential == T + where Layout : IStorageLayout + where InputVector : IVector + where OutputVector : IVector + where Activation : IActivation +{ + public static const int ParameterCount = + OutputVector.Size * InputVector.Size + (HasBias ? OutputVector.Size : 0); + + /// Activation function instance (stores any activation-specific parameters). + internal Activation activation; + + /// Constructor. + /// @param act Activation function instance (defaults to default-constructed Activation). + public __init(Activation act = Activation()) + { + activation = act; + } + + public static int nextOffset(int baseOffset) + { + return baseOffset + ParameterCount; + } + + /// Forward evaluation: y = Activation(W*x + b). + /// @param input Input vector. + /// @param weightAddr Weight address (pointer-like). + /// @param biasAddr Bias address (pointer-like). Pass `none` if no bias. + /// @return Output vector after linear transform and activation. + [Differentiable] + [ForceInline] + public OutputVector eval(InputVector input, A weightAddr, Optional biasAddr = none) + where A : IPointerLikeAddress + where A.Differential : IPointerLikeAddress + { + OutputVector y; + if(HasBias) + { + y = input.linearTransform(weightAddr, biasAddr.value); + } + else + { + y = input.linearTransform(weightAddr); + } + return activation.eval(y); + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang new file mode 100644 index 0000000..7a66070 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang @@ -0,0 +1,38 @@ +/** +Neural network primitives for Slang. +This module provides differentiable primitive data structures and operations for implementing +inline MLP (Multilayer Perceptron) in Slang shaders. It includes vector types, storage abstractions, +activation functions, optimizers, and automatic differentiation support for training small inline +neural networks on the GPU. + +@remarks EXPERIMENTAL: This module is under active design and may change significantly +or be removed in future versions. DO NOT USE IN PRODUCTION. + +@category neural + +Features: +- Differentiable vector types (IVector, InlineVector) +- Pointer-like address abstraction (IPointerLikeAddress) +- Automatic differentiation support +- Linear transformations with optional bias +- Atomic operations for gradient accumulation +- Permutohedral lattice encoding (PermutoEncoder) +*/ +[ExperimentalModule] +module neural; + +__include "ivector"; +__include "inline-vector"; +__include "istorages"; +__include "bindless-storage"; +__include "accelerate-vector-coopmat"; +__include "vectorized-reader"; +__include "shared-memory-pool"; +__include "hash-function"; +__include "permuto-encoder"; +__include "iencoder"; +// Frontend APIs built on the primitives above +__include "iactivation"; +__include "activations"; +__include "ilayer"; +__include "layers"; diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang-module b/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang-module new file mode 100644 index 0000000..2222137 Binary files /dev/null and b/lib/All/slang/lib/slang-standard-module-2026.3.1/neural.slang-module differ diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/permuto-encoder.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/permuto-encoder.slang new file mode 100644 index 0000000..03f750d --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/permuto-encoder.slang @@ -0,0 +1,372 @@ +implementing neural; +#include "common-def.slang" + +// ============================================================================= +// Permuto Encoder +// ============================================================================= + +public struct PermutoEncoder : ITrainableEncoder + where T : __BuiltinFloatingPointType + where T.Differential == T + where InArray : IArrayAccessor, IDifferentiable + where OutArray : IArrayAccessor, IDifferentiable +{ + /// Precomputed per-level information. + public struct PerLevelInfo + { + public uint currentLevelIndex; + public uint offsetOfFeatureTable; // Offset into feature table for this level (in number of features) + public uint featureTableSize; // Hashmap size for this level + public float scale; // Scale for this level + public float scalesPerDim[Dimensions]; + public float shiftsPerDim[Dimensions]; + } + + VISIBILITY_LEVEL struct Params + { + VISIBILITY_LEVEL float maxLevel; // It's maxLevelRatio * MaxLevels, where maxLevelRatio is a user defined ratio + VISIBILITY_LEVEL PerLevelInfo levelInfo; // Contains scale, offset, hashmap size, and per-dim scales/shifts + } + + public struct HyperParameters + { + public float maxLevel; + public PerLevelInfo[MaxLevels] levelInfo; + }; + + internal HyperParameters params; + public __init(HyperParameters params) + { + this.params = params; + } + + // ========================================================================= + // Permutohedral Lattice Helper Functions + // ========================================================================= + + /// Computes the permutohedral lattice index using base conversion hash. + /// @param key The lattice coordinate. + /// @param hashmapSize The size of the hashmap. + /// @return The index into the parameter array. + static uint permutoIndex(uvec key, uint hashmapSize) + { + return baseConvertHash(key) % hashmapSize; + } + + /// Elevates a D-dimension vector to (D+1)-dimension homogeneous vector on hyperplane H_d. + /// The sum of the components of `elevated` is zero, ensuring it's within hyperplane H_d. + /// The magnitudes of the components of `elevated` are similar to each other. + /// @param pos Input position [Dimensions]. + /// @param scalesPerDim Per-dimension scaling factors [Dimensions]. + /// @param shiftsPerDim Per-dimension shifts [Dimensions]. + /// @param elevated Output elevated coordinates [Dimensions+1]. + [Differentiable] + static void permutoElevate( + InArray pos, + no_diff in float scalesPerDim[Dimensions], + no_diff in float shiftsPerDim[Dimensions], + out float elevated[Dimensions + 1]) + where InArray : IArrayAccessor + where InArray : IDifferentiable + { + float sum = 0.0f; + [ForceUnroll] + for (int dim = Dimensions - 1; dim >= 0; --dim) + { + float cf = (__realCast(pos[dim]) + shiftsPerDim[dim]) * scalesPerDim[dim]; + elevated[dim + 1] = sum - float(dim + 1) * cf; + sum += cf; + } + elevated[0] = sum; + } + + /// Finds the closest remainder-0 point and computes the rank ordering. + /// @param elevated The elevated coordinates [Dimensions+1]. + /// @param rem0 Output: coordinates of remainder-0 point [Dimensions+1]. + /// @param rank Output: rank ordering [Dimensions+1]. + /// Note: Not differentiable since outputs are int (no gradient needed). + static void permutoFindRem0( + float elevated[Dimensions + 1], + out int rem0[Dimensions + 1], + out int rank[Dimensions + 1]) + { + rank = {}; + // Find the closest remainder-0 point through rounding + int sum = 0; + [ForceUnroll] + for (uint dim = 0; dim <= Dimensions; ++dim) + { + // Using xxx*(1.0f/N) is faster than xxx/N + float v = elevated[dim] * (1.0f / float(Dimensions + 1)); + float up = ceil(v) * float(Dimensions + 1); + float down = floor(v) * float(Dimensions + 1); + if (up - elevated[dim] < elevated[dim] - down) + { + rem0[dim] = int(up); + } + else + { + rem0[dim] = int(down); + } + sum += rem0[dim]; + } + sum /= int(Dimensions + 1); + + // Find the simplex we are in and store it in rank + // (where rank describes what position coordinate i has in the sorted order) + [ForceUnroll] + for (uint dim = 0; dim < Dimensions; ++dim) + { + float di = elevated[dim] - float(rem0[dim]); + [MaxIters(Dimensions)] + for (uint otherDim = dim + 1; otherDim <= Dimensions; ++otherDim) + { + if (di < elevated[otherDim] - float(rem0[otherDim])) + { + rank[dim]++; + } + else + { + rank[otherDim]++; + } + } + } + + // If the point doesn't lie on the plane (sum != 0) bring it back + [ForceUnroll] + for (uint dim = 0; dim <= Dimensions; ++dim) + { + rank[dim] += sum; + if (rank[dim] < 0) + { + rank[dim] += int(Dimensions + 1); + rem0[dim] += int(Dimensions + 1); + } + else if (rank[dim] > int(Dimensions)) + { + rank[dim] -= int(Dimensions + 1); + rem0[dim] -= int(Dimensions + 1); + } + } + } + + /// Computes the barycentric coordinates for permutohedral interpolation. + /// See p.10 in [Adams et al. 2010]. + /// @param elevated The elevated coordinates [Dimensions+1]. + /// @param rem0 The remainder-0 point coordinates [Dimensions+1]. + /// @param rank The rank ordering [Dimensions+1]. + /// @param barycentric Output: barycentric coordinates [Dimensions+2]. + [Differentiable] + static void permutoBarycentric( + float elevated[Dimensions + 1], + int rem0[Dimensions + 1], + int rank[Dimensions + 1], + out float barycentric[Dimensions + 2]) + { + // Compute the barycentric coordinates + barycentric = {}; + [ForceUnroll] + for (uint dim = 0; dim <= Dimensions; ++dim) + { + float delta = (elevated[dim] - float(rem0[dim])) * (1.0f / float(Dimensions + 1)); + int idxPlus = int(Dimensions) - rank[dim]; + int idxMinus = int(Dimensions + 1) - rank[dim]; + barycentric[idxPlus] += delta; + barycentric[idxMinus] -= delta; + } + // Wrap around + barycentric[0] += 1.0f + barycentric[Dimensions + 1]; + } + + // ========================================================================= + // Feature Reading and Encoding + // ========================================================================= + + /// Reads feature values at a given lattice position from the feature table. + /// @param levelBaseOffset Base offset into the feature table for this level (in number of elements). + [BackwardDerivative(readFeatureValueBwd)] + static void readFeatureValue
( + Address featureTableAddress, + uint levelBaseOffset, + uint hashmapSize, + uvec key, + out T result[FeatureDimensionPerEntry]) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + { + uint index = levelBaseOffset + permutoIndex(key, hashmapSize) * FeatureDimensionPerEntry; + + [ForceUnroll] + for (uint f = 0; f < FeatureDimensionPerEntry; ++f) + { + result[f] = featureTableAddress[index + f]; + } + } + + static void readFeatureValueBwd
( + DifferentialPtrPair
featureTableAddress, + uint levelBaseOffset, + uint hashmapSize, + uvec key, + T.Differential[FeatureDimensionPerEntry] result) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + { + uint index = levelBaseOffset + permutoIndex(key, hashmapSize) * FeatureDimensionPerEntry; + + [ForceUnroll] + for (uint f = 0; f < FeatureDimensionPerEntry; ++f) + { + featureTableAddress.d.atomicAdd(index + f, result[f]); + } + } + + /// Main forward pass: encodes positions using the permutohedral lattice for a single level. + /// Writes results to the appropriate offset in the full output array. + /// + /// @param params Encoding parameters containing: + /// - maxLevel: Maximum level to use (maxLevelRatio * MaxLevels) + /// - levelInfo: Per-level info (currentLevelIndex, offsetOfFeatureTable, featureTableSize, scale, scalesPerDim, shiftsPerDim) + /// @param position Input position (Dimensions floats) + /// @param featureTableAddress Pointer-like address to the feature table for all levels + /// @param encodedFeatures Output array of size MaxLevels * FeatureDimensionPerEntry. Results are written at offset currentLevelIndex * FeatureDimensionPerEntry. + [Differentiable] + VISIBILITY_LEVEL static void encodePerLevel
( + no_diff in Params params, + InArray position, + Address featureTableAddress, + inout OutArray encodedFeatures) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + { + // Compute offset into output array for this level + uint outputOffset = params.levelInfo.currentLevelIndex * FeatureDimensionPerEntry; + + // Initialize this level's output to zero + [ForceUnroll] + for (uint f = 0; f < FeatureDimensionPerEntry; ++f) + { + encodedFeatures[outputOffset + f] = T(0); + } + + // If level is greater than maxLevel, output zero padding (already initialized above) + if (float(params.levelInfo.currentLevelIndex) >= params.maxLevel + 1e-3f) + { + return; + } + + // Use precomputed level-specific parameters + uint levelOffset = params.levelInfo.offsetOfFeatureTable; + uint hashmapSize = params.levelInfo.featureTableSize; + + // Compute the base offset for this level's features (as integer, not address offset). + // We pass this as an integer to readFeatureValue so that the DifferentialPtrPair + // stays at the base address — both .p and .d remain correctly paired. + uint levelBaseOffset = levelOffset * FeatureDimensionPerEntry; + + // Elevate D-dimension vector to (D+1)-dimension homogeneous vector on hyperplane H_d + float elevated[Dimensions + 1]; + permutoElevate(position, params.levelInfo.scalesPerDim, params.levelInfo.shiftsPerDim, elevated); + + // Find the closest remainder-0 and rank + int rem0[Dimensions + 1]; + int rank[Dimensions + 1]; + permutoFindRem0(elevated, rem0, rank); + + // Compute the barycentric coordinates + float barycentric[Dimensions + 2]; + permutoBarycentric(elevated, rem0, rank, barycentric); + + // Interpolate the values using barycentric weights + uvec key; + [ForceUnroll] + for (uint k = 0; k <= Dimensions; ++k) // For each remainder-k vertex + { + // Compute the coordinates of the remainder-k vertex + [ForceUnroll] + for (uint dim = 0; dim < Dimensions; ++dim) + { + key[dim] = uint(rem0[dim] + int(k)); + if (rank[dim] > int(Dimensions - k)) + { + key[dim] -= uint(Dimensions + 1); + } + } + + // Read feature value at this vertex + T featureVal[FeatureDimensionPerEntry]; + readFeatureValue(featureTableAddress, levelBaseOffset, hashmapSize, key, featureVal); + + // Accumulate with barycentric weight + float weight = barycentric[k]; + [ForceUnroll] + for (uint f = 0; f < FeatureDimensionPerEntry; ++f) + { + encodedFeatures[outputOffset + f] += T(weight) * featureVal[f]; + } + } + } + + [Differentiable] + public OutArray encode
(in InArray input, Address parametersAddress) + where Address : IPointerLikeAddress + where Address.Differential : IPointerLikeAddress + { + OutArray encodedFeatures = OutArray(); + + Params levelParams; + levelParams.maxLevel = params.maxLevel; + + [ForceUnroll] + for (uint level = 0; level < MaxLevels; ++level) + { + levelParams.levelInfo = params.levelInfo[level]; + encodePerLevel
(levelParams, input, parametersAddress, encodedFeatures); + } + + return encodedFeatures; + } + + /// Helper function to compute the PerLevelInfo (offset, hashmapSize, etc.) for a given level. + /// The hashmap size is 2^Log2HashmapSize for all levels. + /// The offset for each level is currentLevel * hashmapSize. + /// + /// @param currentLevel The current level being processed + /// @param baseScale Base scale for the encoding + /// @param log2PerLevelScale Log2 of the per-level scale factor + /// @param seed Seed for the random shift generation + /// @param levelInfo Output: the computed level info with all parameters + VISIBILITY_LEVEL static void prepareLevelInfo( + in uint currentLevel, + in float baseScale, + in float log2PerLevelScale, + in uint seed, + out PerLevelInfo levelInfo) + { + static const uint HashmapSize = 1u << Log2HashmapSize; + levelInfo.currentLevelIndex = currentLevel; + levelInfo.featureTableSize = HashmapSize; + levelInfo.offsetOfFeatureTable = currentLevel * HashmapSize; + levelInfo.scale = baseScale * exp2(float(currentLevel) * log2PerLevelScale); + + // Initialize RNG for random shifts (different levels should draw differently) + Pcg32 rng = Pcg32(seed); + rng.advance(int64_t(currentLevel * Dimensions)); + + [ForceUnroll] + for (uint dim = 0; dim < Dimensions; ++dim) + { + levelInfo.scalesPerDim[dim] = levelInfo.scale * rsqrt(float((dim + 1) * (dim + 2))); + // Convert uint32 to float in [0, 1) then scale to [-5, 5) + float randFloat = float(rng.nextUint()) * (1.0f / 4294967296.0f); + levelInfo.shiftsPerDim[dim] = randFloat * 10.0f - 5.0f; + } + } +} diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/shared-memory-pool.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/shared-memory-pool.slang new file mode 100644 index 0000000..e27d365 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/shared-memory-pool.slang @@ -0,0 +1,274 @@ +// Unit test mode is used for unit testing the tiled MMA implementation. +// So we can test this single file by providing -DUNIT_TEST to the compiler. +implementing neural; + +#include "common-def.slang" + +#define Max(A, B) ((A) > (B) ? (A) : (B)) + +internal typealias SPtr = Ptr; + +internal interface ISharedMemoryPool +{ + internal static SPtr getPointer(); +} + +public interface ISharedMemorySize +{ + public static const uint Bytes; +} + +public struct SharedMemoryPool : ISharedMemoryPool +{ + public static const uint sizeInBytes = ShMemSize.Bytes; + internal static groupshared uint4 data[sizeInBytes / sizeof(uint4)]; + VISIBILITY_LEVEL static SPtr getPointer() + { + return __getAddress(data[0]); + } +} + +internal struct SharedMemoryUsage + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + static const bool IsTraining = ExeMode == ExecutionMode.Training; + typealias TileInfoNormal = TileInfo; + typealias TileInfoTransposed = TileInfo; + typealias CMShape = CoopMatShape; + + // Shared memory A is used to load Tile A. The Size Tile A is determined by the height of matrix A and width of CoopMatA. + // The possible shapes of matrix A can be: + // 1. M x K in A * B -> inference (TransposeA = false) + // 2. K x M in A^T * B -> training (TransposeA = true) + // 3. M x N in outer product of dOut and input. -> training (TransposeA = false) + // In the inference mode, tile A size is always [M x CoopMatA_Width]. + // In the training mode, tile A size is either [M x CoopMatA_Width] or [K x CoopMatA_Width], so we need to choose the max value + static const int SharedMemSizeInVectorMatA = !IsTraining ? + (TileInfoNormal.HeightInElementsTileA * CMShape.COLUMN_A) / CMShape.ElementCountPerVector : + (Max(TileInfoNormal.HeightInElementsTileA, TileInfoTransposed.HeightInElementsTileA) * CMShape.COLUMN_A) / CMShape.ElementCountPerVector; + + // Shared memory B is used to load Tile B. The Size Tile B is determined by the height of CoopMatB and width of Tile B. + // The possible shapes of matrix B in inference mode can be: + // 1. K x N in A * B -> inference + // 2. M x N in A^T * B -> training + // 3. N x K in outer product of dOut and input. -> training + // In the inference mode, tile B size is always [CoopMatB_Height x N]. + // In the training mode, tile B size is either [CoopMatB_Height x N] or [CoopMatB_Height x K], so we need to choose the max value. + + // InputSize is K. + static const int TileBWidthForOuterProduct = ((InputSize + CMShape.COLUMN_B - 1) / CMShape.COLUMN_B) * CMShape.COLUMN_B; + static const int SharedMemSizeInVectorMatB = !IsTraining ? + ((TileInfoNormal.WidthInElementsTileB * CMShape.ROW_B) / CMShape.ElementCountPerVector) : + ((Max(TileInfoNormal.WidthInElementsTileB, TileBWidthForOuterProduct) * CMShape.ROW_B) / CMShape.ElementCountPerVector); + + // Shared memory C is used to store the result of CoopMatC. The size is determened by height of CoopMatC and width of Tile C. + // The possible shapes matrix C can only be: + // 1. M x N in A * B + // 2. K x N in A^T * B + // 3. M x K in outer product of dOut and input. + // Therefore the Tile C size is same as the Tile B size. However, the data type of Tile B can only be half, while tile C can be + // both float and half, so we need to take that into account. + static const int SharedMemSizeInVectorMatC = SharedMemSizeInVectorMatB * sizeof(T) / sizeof(half); +} + +public struct SharedMemorySize0 + : ISharedMemorySize + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + typealias ShMemInfo = SharedMemoryUsage; + + // Notice that in the actual implementation, we always reuse shared memory for Tile B and Tile C because they are always used at + // different stages of the computation, and they have the same size. + public static const uint Bytes = + (ShMemInfo.SharedMemSizeInVectorMatA + (ShMemInfo.SharedMemSizeInVectorMatC) * SubgroupCount) * sizeof(uint4); +} + +// The following code is a macro-based implementation of the shared memory size calculation. +// It is used to calculate the shared memory size for a given number of hidden layers. +// The challenge here is that the size of the shared memory has to be compile time constant, however +// slang doesn't really have const_expr function. So the only way to get the compile time constant +// is to use meta programming to generate the code that can be evaluated at compile time. +// Here the algorithm is very simple where we just use divide and conquer to calculate the shared memory size. +// Firstly, we define the base case `SharedMemorySize0` that give an input and output of a layer, we calculate the shared memory size for this layer. +// Then we can define larger number of layers by using the divide and conquer strategy. The reason to use Macro here +// is just to reduce the mount of code that we need to write. But under the hood, the macro will be expanded to: +// `SharedMemorySize1` to `SharedMemorySize15`. + +// Take an example: +// ``` +// DEFINE_SHMEM_SIZE(3, 1, 1, PARAM_3, ARG_3_L, ARG_3_R) +// ``` +// This will be expanded to: +// ``` +// public struct SharedMemorySize3 SHMEM_WHERE { +// internal static const uint a = SharedMemorySize1.Bytes; +// internal static const uint b = SharedMemorySize1.Bytes; +// public static const uint Bytes = Max(a, b); +// } +// ``` +// Where `LN` and `RN` determine how we divide input sequence of layers into two parts. + +// TODO: We shouldn't need such sophisticated meta-programming to achieve this once we have const_expr function +// or we can provide more advanced variadic generic parameters support such as First(...)/Rest(...), so that +// we can define the SharedMemorySize as variadic generic struct instead of these pre-defined generics. +// +// We note that this implementation is not the most efficient way to calculate the shared memory size, because +// we can first find out the max layer size, and then do the remaining calculation. But since this computation is +// not done at run time, so we don't need to worry about the performance, and we can reuse other data structure we +// already have, so it's easiest way to implement this. + + +#define UNPACK(...) __VA_ARGS__ + +// 2. Define your helper macros +#define SHMEM_WHERE where T : __BuiltinFloatingPointType where T.Differential == T +#define SHMEM_BASE T, Target, ExeMode, SubgroupSize, SubgroupCount + +// 3. The Core Macro - note the removed spaces around UNPACK +#define DEFINE_SHMEM_SIZE(N, LN, RN, ARGS, L_VALS, R_VALS) \ + public struct SharedMemorySize##N \ + : ISharedMemorySize \ + SHMEM_WHERE \ + { \ + internal static const uint a = SharedMemorySize##LN.Bytes; \ + internal static const uint b = SharedMemorySize##RN.Bytes; \ + public static const uint Bytes = Max(a, b); \ + } + +#define PARAM_1 (uint S0, uint S1, uint S2) +#define ARG_1 (S0, S1, S2) +#define ARG_1_L (S0, S1) +#define ARG_1_R (S1, S2) + +#define PARAM_2 (UNPACK PARAM_1, uint S3) +#define ARG_2 (UNPACK ARG_1, S3) +#define ARG_2_L (S0, S1, S2) +#define ARG_2_R (S2, S3) + +#define PARAM_3 (UNPACK PARAM_2, uint S4) +#define ARG_3 (UNPACK ARG_2, S4) +#define ARG_3_L (S0, S1, S2) +#define ARG_3_R (S2, S3, S4) + +DEFINE_SHMEM_SIZE(1, 0, 0, PARAM_1, ARG_1_L, ARG_1_R) +DEFINE_SHMEM_SIZE(2, 1, 0, PARAM_2, ARG_2_L, ARG_2_R) +DEFINE_SHMEM_SIZE(3, 1, 1, PARAM_3, ARG_3_L, ARG_3_R) + +// from 4 to 7 +#define PARAM_4 (UNPACK PARAM_3, uint S5) +#define ARG_4 (UNPACK ARG_3, S5) +#define ARG_4_R (S4, S5) + +#define PARAM_5 (UNPACK PARAM_4, uint S6) +#define ARG_5 (UNPACK ARG_4, S6) +#define ARG_5_R (UNPACK ARG_4_R, S6) + +#define PARAM_6 (UNPACK PARAM_5, uint S7) +#define ARG_6 (S0, S1, S2, S3, S4, S5, S6, S7) +#define ARG_6_R (UNPACK ARG_5_R, S7) + +#define PARAM_7 (UNPACK PARAM_6, uint S8) +#define ARG_7 (UNPACK ARG_6, S8) +#define ARG_7_R (UNPACK ARG_6_R, S8) + +DEFINE_SHMEM_SIZE(4, 3, 0, PARAM_4, ARG_3, ARG_4_R) +DEFINE_SHMEM_SIZE(5, 3, 1, PARAM_5, ARG_3, ARG_5_R) +DEFINE_SHMEM_SIZE(6, 3, 2, PARAM_6, ARG_3, ARG_6_R) +DEFINE_SHMEM_SIZE(7, 3, 3, PARAM_7, ARG_3, ARG_7_R) + +// from 8 to 15 +#define PARAM_8 (UNPACK PARAM_7, uint S9) +#define ARG_8 (UNPACK ARG_7, S9) +#define ARG_8_R (S8, S9) + +#define PARAM_9 (UNPACK PARAM_8, uint S10) +#define ARG_9 (UNPACK ARG_8, S10) +#define ARG_9_R (UNPACK ARG_8_R, S10) + +#define PARAM_10 (UNPACK PARAM_9, uint S11) +#define ARG_10 (UNPACK ARG_9, S11) +#define ARG_10_R (UNPACK ARG_9_R, S11) + +#define PARAM_11 (UNPACK PARAM_10, uint S12) +#define ARG_11 (UNPACK ARG_10, S12) +#define ARG_11_R (UNPACK ARG_10_R, S12) + +#define PARAM_12 (UNPACK PARAM_11, uint S13) +#define ARG_12 (UNPACK ARG_11, S13) +#define ARG_12_R (UNPACK ARG_11_R, S13) + +#define PARAM_13 (UNPACK PARAM_12, uint S14) +#define ARG_13 (UNPACK ARG_12, S14) +#define ARG_13_R (UNPACK ARG_12_R, S14) + +#define PARAM_14 (UNPACK PARAM_13, uint S15) +#define ARG_14 (UNPACK ARG_13, S15) +#define ARG_14_R (UNPACK ARG_13_R, S15) + +#define PARAM_15 (UNPACK PARAM_14, uint S16) +#define ARG_15 (UNPACK ARG_14, S16) +#define ARG_15_R (UNPACK ARG_14_R, S16) + +DEFINE_SHMEM_SIZE(8, 7, 0, PARAM_8, ARG_7, ARG_8_R) +DEFINE_SHMEM_SIZE(9, 7, 1, PARAM_9, ARG_7, ARG_9_R) +DEFINE_SHMEM_SIZE(10, 7, 2, PARAM_10, ARG_7, ARG_10_R) +DEFINE_SHMEM_SIZE(11, 7, 3, PARAM_11, ARG_7, ARG_11_R) +DEFINE_SHMEM_SIZE(12, 7, 4, PARAM_12, ARG_7, ARG_12_R) +DEFINE_SHMEM_SIZE(13, 7, 5, PARAM_13, ARG_7, ARG_13_R) +DEFINE_SHMEM_SIZE(14, 7, 6, PARAM_14, ARG_7, ARG_14_R) +DEFINE_SHMEM_SIZE(15, 7, 7, PARAM_15, ARG_7, ARG_15_R) + +// Slang doesn't support generic overloading, so we cannot provide the one generic with different number of parameters. +public struct SharedMemorySize + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + #define STRIP_PARENS(x) STRIP_PARENS_I x + #define STRIP_PARENS_I(...) __VA_ARGS__ + + public typealias OfLayer1 = SharedMemorySize0; + public typealias OfLayer2 = SharedMemorySize1; + public typealias OfLayer3 = SharedMemorySize2; + public typealias OfLayer4 = SharedMemorySize3; + public typealias OfLayer5 = SharedMemorySize4; + public typealias OfLayer6 = SharedMemorySize5; + public typealias OfLayer7 = SharedMemorySize6; + public typealias OfLayer8 = SharedMemorySize7; + public typealias OfLayer9 = SharedMemorySize8; + public typealias OfLayer10 = SharedMemorySize9; + public typealias OfLayer11 = SharedMemorySize10; + public typealias OfLayer12 = SharedMemorySize11; + public typealias OfLayer13 = SharedMemorySize12; + public typealias OfLayer14 = SharedMemorySize13; + public typealias OfLayer15 = SharedMemorySize14; + public typealias OfLayer16 = SharedMemorySize15; +} + +#if 0 + +// We should implement First/Rest syntax to something like this. +interface IVal { + static const int Value; +} +SharedMemorySize +{ + static const uint SharedMemSizeInBytes = + max(SharedMemorySize, SharedMemorySize); +} + +// Slang doesn't support generic overloading, therefore we cannot provide the pre-defined generics that adds different number of HiddenSize. + +public struct SharedMemorySize + where T : __BuiltinFloatingPointType + where T.Differential == T +{ + typealias ShMemInfo = SharedMemoryUsage; + + // Notice that in the actual implementation, we always reuse shared memory for Tile B and Tile C because they are always used at + // different stages of the computation, and they have the same size. + static const uint SharedMemSizeInBytes = + (ShMemInfo.SharedMemSizeInVectorMatA + (ShMemInfo.SharedMemSizeInVectorMatB) * SubgroupCount) * sizeof(uint4); +} +#endif diff --git a/lib/All/slang/lib/slang-standard-module-2026.3.1/vectorized-reader.slang b/lib/All/slang/lib/slang-standard-module-2026.3.1/vectorized-reader.slang new file mode 100644 index 0000000..ef53105 --- /dev/null +++ b/lib/All/slang/lib/slang-standard-module-2026.3.1/vectorized-reader.slang @@ -0,0 +1,231 @@ +implementing neural; + +#include "common-def.slang" + + +internal interface IArrayAccessor +{ + internal void atomicAdd(int index, T value) + { + static_assert(false, "atomicAdd is not supported for IArrayAccessor"); + } + + __subscript(int index)->T + { + get; + set; + } +} + +internal extension RWStructuredBuffer.Handle : IArrayAccessor +{ + [ForceInline] + override internal void atomicAdd(int index, T value) + { + __atomic_reduce_add(this[index], value); + } +} + +internal extension Ptr : IArrayAccessor +{ + internal __subscript(int index) -> T + { + [ForceInline] + get { return this[index]; } + + [ForceInline] + set { this[index] = newValue; } + } + + [ForceInline] + override internal void atomicAdd(int index, T value) + { + __atomic_reduce_add(this[index], value); + } +} + +internal extension Array : IArrayAccessor +{ + internal __subscript(int index) -> T + { + [ForceInline] + get { return this[index]; } + + [ForceInline] + set { this[index] = newValue; } + } +} + +VISIBILITY_LEVEL enum AccessOp : uint32_t +{ + READ, + WRITE, + ACCUMULATE, + ATOMIC_ADD, +} + +#define COMMON_TYPE_CONSTRAINTS \ + where T : __BuiltinFloatingPointType \ + where U : __BuiltinFloatingPointType \ + where BufferType : IArrayAccessor + +[ForceInline] +internal static void readOneElement(BufferType buffer, int bufferIdx, int elementIdx, inout uint result) + COMMON_TYPE_CONSTRAINTS +{ + const uint shift = BitsShiftPerRead * elementIdx; + T convertedValue; + convertedValue = __realCast(buffer[bufferIdx]); + switch (NBytes) + { + case 1: + result |= uint(bit_cast(convertedValue)) << shift; + break; + case 2: + result |= uint(bit_cast(convertedValue)) << shift; + break; + case 4: + result |= uint(bit_cast(convertedValue)) << shift; + break; + default: + static_assert(false, "Unsupported data type T"); + } +} + +[ForceInline] +internal static void writeOneElement(inout BufferType buffer, int bufferIdx, int elementIdx, uint value) + COMMON_TYPE_CONSTRAINTS +{ + const uint shift = BitsShiftPerWrite * elementIdx; + U convertedValue; + switch (NBytes) + { + case 1: + convertedValue = __realCast(bit_cast((uint8_t)(value >> shift))); + break; + case 2: + convertedValue = __realCast(bit_cast((uint16_t)(value >> shift))); + break; + case 4: + convertedValue = __realCast(bit_cast((uint)(value >> shift))); + break; + default: + static_assert(false, "Unsupported data type T"); + } + + switch (Op) + { + case AccessOp.WRITE: + buffer[bufferIdx] = convertedValue; + break; + case AccessOp.ACCUMULATE: + buffer[bufferIdx] = buffer[bufferIdx] + convertedValue; + break; + case AccessOp.ATOMIC_ADD: + buffer.atomicAdd(bufferIdx, convertedValue); + break; + default: + static_assert(false, "Unsupported access operation"); + } +} + +[ForceInline] +internal static void accessUint4Aligned(inout BufferType buffer, int startIndex, inout uint4 value) + COMMON_TYPE_CONSTRAINTS +{ + const int nBytes = sizeof(T); + const int WritePerElement = 4 / nBytes; + const int BitsShiftPerWrite = 32 / WritePerElement; + + if (Op == AccessOp.READ) + value = uint4(0, 0, 0, 0); + + [ForceUnroll] + for (int i = 0; i < 4; i++) + { + [ForceUnroll] + for (int j = 0; j < WritePerElement; j++) + { + int index = startIndex + i * WritePerElement + j; + switch (Op) + { + case AccessOp.READ: + readOneElement(buffer, index, j, value[i]); + break; + case AccessOp.WRITE: + case AccessOp.ACCUMULATE: + case AccessOp.ATOMIC_ADD: + writeOneElement(buffer, index, j, value[i]); + break; + default: + static_assert(false, "Unsupported access operation"); + } + } + } +} + +[ForceInline] +internal void accessUint4(BufferType buffer, int baseIndex, int startIndex, inout uint4 value) + COMMON_TYPE_CONSTRAINTS +{ + if (IsAligned) + { + // Call the aligned version of readUint4 which is branchless. + accessUint4Aligned(buffer, startIndex, value); + return; + } + + if (Op == AccessOp.READ) + value = uint4(0, 0, 0, 0); + + // T is the type of source (read) or destination (write) data type. We will always pack few elements into a uint4. + // So T will determine how many elements we can pack into a uint4. + // If U is different from T, we will first convert from U to T (in read operation) or from T to U (in write operation). + // But U will not determined how many elements we can read or write, only T will. + const int nBytes = sizeof(T); + const int ReadPerElement = 4 / nBytes; + const int BitsShiftPerRead = 32 / ReadPerElement; + + const int x = (startIndex - baseIndex) % Stride; + + // end address of this read [address+length-1] + const int endAddress = (x + 4 * ReadPerElement - 1); + + // this is same as paddingCount = endAddress < AlignedStride ? 0 : AlignedStride - endAddress + 1 + const int paddingCount = max(0, endAddress - Stride + 1); + const int elementsToRead = (4 * ReadPerElement) - paddingCount; + + [ForceUnroll] + for (int i = 0; i < 4; i++) + { + int offset = i * ReadPerElement; + [ForceUnroll] + for (int j = 0; j < ReadPerElement; j++) + { + // 4 * ReadPerElement is the total number of elements we can read from the buffer. + // paddingCount is the number of the elements we need to pad. + // e.g. if ReadPerElement is 2, paddingCount is 4.Because (4 * 2 - 4 == 4), so we can + // just stop reading when offset bigger than 3. + offset += j; + if (offset >= elementsToRead) + { + return; + } + + int index = (startIndex + offset); + switch (Op) + { + case AccessOp.READ: + readOneElement(buffer, index, j, value[i]); + break; + case AccessOp.WRITE: + case AccessOp.ACCUMULATE: + case AccessOp.ATOMIC_ADD: + writeOneElement(buffer, index, j, value[i]); + break; + default: + static_assert(false, "Unsupported access operation"); + } + } + } +} diff --git a/lib/All/slang/share/doc/slang/64bit-type-support.md b/lib/All/slang/share/doc/slang/64bit-type-support.md new file mode 100644 index 0000000..5f54f66 --- /dev/null +++ b/lib/All/slang/share/doc/slang/64bit-type-support.md @@ -0,0 +1,156 @@ +Slang 64-bit Type Support +========================= + +## Summary + +* Not all targets support 64 bit types, or all 64 bit types + * 64 bit integers generally require later APIs/shader models +* When specifying 64 bit floating-point literals *always* use the type suffixes (ie `L`) +* An integer literal will be interpreted as 64 bits if it cannot fit in a 32 bit value. +* GPU target/s generally do not support all double intrinsics + * Typically missing are trascendentals (sin, cos etc), logarithm and exponential functions + * CUDA is the exception supporting nearly all double intrinsics +* D3D + * D3D targets *appear* to support double intrinsics (like sin, cos, log etc), but behind the scenes they are actually being converted to float + * When using D3D12, it is best to use DXIL if you use double because there are some serious issues around double and DXBC +* VK will produce an error in validation if a double intrinsic is used it does support (which is most of them) +* Vector and Matrix types have even spottier than scalar intrinsic support across targets + +Overview +======== + +The Slang language supports 64 bit built in types. Such as + +* `double` +* `uint64_t` +* `int64_t` + +This also applies to vector and matrix versions of these types. + +Unfortunately if a specific target supports the type or the typical HLSL intrinsic functions (such as sin/cos/max/min etc) depends very much on the target. + +Special attention has to be made with respect to literal 64 bit types. By default float literals if they do not have an explicit suffix are assumed to be 32 bit. There is a variety of reasons for this design choice - the main one being around by default behavior of getting good performance. The suffixes required for 64 bit types are as follows + +``` +// double - 'l' or 'L' + +double a = 1.34e-200L; +// WRONG!: This is the same as b = double(float(1.34e-200)) which will be 0. Will produce a warning. +double b = 1.34e-200; + +// int64_t - 'll' or 'LL' (or combination of upper/lower) + +int64_t c = -5436365345345234ll; + +int64_t e = ~0LL; // Same as 0xffffffffffffffff + +// uint64_t - 'ull' or 'ULL' (or combination of upper/lower) + +uint64_t g = 0x8000000000000000ull; + +uint64_t i = ~0ull; // Same as 0xffffffffffffffff +uint64_t j = ~0; // Equivalent to 'i' because uint64_t(int64_t(~int32_t(0))); +``` + +These issues are discussed more on issue [#1185](https://github.com/shader-slang/slang/issues/1185) + +The type of a decimal non-suffixed integer literal is the first integer type from the list [`int`, `int64_t`] +which can represent the specified literal value. If the value cannot fit, the literal is represented as an `uint64_t` +and a warning is given. +The type of a hexadecimal non-suffixed integer literal is the first type from the list [`int`, `uint`, `int64_t`, `uint64_t`] +that can represent the specified literal value. A non-suffixed integer literal will be 64 bit if it cannot fit in 32 bits. +``` +// Same as int64_t a = int(1), the value can fit into a 32 bit integer. +int64_t a = 1; + +// Same as int64_t b = int64_t(2147483648), the value cannot fit into a 32 bit integer. +int64_t b = 2147483648; + +// Same as int64_t c = uint64_t(18446744073709551615), the value is larger than the maximum value of a signed 64 bit +// integer, and is interpreted as an unsigned 64 bit integer. Warning is given. +uint64_t c = 18446744073709551615; + +// Same as uint64_t = int(0x7FFFFFFF), the value can fit into a 32 bit integer. +uint64_t d = 0x7FFFFFFF; + +// Same as uint64_t = int64_t(0x7FFFFFFFFFFFFFFF), the value cannot fit into an unsigned 32 bit integer but +// can fit into a signed 64 bit integer. +uint64_t e = 0x7FFFFFFFFFFFFFFF; + +// Same as uint64_t = uint64_t(0xFFFFFFFFFFFFFFFF), the value cannot fit into a signed 64 bit integer, and +// is interpreted as an unsigned 64 bit integer. +uint64_t f = 0xFFFFFFFFFFFFFFFF; +``` + +Double support +============== + +Target | Compiler/Binary | Double Type | Intrinsics | Notes +---------|------------------|----------------|-----------------------|----------- +CPU | | Yes | Yes | 1 +CUDA | Nvrtx/PTX | Yes | Yes | 1 +D3D12 | DXC/DXIL | Yes | Small Subset | 4 +Vulkan | GlSlang/Spir-V | Yes | Partial | 2 +D3D11 | FXC/DXBC | Yes | Small Subset | 4 +D3D12 | FXC/DXBC | Yes | Small Subset | 3, 4 + +1) CUDA and CPU support most intrinsics, with the notable exception currently of matrix invert +2) In terms of lack of general intrinsic support, the restriction is described in https://www.khronos.org/registry/spir-v/specs/1.0/GLSL.std.450.html + +The following intrinsics are available for Vulkan + +`fmod` (as %), `rcp`, `sign`, `saturate`, `sqrt`, `rsqrt`, `frac`, `ceil`, `floor`, `trunc`, `abs`, `min`, `max`, `smoothstep`, `lerp`, `clamp`, `step` and `asuint`. + +These are tested in the test `tests/hlsl-intrinsic/scalar-double-vk-intrinsic.slang`. + +What is missing are transedentals, expX, logX. + +Note that GlSlang does produce Spir-V that contains double intrinsic calls for the missing intrinsics, the failure happens when validating the Spir-V + +``` +Validation: error 0: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object: VK_NULL_HANDLE (Type = 0) | SPIR-V module not valid: GLSL.std.450 Sin: expected Result Type to be a 16 or 32-bit scalar or vector float type + %57 = OpExtInst %double %1 Sin %56 +``` + +3) That if a RWStructuredBuffer is used on D3D12 with DXBC, and a double is written, it can lead to incorrect behavior. Thus it is recommended not to use double with dxbc, but to use dxil to keep things simple. A test showing this problem is `tests/bugs/dxbc-double-problem.slang`. The test `tests/hlsl-intrinsic/scalar-double-simple.slang` shows not using a double resource, doubles do appear to work on D3D12 DXBC. + +4) If you compile code using double and intrinsics through Slang at first blush it will seem to work. Assuming there are no errors in your code, your code will even typically appear to work correctly. Unfortunately what is really happening is the backend compiler (fxc or dxc) compiler is narrowing double to float and then using float intrinsics. It typically generates a warning when this happens, but unless there is an error in your code you will not see these warnings because dxc doesn't appear to have a mechanism to return warnings if there isn't an error. This is why everything appears to work - but actually any intrinsic call is losing precision silently. + +Note on dxc by default Slang disables warnings - warnings need to be enabled to see the narrowing warnings. + +There is another exception around the use of % - if you do this with double it will return an error saying on float is supported. + +It appears that no intrinsics are available for double with fxc. + +On dxc the following intrinsics are available with double:: + +`rcp`, `sign`, `saturate`, `abs`, `min`, `max`, `clamp`, `asuint`. + +These are tested in the test `tests/hlsl-intrinsic/scalar-double-d3d-intrinsic.slang`. + +There is no support for transcendentals (`sin`, `cos` etc) or `log`/`exp`. More surprising is that `sqrt`, `rsqrt`, `frac`, `ceil`, `floor`, `trunc`, `step`, `lerp`, `smoothstep` are also not supported. + +uint64_t and int64_t Support +============================ + +Target | Compiler/Binary | u/int64_t Type | Intrinsic support | Notes +---------|------------------|----------------|--------------------|-------- +CPU | | Yes | Yes | +CUDA | Nvrtx/PTX | Yes | Yes | +Vulkan | GlSlang/Spir-V | Yes | Yes | +D3D12 | DXC/DXIL | Yes | Yes | 1 +D3D11 | FXC/DXBC | No | No | 2 +D3D12 | FXC/DXBC | No | No | 2 + +1) The [sm6.0 docs](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12) describe only supporting uint64_t, but dxc says int64_t is supported in [HLSL 2016](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Language-Versions). Tests show that this is indeed the case. + +2) uint64_t support requires https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12, so DXBC is not a target. + +The intrinsics available on `uint64_t` type are `abs`, `min`, `max`, `clamp` and `countbits`. +The intrinsics available on `int64_t` type are `abs`, `min`, `max`, `clamp` and `countbits`. + +GLSL +==== + +GLSL/Spir-v based targets do not support 'generated' intrinsics on matrix types. For example 'sin(mat)' will not work on GLSL/Spir-v. + diff --git a/lib/All/slang/share/doc/slang/README.md b/lib/All/slang/share/doc/slang/README.md new file mode 100644 index 0000000..ca6a3dd --- /dev/null +++ b/lib/All/slang/share/doc/slang/README.md @@ -0,0 +1,35 @@ +Slang Documentation +=================== + +This directory contains documentation for the Slang system. +Some of the documentation is intended for users of the language and compiler, while other documentation is intended for developers contributing to the project. + +Getting Started +--------------- + +The Slang [User's Guide](https://shader-slang.github.io/slang/user-guide/) provides an introduction to the Slang language and its major features, as well as the compilation and reflection API. + +There is also documentation specific to using the [slangc](https://shader-slang.github.io/slang/user-guide/compiling.html#command-line-compilation-with-slangc) command-line tool. + +Advanced Users +-------------- + +For the benefit of advanced users we provide detailed documentation on how Slang compiles code for specific platforms. +The [target compatibility guide](target-compatibility.md) gives an overview of feature compatibility for targets. + +The [CPU target guide](cpu-target.md) gives information on compiling Slang or C++ source into shared libraries/executables or functions that can be directly executed. It also covers how to generate C++ code from Slang source. + +The [CUDA target guide](cuda-target.md) provides information on compiling Slang/HLSL or CUDA source. Slang can compile to equivalent CUDA source, as well as to PTX via the nvrtc CUDA compiler. + +Contributors +------------ + +For contributors to the Slang project, the information under the [`design/`](design/) directory may help explain the rationale behind certain design decisions and help when ramping up in the codebase. + +Research +-------- + +The Slang project is based on a long history of research work. While understanding this research is not necessary for working with Slang, it may be instructive for understanding the big-picture goals of the language, as well as why certain critical decisions were made. + +A [paper](http://graphics.cs.cmu.edu/projects/slang/) on the Slang system was accepted into SIGGRAPH 2018, and it provides an overview of the language and the compiler implementation. +Yong He's [dissertation](http://graphics.cs.cmu.edu/projects/renderergenerator/yong_he_thesis.pdf) provided more detailed discussion of the design of the Slang system. diff --git a/lib/All/slang/share/doc/slang/_config.yml b/lib/All/slang/share/doc/slang/_config.yml new file mode 100644 index 0000000..72d781d --- /dev/null +++ b/lib/All/slang/share/doc/slang/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-tactile diff --git a/lib/All/slang/share/doc/slang/_includes/anchor_headings.html b/lib/All/slang/share/doc/slang/_includes/anchor_headings.html new file mode 100644 index 0000000..3df42b6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/_includes/anchor_headings.html @@ -0,0 +1,137 @@ +{% capture headingsWorkspace %} +{% comment %} +Copyright (c) 2018 Vladimir "allejo" Jimenez + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +{% endcomment %} +{% comment %} +Version 1.0.9 +https://github.com/allejo/jekyll-anchor-headings + +"Be the pull request you wish to see in the world." ~Ben Balter + +Usage: +{% include anchor_headings.html html=content anchorBody="#" %} + +Parameters: +* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll + +Optional Parameters: +* beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content +* headerAttrs (string) : '' - Any custom HTML attributes that will be added to the heading tag; you may NOT use `id`; +the `%heading%` and `%html_id%` placeholders are available +* anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `` tag; you may NOT use `href`, + `class` or `title`; + the `%heading%` and `%html_id%` placeholders are available + * anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is + available + * anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a + space + * anchorTitle (string) : '' - The `title` attribute that will be used for anchors + * h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be + ignored + * h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be + ignored + * bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and + content + * bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and + content + + Output: + The original HTML with the addition of anchors inside of all of the h1-h6 headings. + {% endcomment %} + + {% assign minHeader = include.h_min | default: 1 %} + {% assign maxHeader = include.h_max | default: 2 %} + {% assign beforeHeading = include.beforeHeading %} + {% assign nodes = include.html | split: ' + {% if headerLevel == 0 %} + + {% assign firstChunk = node | split: '>' | first %} + + + {% unless firstChunk contains '<' %} {% capture node %}{% endcapture %} + {% assign _workspace = node | split: _closingTag %} + {% assign _idWorkspace = _workspace[0] | split: 'id="' %} + {% assign _idWorkspace = _idWorkspace[1] | split: '"' %} + {% assign html_id = _idWorkspace[0] %} + + {% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %} + {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} + + + {% capture anchor %}{% endcapture %} + + {% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %} {% assign escaped_header=header | + strip_html %} {% if include.headerAttrs %} {% capture _hAttrToStrip %}{{ _hAttrToStrip | split: '>' | + first }} {{ include.headerAttrs | replace: '%heading%' , escaped_header | replace: '%html_id%' , html_id + }}>{% endcapture %} + {% endif %} + + {% capture anchor %}href="#{{ html_id }}"{% endcapture %} + + {% if include.anchorClass %} + {% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %} + {% endif %} + + {% if include.anchorTitle %} + {% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', escaped_header + }}"{% endcapture %} + {% endif %} + + {% if include.anchorAttrs %} + {% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', escaped_header | + replace: '%html_id%', html_id }}{% endcapture %} + {% endif %} + + {% capture anchor %}{{ include.anchorBody | replace: '%heading%', escaped_header | + default: '' }}{% endcapture %} + + + {% if beforeHeading %} + {% capture anchor %}{{ anchor }} {% endcapture %} + {% else %} + {% capture anchor %} {{ anchor }}{% endcapture %} + {% endif %} + {% endif %} + + {% capture new_heading %} + + {% endcapture %} + + + {% assign chunkCount = _workspace | size %} + {% if chunkCount > 1 %} + {% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %} + {% endif %} + + {% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %} + {% endfor %} + {% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }} \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/_layouts/deprecated.html b/lib/All/slang/share/doc/slang/_layouts/deprecated.html new file mode 100644 index 0000000..f9d8b0b --- /dev/null +++ b/lib/All/slang/share/doc/slang/_layouts/deprecated.html @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + {% seo %} + + + +
+ +
+
+ {% include anchor_headings.html html=content anchorBody="" %} +
+ +
+ {% if site.github.is_project_page %} + {{ site.title | default: site.github.repository_name }} is maintained by {{ site.github.owner_name }}
+ {% endif %} + This page was generated by GitHub Pages. +
+
+
+ + + + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/_layouts/user-guide.html b/lib/All/slang/share/doc/slang/_layouts/user-guide.html new file mode 100644 index 0000000..347eb28 --- /dev/null +++ b/lib/All/slang/share/doc/slang/_layouts/user-guide.html @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + {% seo %} + + + +
+ + +
+
+ {% include_relative toc.html %} +
+
+
+
+ {% include anchor_headings.html html=content anchorBody="" %} +
+ +
+ {% if site.github.is_project_page %} + {{ site.title | default: site.github.repository_name }} is maintained by {{ site.github.owner_name }}
+ {% endif %} + This page was generated by GitHub Pages. +
+
+
+ + + + + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/assets/css/style.scss b/lib/All/slang/share/doc/slang/assets/css/style.scss new file mode 100644 index 0000000..801ee55 --- /dev/null +++ b/lib/All/slang/share/doc/slang/assets/css/style.scss @@ -0,0 +1,203 @@ +--- +--- + +@import "{{ site.theme }}"; +a:hover { + text-decoration: underline; +} +h3 { + color: #363636; +} +h4 { + color: #363636; +} +blockquote { + background-color: #f2f2f2; + padding-top: 10px; + padding-bottom: 5px; +} +blockquote p { + font-size: 16px; + font-weight: 400; + margin-bottom: 5px; + color: #202020; +} +body { + color: initial; + text-shadow: none; + background: none; +} +#container +{ + background:none; +} + + + +.highlight .cm { + color: #148b04; +} +.highlight .cp { + color: #148b04; +} +.highlight .c1 { + color: #148b04; +} +.highlight .cs { + color: #148b04; +} +.highlight .c, .highlight .ch, .highlight .cd, .highlight .cpf { + color: #148b04; +} +.highlight .err { + color: #a61717; + background-color: #e3d2d2; +} +.highlight .gd { + color: #000000; + background-color: #ffdddd; +} +.highlight .ge { + color: #000000; + font-style: italic; +} +.highlight .gr { + color: #aa0000; +} +.highlight .gh { + color: #999999; +} +.highlight .gi { + color: #000000; + background-color: #ddffdd; +} +.highlight .go { + color: #888888; +} +.highlight .gp { + color: #555555; +} +.highlight .gu { + color: #aaaaaa; +} +.highlight .gt { + color: #aa0000; +} +.highlight .kc { + color: #1243d4; +} +.highlight .kd { + color: #1243d4; +} +.highlight .kn { + color: #1243d4; +} +.highlight .kp { + color: #1243d4; +} +.highlight .kr { + color: #1243d4; +} +.highlight .kt { + color: #1243d4; +} +.highlight .k, .highlight .kv { + color: #1243d4; +} +.highlight .m, .highlight .mb, .highlight .mx, .highlight .mi, .highlight .mf { + color: #7211c2; +} +.highlight .sa { + color: #000000; +} +.highlight .sb { + color: #d14; +} +.highlight .sc { + color: #d14; +} +.highlight .sd { + color: #d14; +} +.highlight .s2 { + color: #d14; +} +.highlight .se { + color: #d14; +} +.highlight .sh { + color: #d14; +} +.highlight .si { + color: #d14; +} +.highlight .sx { + color: #d14; +} +.highlight .sr { + color: #009926; +} +.highlight .s1 { + color: #d14; +} +.highlight .ss { + color: #990073; +} +.highlight .s, .highlight .dl { + color: #d14; +} +.highlight .na { + color: #008080; +} +.highlight .bp { + color: #999999; +} +.highlight .n{ + color: black; +} +.highlight .nc { + color: #11abb9; +} +.highlight .nt { + color: #11abb9; +} +.highlight .vc { + color: #008080; +} +.highlight .vg { + color: #008080; +} +.highlight .vi { + color: #008080; +} +.highlight .nv, .highlight .vm { + color: #008080; +} +.highlight .ow { + color: #000000; +} +.highlight .o { + color: #000000; +} +.highlight .w { + color: #000000; +} +.highlight .p {color:#000000;} + +code +{ + background-color: initial; + border:none; +} +pre{ + color: #000000; + background: #F8F8F8; +} +pre code { + color: #000000; + background-color: #F8F8F8; +} +.highlight +{ + background: #F8F8F8; +} diff --git a/lib/All/slang/share/doc/slang/assets/moduletree.png b/lib/All/slang/share/doc/slang/assets/moduletree.png new file mode 100644 index 0000000..ef8c099 Binary files /dev/null and b/lib/All/slang/share/doc/slang/assets/moduletree.png differ diff --git a/lib/All/slang/share/doc/slang/build_reference.ps1 b/lib/All/slang/share/doc/slang/build_reference.ps1 new file mode 100644 index 0000000..a296768 --- /dev/null +++ b/lib/All/slang/share/doc/slang/build_reference.ps1 @@ -0,0 +1,62 @@ +# This script uses `slangc` to generate the core module reference documentation and push the updated +# documents to shader-slang/stdlib-reference repository. +# The stdlib-reference repository has github-pages setup so that the markdown files we generate +# in this step will be rendered as html pages by Jekyll upon a commit to the repository. +# So we we need to do here is to pull the stdlib-reference repository, regenerate the markdown files +# and push the changes back to the repository. + +# The generated markdown files will be located in three folders: +# - ./global-decls +# - ./interfaces +# - ./types +# In addition, slangc will generate a table of content file `toc.html` which will be copied to +# ./_includes/stdlib-reference-toc.html for Jekyll for consume it correctly. + +# If stdlib-reference folder does not exist, clone from github repo +if (-not (Test-Path ".\stdlib-reference")) { + git clone https://github.com/shader-slang/stdlib-reference/ +} +else { +# If it already exist, just pull the latest changes. + cd stdlib-reference + git pull + cd ../ +} +# Remove the old generated files. +Remove-Item -Path ".\stdlib-reference\global-decls" -Recurse -Force +Remove-Item -Path ".\stdlib-reference\interfaces" -Recurse -Force +Remove-Item -Path ".\stdlib-reference\types" -Recurse -Force +Remove-Item -Path ".\stdlib-reference\attributes" -Recurse -Force + +# Use git describe to produce a version string and write it to _includes/version.inc. +# This file will be included by the stdlib-reference Jekyll template. +git describe --tags | Out-File -FilePath ".\stdlib-reference\_includes\version.inc" -Encoding ASCII + +cd stdlib-reference +$slangPaths = @( + "../../build/RelWithDebInfo/bin/slangc.exe", + "../../build/Release/bin/slangc.exe", + "../../build/Debug/bin/slangc.exe" +) +$slangExe = $slangPaths | Where-Object { Test-Path $_ } | Select-Object -First 1 +if ($slangExe) { + & $slangExe -compile-core-module -doc + Move-Item -Path ".\toc.html" -Destination ".\_includes\stdlib-reference-toc.html" -Force + git config user.email "bot@shader-slang.com" + git config user.name "Stdlib Reference Bot" + git add . + git commit -m "Update the core module reference" + git push +} else { + Write-Error "Could not find slangc executable in RelWithDebInfo or Release directories" +} +cd ../ + +# For local debugging only. +# Remove-Item -Path "D:\git_repo\stdlib-reference\global-decls" -Recurse -Force +# Remove-Item -Path "D:\git_repo\stdlib-reference\interfaces" -Recurse -Force +# Remove-Item -Path "D:\git_repo\stdlib-reference\types" -Recurse -Force +# Copy-Item -Path .\stdlib-reference\global-decls -Destination D:\git_repo\stdlib-reference\global-decls -Recurse -Force +# Copy-Item -Path .\stdlib-reference\interfaces -Destination D:\git_repo\stdlib-reference\interfaces -Recurse -Force +# Copy-Item -Path .\stdlib-reference\types -Destination D:\git_repo\stdlib-reference\types -Recurse -Force +# Copy-Item -Path .\stdlib-reference\_includes\stdlib-reference-toc.html -Destination D:\git_repo\stdlib-reference\_includes\stdlib-reference-toc.html -Force diff --git a/lib/All/slang/share/doc/slang/build_toc.ps1 b/lib/All/slang/share/doc/slang/build_toc.ps1 new file mode 100644 index 0000000..543a8bc --- /dev/null +++ b/lib/All/slang/share/doc/slang/build_toc.ps1 @@ -0,0 +1,10 @@ +$job = Start-Job -ArgumentList $PSScriptRoot -ScriptBlock { + Set-Location $args[0] + $code = (Get-Content -Raw -Path "scripts/Program.cs").ToString() + $assemblies = ("System.Core", "System.IO", "System.Collections") + Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $code -Language CSharp + $path = Join-Path -Path $args[0] -ChildPath "user-guide" + [toc.Builder]::Run($path); +} +Wait-Job $job +Receive-Job -Job $job diff --git a/lib/All/slang/share/doc/slang/build_toc.sh b/lib/All/slang/share/doc/slang/build_toc.sh new file mode 100644 index 0000000..1776686 --- /dev/null +++ b/lib/All/slang/share/doc/slang/build_toc.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash +set -e + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +project_root="$(dirname "$script_dir")" +check_only=0 + +show_help() { + me=$(basename "$0") + cat <] [--check-only] + +Options: + --help Show this help message + --source Path to project root directory (defaults to parent of the script directory) + --check-only Check if TOC needs updating, exit 1 if changes needed +EOF +} + +while [[ "$#" -gt 0 ]]; do + case $1 in + -h | --help) + show_help + exit 0 + ;; + --source) + project_root="$2" + shift + ;; + --check-only) + check_only=1 + ;; + *) + echo "unrecognized argument: $1" >&2 + show_help >&2 + exit 1 + ;; + esac + shift +done + +missing_bin=0 + +require_bin() { + local name="$1" + if ! command -v "$name" &>/dev/null; then + echo "This script needs $name, but it isn't in \$PATH" >&2 + missing_bin=1 + return + fi +} + +require_bin "mcs" +require_bin "mono" + +if [ "$missing_bin" -eq 1 ]; then + exit 1 +fi + +temp_dir=$(mktemp -d) +trap 'rm -rf "$temp_dir"' EXIT + +docs_dir="$project_root/docs" + +cat >"$temp_dir/temp_program.cs" <&2 + exit 1 +fi + +for dir in "user-guide"; do + if [ -d "$docs_dir/$dir" ]; then + if [ "$check_only" -eq 1 ]; then + # Ensure working directory is clean + if ! git -C "$project_root" diff --quiet "docs/$dir/toc.html" 2>/dev/null; then + echo "Working directory not clean, cannot check TOC" >&2 + exit 1 + fi + fi + + if ! mono "$temp_dir/toc-builder.exe" "$docs_dir/$dir"; then + echo "TOC generation failed for $dir" >&2 + exit 1 + fi + + if [ "$check_only" -eq 1 ]; then + if ! git -C "$project_root" diff --quiet "docs/$dir/toc.html" 2>/dev/null; then + git -C "$project_root" diff --color "docs/$dir/toc.html" + git -C "$project_root" checkout -- "docs/$dir/toc.html" 2>/dev/null + exit 1 + fi + fi + else + echo "Directory $dir not found" >&2 + fi +done diff --git a/lib/All/slang/share/doc/slang/building.md b/lib/All/slang/share/doc/slang/building.md new file mode 100644 index 0000000..28a0133 --- /dev/null +++ b/lib/All/slang/share/doc/slang/building.md @@ -0,0 +1,442 @@ +# Building Slang From Source + +### TLDR + +`cmake --workflow --preset release` to configure, build, and package a release +version of Slang. + +## Prerequisites: + +Please install: + +- CMake (3.26 preferred, but 3.22 works[^1]) +- A C++ compiler with support for C++17. GCC, Clang and MSVC are supported +- A CMake compatible backend, for example Visual Studio or Ninja +- Python3 (a dependency for building spirv-tools) + +Optional dependencies for tests include + +- CUDA +- OptiX +- NVAPI +- Aftermath +- X11 + +Other dependencies are sourced from submodules in the [./external](./external) +directory. + +## Get the Source Code + +Clone [this](https://github.com/shader-slang/slang) repository. Make sure to +fetch the submodules also. + +```bash +git clone https://github.com/shader-slang/slang --recursive +``` + +You will need the git tags from this repository, otherwise versioning +information (including the Slang modules directory name and the library +filenames on macOS and Linux) will be incorrect. The above command should fetch +them for you, but if you're fetching from a fork you may need to explicitly +fetch the latest tags from the shader-slang repository with: + +```bash +git fetch https://github.com/shader-slang/slang.git 'refs/tags/*:refs/tags/*' +``` + +## Configure and build + +> This section assumes cmake 3.25 or greater, if you're on a lower version +> please see [building with an older cmake](#building-with-an-older-cmake) + +For a Ninja based build system (all platforms) run: +```bash +cmake --preset default +cmake --build --preset releaseWithDebugInfo # or --preset debug, or --preset release +``` + +For Visual Studio run: +```bash +cmake --preset vs2022 # or 'vs2019' or 'vs2026' +start devenv ./build/slang.sln # to optionally open the project in Visual Studio +cmake --build --preset releaseWithDebugInfo # to build from the CLI, could also use --preset release or --preset debug +``` + +There are also `*-dev` variants like `vs2022-dev` and `vs2026-dev` which turn on features to aid +debugging. + +### WebAssembly build + +In order to build WebAssembly build of Slang, Slang needs to be compiled with +[Emscripten SDK](https://github.com/emscripten-core/emsdk). You can find more +information about [Emscripten](https://emscripten.org/). + +You need to clone the EMSDK repo. And you need to install and activate the latest. + + +```bash +git clone https://github.com/emscripten-core/emsdk.git +cd emsdk +``` + +For non-Windows platforms +```bash +./emsdk install latest +./emsdk activate latest +``` + +For Windows +```cmd +emsdk.bat install latest +emsdk.bat activate latest +``` + +After EMSDK is activated, Slang needs to be built in a cross compiling setup: + +- build the `generators` target for the build platform +- configure the build with `emcmake` for the host platform +- build for the host platform. + +> Note: For more details on cross compiling please refer to the +> [cross-compiling](docs/building.md#cross-compiling) section. + +```bash +# Build generators. +cmake --workflow --preset generators --fresh +mkdir generators +cmake --install build --prefix generators --component generators + +# Configure the build with emcmake. +# emcmake is available only when emsdk_env setup the environment correctly. +pushd ../emsdk +source ./emsdk_env # For Windows, emsdk_env.bat +popd +emcmake cmake -DSLANG_GENERATORS_PATH=generators/bin --preset emscripten -G "Ninja" + +# Build slang-wasm.js and slang-wasm.wasm in build.em/Release/bin +cmake --build --preset emscripten --target slang-wasm +``` + +> Note: If the last build step fails, try running the command that `emcmake` +> outputs, directly. + +## Installing + +Build targets may be installed using cmake: + +```bash +cmake --build . --target install +``` + +This should install `SlangConfig.cmake` that should allow `find_package` to work. +SlangConfig.cmake defines `SLANG_EXECUTABLE` variable that will point to `slangc` +executable and also define `slang::slang` target to be linked to. + +For now, `slang::slang` is the only exported target defined in the config which can +be linked to. + +Example usage + +```cmake +find_package(slang REQUIRED PATHS ${your_cmake_install_prefix_path} NO_DEFAULT_PATH) +# slang_FOUND should be automatically set +target_link_libraries(yourLib PUBLIC + slang::slang +) +``` + +## Testing + +```bash +build/Debug/bin/slang-test +``` + +See the [documentation on testing](../tools/slang-test/README.md) for more information. + +## Debugging + +See the [documentation on debugging](/docs/debugging.md). + +## Distributing + +### Versioned Libraries + +As of v2025.21, the Slang libraries on **Mac** and **Linux** use versioned +filenames. The public ABI for Slang libraries in general is not currently +stable, so in accordance with semantic versioning conventions, the major +version number for dynamically linkable libraries is currently 0. Due to the +unstable ABI, releases are designed so that downstream users will be linked +against the fully versioned library filenames (e.g., +`libslang-compiler.so.0.2025.21` instead of `libslang-compiler.so`). + +Slang libraries for **Windows** do not have an explicit version in the +library filename, but the the same guidance about stability of the ABI applies. + +Downstream users of Slang distributing their products as binaries should +therefor **on all platforms, including Windows** redistribute the Slang +libraries they linked against, or otherwise communicate the specific version +dependency to their users. It is *not the case* that a user of your product can +just install any recent Slang release and have an installation of Slang that +works for any given binary. + +## More niche topics + +### CMake options + +| Option | Default | Description | +|-----------------------------------|----------------------------|----------------------------------------------------------------------------------------------| +| `SLANG_VERSION` | Latest `v*` tag | The project version, detected using git if available | +| `SLANG_EMBED_CORE_MODULE` | `TRUE` | Build slang with an embedded version of the core module | +| `SLANG_EMBED_CORE_MODULE_SOURCE` | `TRUE` | Embed the core module source in the binary | +| `SLANG_ENABLE_DXIL` | `TRUE` | Enable generating DXIL using DXC | +| `SLANG_ENABLE_ASAN` | `FALSE` | Enable ASAN (address sanitizer) | +| `SLANG_ENABLE_COVERAGE` | `FALSE` | Enable code coverage instrumentation | +| `SLANG_ENABLE_FULL_IR_VALIDATION` | `FALSE` | Enable full IR validation (SLOW!) | +| `SLANG_ENABLE_IR_BREAK_ALLOC` | `FALSE` | Enable IR BreakAlloc functionality for debugging. | +| `SLANG_ENABLE_GFX` | `TRUE` | Enable gfx targets | +| `SLANG_ENABLE_SLANGD` | `TRUE` | Enable language server target | +| `SLANG_ENABLE_SLANGC` | `TRUE` | Enable standalone compiler target | +| `SLANG_ENABLE_SLANGI` | `TRUE` | Enable Slang interpreter target | +| `SLANG_ENABLE_SLANGRT` | `TRUE` | Enable runtime target | +| `SLANG_ENABLE_SLANG_GLSLANG` | `TRUE` | Enable glslang dependency and slang-glslang wrapper target | +| `SLANG_ENABLE_TESTS` | `TRUE` | Enable test targets, requires SLANG_ENABLE_GFX, SLANG_ENABLE_SLANGD and SLANG_ENABLE_SLANGRT | +| `SLANG_ENABLE_EXAMPLES` | `TRUE` | Enable example targets, requires SLANG_ENABLE_GFX | +| `SLANG_LIB_TYPE` | `SHARED` | How to build the slang library | +| `SLANG_ENABLE_RELEASE_DEBUG_INFO` | `TRUE` | Enable generating debug info for Release configs | +| `SLANG_ENABLE_RELEASE_LTO` | `FALSE` | Enable LTO for Release builds | +| `SLANG_ENABLE_SPLIT_DEBUG_INFO` | `TRUE` | Enable generating split debug info for Debug and RelWithDebInfo configs | +| `SLANG_SLANG_LLVM_FLAVOR` | `FETCH_BINARY_IF_POSSIBLE` | How to set up llvm support | +| `SLANG_SLANG_LLVM_BINARY_URL` | System dependent | URL specifying the location of the slang-llvm prebuilt library | +| `SLANG_GENERATORS_PATH` | `` | Path to an installed `all-generators` target for cross compilation | + +The following options relate to optional dependencies for additional backends +and running additional tests. Left unchanged they are auto detected, however +they can be set to `OFF` to prevent their usage, or set to `ON` to make it an +error if they can't be found. + +| Option | CMake hints | Notes | +|--------------------------|--------------------------------|----------------------------------------------------------------------------------------------| +| `SLANG_ENABLE_CUDA` | `CUDAToolkit_ROOT` `CUDA_PATH` | Enable running tests with the CUDA backend, doesn't affect the targets Slang itself supports | +| `SLANG_ENABLE_OPTIX` | `Optix_ROOT_DIR` | Requires CUDA | +| `SLANG_ENABLE_NVAPI` | `NVAPI_ROOT_DIR` | Only available for builds targeting Windows | +| `SLANG_ENABLE_AFTERMATH` | `Aftermath_ROOT_DIR` | Enable Aftermath in GFX, and add aftermath crash example to project | +| `SLANG_ENABLE_XLIB` | | | + +### Advanced options + +| Option | Default | Description | +|------------------------------------|---------|--------------------------------------------------------------------------------------------------------------------------------| +| `SLANG_ENABLE_DX_ON_VK` | `FALSE` | Enable running the DX11 and DX12 tests on non-warning Windows platforms via vkd3d-proton, requires system-provided d3d headers | +| `SLANG_ENABLE_SLANG_RHI` | `TRUE` | Enable building and using [slang-rhi](https://github.com/shader-slang/slang-rhi) for tests | +| `SLANG_USE_SYSTEM_MINIZ` | `FALSE` | Build using system Miniz library instead of the bundled version in [./external](./external) | +| `SLANG_USE_SYSTEM_LZ4` | `FALSE` | Build using system LZ4 library instead of the bundled version in [./external](./external) | +| `SLANG_USE_SYSTEM_VULKAN_HEADERS` | `FALSE` | Build using system Vulkan headers instead of the bundled version in [./external](./external) | +| `SLANG_USE_SYSTEM_SPIRV_HEADERS` | `FALSE` | Build using system SPIR-V headers instead of the bundled version in [./external](./external) | +| `SLANG_USE_SYSTEM_UNORDERED_DENSE` | `FALSE` | Build using system unordered dense instead of the bundled version in [./external](./external) | +| `SLANG_SPIRV_HEADERS_INCLUDE_DIR` | `` | Use this specific path to SPIR-V headers instead of the bundled version in [./external](./external) | + +### LLVM Support + +There are several options for getting llvm-support: + +- Use a prebuilt binary slang-llvm library: + `-DSLANG_SLANG_LLVM_FLAVOR=FETCH_BINARY` or `-DSLANG_SLANG_LLVM_FLAVOR=FETCH_BINARY_IF_POSSIBLE` (this is the default) + - You can set `SLANG_SLANG_LLVM_BINARY_URL` to point to a local + `libslang-llvm.so/slang-llvm.dll` or set it to a URL of an zip/archive + containing such a file + - If this isn't set then the build system tries to download it from the + release on github matching the current tag. If such a tag doesn't exist + or doesn't have the correct os\*arch combination then the latest release + will be tried. + - If `SLANG_SLANG_LLVM_BINARY_URL` is `FETCH_BINARY_IF_POSSIBLE` then in + the case that a prebuilt binary can't be found then the build will proceed + as though `DISABLE` was chosen +- Use a system supplied LLVM: `-DSLANG_SLANG_LLVM_FLAVOR=USE_SYSTEM_LLVM`, you + must have llvm-21.1 and a matching libclang installed. It's important that + either: + - You don't end up linking to a dynamic libllvm.so, this will almost + certainly cause multiple versions of LLVM to be loaded at runtime, + leading to errors like `opt: CommandLine Error: Option + 'asm-macro-max-nesting-depth' registered more than once!`. Avoid this by + compiling LLVM without the dynamic library. + - Anything else which may be linked in (for example Mesa, also dynamically + loads the same llvm object) +- Do not enable LLVM support: `-DSLANG_SLANG_LLVM_FLAVOR=DISABLE` + +To build only a standalone slang-llvm, you can run: + +```bash +cmake --workflow --preset slang-llvm +``` + +This will generate `build/dist-release/slang-slang-llvm.zip` containing the +library. This, of course, uses the system LLVM to build slang-llvm, otherwise +it would just be a convoluted way to download a prebuilt binary. + +### Cross compiling + +Slang generates some code at build time, using generators build from this +codebase. Due to this, for cross compilation one must already have built these +generators for the build platform. Build them with the `generators` preset, and +pass the install path to the cross building CMake invocation using +`SLANG_GENERATORS_PATH` + +Non-Windows platforms: + +```bash +# build the generators +cmake --workflow --preset generators --fresh +mkdir build-platform-generators +cmake --install build --config Release --prefix build-platform-generators --component generators +# reconfigure, pointing to these generators +# Here is also where you should set up any cross compiling environment +cmake \ + --preset default \ + --fresh \ + -DSLANG_GENERATORS_PATH=build-platform-generators/bin \ + -Dwhatever-other-necessary-options-for-your-cross-build \ + # for example \ + -DCMAKE_C_COMPILER=my-arch-gcc \ + -DCMAKE_CXX_COMPILER=my-arch-g++ +# perform the final build +cmake --workflow --preset release +``` + +Windows + +```bash +# build the generators +cmake --workflow --preset generators --fresh +mkdir build-platform-generators +cmake --install build --config Release --prefix build-platform-generators --component generators +# reconfigure, pointing to these generators +# Here is also where you should set up any cross compiling environment +# For example +./vcvarsamd64_arm64.bat +cmake \ + --preset default \ + --fresh \ + -DSLANG_GENERATORS_PATH=build-platform-generators/bin \ + -Dwhatever-other-necessary-options-for-your-cross-build +# perform the final build +cmake --workflow --preset release +``` + +### Example cross compiling with MSVC to windows-aarch64 + +One option is to build using the ninja generator, which requires providing the +native and cross environments via `vcvarsall.bat` + +```bash +vcvarsall.bat +cmake --workflow --preset generators --fresh +mkdir generators +cmake --install build --prefix generators --component generators +vsvarsall.bat x64_arm64 +cmake --preset default --fresh -DSLANG_GENERATORS_PATH=generators/bin +cmake --workflow --preset release +``` + +Another option is to build using the Visual Studio generator which can find +this automatically + +``` +cmake --preset vs2022 # or --preset vs2019, vs2026 +cmake --build --preset generators # to build from the CLI +cmake --install build --prefix generators --component generators +rm -rf build # The Visual Studio generator will complain if this is left over from a previous build +cmake --preset vs2022 --fresh -A arm64 -DSLANG_GENERATORS_PATH=generators/bin +cmake --build --preset release +``` + +### Nix + +This repository contains a [Nix](https://nixos.org/) +[flake](https://wiki.nixos.org/wiki/Flakes) (not officially supported or +tested), which provides the necessary prerequisites for local development. Also, +if you use [direnv](https://direnv.net/), you can run the following commands to +have the Nix environment automatically activate when you enter your clone of +this repository: + +```bash +echo 'use flake' > .envrc +direnv allow +``` + +## Building with an older CMake + +Because older CMake versions don't support all the features we want to use in +CMakePresets, you'll have to do without the presets. Something like the following + +```bash +cmake -B build -G Ninja +cmake --build build -j +``` + +## Specific supported compiler versions + + + +_GCC_ 11.4 and 13.3 are tested in CI and is the recommended minimum version. GCC 10 is +supported on a best-effort basis, i.e. PRs supporting this version are +encouraged but it isn't a continuously maintained setup. + +_MSVC_ 19 is tested in CI and is the recommended minimum version. + +_Clang_ 17.0 is tested in CI and is the recommended minimum version. + +## Static linking against libslang-compiler + +To build statically, set the `SLANG_LIB_TYPE` flag in CMake to `STATIC`. + +If linking against a static `libslang-compiler.a` you will need to link against some +dependencies also if you're not already incorporating them into your project. + +``` +${SLANG_DIR}/build/Release/lib/libslang-compiler.a +${SLANG_DIR}/build/Release/lib/libcompiler-core.a +${SLANG_DIR}/build/Release/lib/libcore.a +${SLANG_DIR}/build/external/miniz/libminiz.a +${SLANG_DIR}/build/external/lz4/build/cmake/liblz4.a +``` + +## Deprecation of libslang and slang.dll filenames + +In Slang v2025.21, the primary library for Slang was renamed, from +`libslang.so` and `slang.dll` to `libslang-compiler.so` and +`slang-compiler.dll`. (A similar change was made for macOS.) The reason behind +this change was to address a conflict on the Linux target, where the S-Lang +library of the same name is commonly preinstalled on Linux distributions. The +same issue affected macOS, to a lesser extent, where the S-Lang library could +be installed via `brew`. To make the Slang library name predictable and +simplify downstream build logic, the Slang library name was changed on all +platforms. + +A change like this requires a period of transition, so on a **temporary** +basis: Linux and macOS packages now include symlinks from the old filename to +the new one. For Windows, a proxy library is provided with the old name, that +redirects all functions to the new `slang-compiler.dll`. The rationale here is +that applications with a complex dependency graph may have some components +still temporarily using `slang.dll`, while others have been updated to use +`slang-compiler.dll`. Using a proxy library for `slang.dll` ensures that all +components are using the same library, and avoids any potential state or +heap-related issues from an executable sharing data structures between the two +libraries. + +These backwards compatability affordances, namely the proxy `slang.dll` and +`slang.lib` (for Windows) and the `libslang.so` and `libslang.dylib` symlinks +(for Linux and macOS), **will be removed at the end of 2026**. Until that time, +they will be present in the github release packages for downstream use. +Downstream packaging may or may not choose to distribute them, at their +discretion. **We strongly encourage downstream users of Slang to move to the +new library names as soon as they are able.** + +## Notes + +[^1] below 3.25, CMake lacks the ability to mark directories as being +system directories (https://cmake.org/cmake/help/latest/prop_tgt/SYSTEM.html#prop_tgt:SYSTEM), +this leads to an inability to suppress warnings originating in the +dependencies in `./external`, so be prepared for some additional warnings. diff --git a/lib/All/slang/share/doc/slang/ci.md b/lib/All/slang/share/doc/slang/ci.md new file mode 100644 index 0000000..fb4c7e6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/ci.md @@ -0,0 +1,36 @@ +# Our CI + +There are github actions for building and testing slang. + +## Tests + +Most configurations run a restricted set of tests, however on some self hosted +runners we run the full test suite, as well as running Falcor's test suite with +the new slang build. + +## Building LLVM + +We require a static build of LLVM for building slang-llvm, we build and cache +this in all workflow runs. Since this changes infrequently, the cache is almost +always hit. A cold build takes about an hour on the slowest platform. The +cached output is a few hundred MB, so conceivably if we add many more platforms +we might be caching more than the 10GB github allowance, which would +necessitate being a bit more complicated in building and tracking outputs here. + +For slang-llvm, this is handled the same as any other dependency, except on +Windows Debug builds, where we are required by the differences in Debug/Release +standard libraries to always make a release build, this is noted in the ci +action yaml file. + +Note that we don't use sccache while building LLVM, as it changes very +infrequently. The caching of LLVM is done by caching the final build product +only. + +## sccache + +> Due to reliability issues, we are not currently using sccache, this is +> historical/aspirational. + +The CI actions use sccache, keyed on compiler and platform, this runs on all +configurations and significantly speeds up small source change builds. This +cache can be safely missed without a large impact on build times. diff --git a/lib/All/slang/share/doc/slang/command-line-slangc-reference.md b/lib/All/slang/share/doc/slang/command-line-slangc-reference.md new file mode 100644 index 0000000..e7696f1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/command-line-slangc-reference.md @@ -0,0 +1,1802 @@ +# Slang Command Line Options + +*Usage:* +``` +slangc [options...] [--] + +# For help +slangc -h + +# To generate this file +slangc -help-style markdown -h +``` +### Quick Links + +* [General](#General) +* [Target](#Target) +* [Downstream](#Downstream) +* [Debugging](#Debugging) +* [Repro](#Repro) +* [Experimental](#Experimental) +* [Internal](#Internal) +* [Deprecated](#Deprecated) +* [compiler](#compiler) +* [language](#language) +* [language-version](#language-version) +* [archive-type](#archive-type) +* [line-directive-mode](#line-directive-mode) +* [debug-info-format](#debug-info-format) +* [fp-mode](#fp-mode) +* [fp-denormal-mode](#fp-denormal-mode) +* [help-style](#help-style) +* [optimization-level](#optimization-level) +* [debug-level](#debug-level) +* [file-system-type](#file-system-type) +* [source-embed-style](#source-embed-style) +* [target](#target) +* [stage](#stage) +* [vulkan-shift](#vulkan-shift) +* [capability](#capability) +* [file-extension](#file-extension) +* [help-category](#help-category) + + +## General + +General options + + +### -D + +**-D<name>\[=<value>\], -D <name>\[=<value>\]** + +Insert a preprocessor macro. + +The space between - D and <name> is optional. If no <value> is specified, Slang will define the macro with an empty value. + + + +### -depfile + +**-depfile <path>** + +Save the source file dependency list in a file. + + + +### -entry + +**-entry <name>** + +Specify the name of an entry-point function. + +When compiling from a single file, this defaults to main if you specify a stage using [-stage](#stage-1). + +Multiple [-entry](#entry) options may be used in a single invocation. When they do, the file associated with the entry point will be the first one found when searching to the left in the command line. + +If no [-entry](#entry) options are given, compiler will use \[shader(...)\] attributes to detect entry points. + + + +### -specialize + +**-specialize <typename>** + +Specialize the last entrypoint with <typename>. + + + + + +### -emit-ir +Emit IR typically as a '.slang-module' when outputting to a container. + + + +### -h, -help, --help + +**-h or -h <[help-category](#help-category)>** + +Print this message, or help in specified category. + + + +### -help-style + +**-help-style <[help-style](#help-style)>** + +Help formatting style + + + +### -I + +**-I<path>, -I <path>** + +Add a path to be used in resolving '#include' and 'import' operations. + + + +### -lang + +**-lang <[language](#language)>** + +Set the language for the following input files. + + + +### -matrix-layout-column-major +Set the default matrix layout to column-major. + + + +### -matrix-layout-row-major +Set the default matrix layout to row-major. + + + +### -restrictive-capability-check +Many capability warnings will become an error. + + + +### -ignore-capabilities +Do not warn or error if capabilities are violated + + + +### -minimum-slang-optimization +Perform minimum code optimization in Slang to favor compilation time. + + + +### -disable-non-essential-validations +Disable non-essential IR validations such as use of uninitialized variables. + + + +### -disable-source-map +Disable source mapping in the Obfuscation. + + + +### -module-name + +**-module-name <name>** + +Set the module name to use when compiling multiple .slang source files into a single module. + + + +### -o + +**-o <path>** + +Specify a path where generated output should be written. + +If no [-target](#target-1) or [-stage](#stage-1) is specified, one may be inferred from file extension (see [<file-extension>](#file-extension)). If multiple [-target](#target-1) options and a single [-entry](#entry) are present, each [-o](#o) associates with the first [-target](#target-1) to its left. Otherwise, if multiple [-entry](#entry) options are present, each [-o](#o) associates with the first [-entry](#entry) to its left, and with the [-target](#target-1) that matches the one inferred from <path>. + + + +### -profile + +**-profile <profile>\[+<[capability](#capability)>...\]** + +Specify the shader profile for code generation. + +Accepted profiles are: + +* sm_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6} + +* glsl_{110,120,130,140,150,330,400,410,420,430,440,450,460} + +Additional profiles that include [-stage](#stage-1) information: + +* {vs,hs,ds,gs,ps}_<version> + +See [-capability](#capability-1) for information on [<capability>](#capability) + +When multiple [-target](#target-1) options are present, each [-profile](#profile) associates with the first [-target](#target-1) to its left. + + + +### -stage + +**-stage <[stage](#stage)>** + +Specify the stage of an entry-point function. + +When multiple [-entry](#entry) options are present, each [-stage](#stage-1) associated with the first [-entry](#entry) to its left. + +May be omitted if entry-point function has a \[shader(...)\] attribute; otherwise required for each [-entry](#entry) option. + + + +### -target + +**-target <[target](#target)>** + +Specifies the format in which code should be generated. + + + +### -v, -version +Display the build version. This is the contents of git describe --tags. + +It is typically only set from automated builds(such as distros available on github).A user build will by default be 'unknown'. + + + +### -std + +**-std <[language-version](#language-version)>** + +Specifies the language standard that should be used. + + + +### -warnings-as-errors + +**-warnings-as-errors all or -warnings-as-errors <id>\[,<id>...\]** + +all - Treat all warnings as errors. + +<id>\[,<id>...\]: Treat specific warning ids as errors. + + + + + +### -warnings-disable + +**-warnings-disable <id>\[,<id>...\]** + +Disable specific warning ids. + + + +### -W + +**-W<id>** + +Enable a warning with the specified id. + + + +### -Wno- + +**-Wno-<id>** + +Disable warning with <id> + + + +### -dump-warning-diagnostics +Dump to output list of warning diagnostic numeric and name ids. + + + +### -- +Treat the rest of the command line as input files. + + + +### -report-downstream-time +Reports the time spent in the downstream compiler. + + + +### -report-perf-benchmark +Reports compiler performance benchmark results. + + + +### -report-detailed-perf-benchmark +Reports compiler performance benchmark results for each intermediate pass (implies [-report-perf-benchmark](#report-perf-benchmark)). + + + +### -report-checkpoint-intermediates +Reports information about checkpoint contexts used for reverse-mode automatic differentiation. + + + +### -report-dynamic-dispatch-sites +Reports information about dynamic dispatch sites for interface calls. + + + +### -skip-spirv-validation +Skips spirv validation. + + + +### -source-embed-style + +**-source-embed-style <[source-embed-style](#source-embed-style)>** + +If source embedding is enabled, defines the style used. When enabled (with any style other than `none`), will write compile results into embeddable source for the target language. If no output file is specified, the output is written to stdout. If an output file is specified it is written either to that file directly (if it is appropriate for the target language), or it will be output to the filename with an appropriate extension. + + + +Note for C/C++ with u16/u32/u64 types it is necessary to have "#include <stdint.h>" before the generated file. + + + + + +### -source-embed-name + +**-source-embed-name <name>** + +The name used as the basis for variables output for source embedding. + + + +### -source-embed-language + +**-source-embed-language <[language](#language)>** + +The language to be used for source embedding. Defaults to C/C++. Currently only C/C++ are supported + + + +### -disable-short-circuit +Disable short-circuiting for "&&" and "||" operations + + + +### -unscoped-enum +Treat enums types as unscoped by default. + + + +### -preserve-params +Preserve all resource parameters in the output code, even if they are not used by the shader. + + + +### -conformance + +**-conformance <typeName>:<interfaceName>\[=<sequentialID>\]** + +Include additional type conformance during linking for dynamic dispatch. + + + +### -reflection-json + +**-reflection-json <path>** + +Emit reflection data in JSON format to a file. + + + +### -msvc-style-bitfield-packing +Pack bitfields according to MSVC rules (msb first, new field when underlying type size changes) rather than gcc-style (lsb first) + + + + +## Target + +Target code generation options + + +### -capability + +**-capability <[capability](#capability)>\[+<[capability](#capability)>...\]** + +Add optional capabilities to a code generation target. See Capabilities below. + + + +### -default-image-format-unknown +Set the format of R/W images with unspecified format to 'unknown'. Otherwise try to guess the format. + + + +### -disable-dynamic-dispatch +Disables generating dynamic dispatch code. + + + +### -disable-specialization +Disables generics and specialization pass. + + + +### -fp-mode, -floating-point-mode + +**-fp-mode <[fp-mode](#fp-mode)>, -floating-point-mode <[fp-mode](#fp-mode)>** + +Control floating point optimizations + + + +### -denorm-mode-fp16 + +**-denorm-mode-fp16 <[fp-denormal-mode](#fp-denormal-mode)>** + +Control handling of 16-bit denormal floating point values in SPIR-V (any, preserve, ftz) + + + +### -denorm-mode-fp32 + +**-denorm-mode-fp32 <[fp-denormal-mode](#fp-denormal-mode)>** + +Control handling of 32-bit denormal floating point values in SPIR-V and DXIL (any, preserve, ftz) + + + +### -denorm-mode-fp64 + +**-denorm-mode-fp64 <[fp-denormal-mode](#fp-denormal-mode)>** + +Control handling of 64-bit denormal floating point values in SPIR-V (any, preserve, ftz) + + + +### -g + +**-g, -g<[debug-info-format](#debug-info-format)>, -g<[debug-level](#debug-level)>** + +Include debug information in the generated code, where possible. + +[<debug-level>](#debug-level) is the amount of information, 0..3, unspecified means 2 + +[<debug-info-format>](#debug-info-format) specifies a debugging info format + +It is valid to have multiple [-g](#g) options, such as a [<debug-level>](#debug-level) and a [<debug-info-format>](#debug-info-format) + + + +### -line-directive-mode + +**-line-directive-mode <[line-directive-mode](#line-directive-mode)>** + +Sets how the `#line` directives should be produced. Available options are: + +If not specified, default behavior is to use C-style `#line` directives for HLSL and C/C++ output, and traditional GLSL-style `#line` directives for GLSL output. + + + +### -O + +**-O<[optimization-level](#optimization-level)>** + +Set the optimization level. + + + +### -obfuscate +Remove all source file information from outputs. + + + +### -force-glsl-scalar-layout, -fvk-use-scalar-layout +Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, ByteAddressBuffer and general pointers follow the 'scalar' layout when targeting GLSL or SPIRV. + + + +### -fvk-use-dx-layout +Pack members using FXCs member packing rules when targeting GLSL or SPIRV. + + + +### -fvk-use-c-layout +Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, ByteAddressBuffer and general pointers follow the C/C++ structure layout rules when targeting SPIRV. + + + +### -fvk-<vulkan-shift>-shift + +**-fvk-<[vulkan-shift](#vulkan-shift)>-shift <N> <space>** + +For example '-fvk-b-shift <N> <space>' shifts by N the inferred binding numbers for all resources in 'b' registers of space <space>. For a resource attached with :register(bX, <space>) but not \[vk::binding(...)\], sets its Vulkan descriptor set to <space> and binding number to X + N. If you need to shift the inferred binding numbers for more than one space, provide more than one such option. If more than one such option is provided for the same space, the last one takes effect. If you need to shift the inferred binding numbers for all sets, use 'all' as <space>. + +* \[DXC description\](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#implicit-binding-number-assignment) + +* \[GLSL wiki\](https://github.com/KhronosGroup/glslang/wiki/HLSL-FAQ#auto-mapped-binding-numbers) + + + + + +### -fvk-bind-globals + +**-fvk-bind-globals <N> <descriptor-set>** + +Places the $Globals cbuffer at descriptor set <descriptor-set> and binding <N>. + +It lets you specify the descriptor for the source at a certain register. + +* \[DXC description\](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#implicit-binding-number-assignment) + + + + + +### -fvk-invert-y +Negates (additively inverts) SV_Position.y before writing to stage output. + + + +### -fvk-use-dx-position-w +Reciprocates (multiplicatively inverts) SV_Position.w after reading from stage input. For use in fragment shaders only. + + + +### -fvk-use-entrypoint-name +Uses the entrypoint name from the source instead of 'main' in the spirv output. + + + +### -fvk-use-gl-layout +Use std430 layout instead of D3D buffer layout for raw buffer load/stores. + + + +### -fspv-reflect +Include reflection decorations in the resulting SPIRV for shader parameters. + + + +### -enable-effect-annotations +Enables support for legacy effect annotation syntax. + + + +### -emit-spirv-via-glsl +Generate SPIR-V output by compiling generated GLSL with glslang + + + +### -emit-spirv-directly +Generate SPIR-V output directly (default) + + + +### -spirv-core-grammar +A path to a specific spirv.core.grammar.json to use when generating SPIR-V output + + + +### -incomplete-library +Allow generating code from incomplete libraries with unresolved external functions + + + +### -bindless-space-index + +**-bindless-space-index <index>** + +Specify the space index for the system defined global bindless resource array. + + + +### -separate-debug-info +Emit debug data to a separate file, and strip it from the main output file. + + + +### -emit-cpu-via-cpp +Generate CPU targets using C++ (default) + + + +### -emit-cpu-via-llvm +Generate CPU targets using LLVM + + + +### -llvm-target-triple + +**-llvm-target-triple <target triple>** + +Sets the target triple for the LLVM target, enabling cross compilation. The default value is the host platform. + + + +### -llvm-cpu + +**-llvm-cpu <cpu name>** + +Sets the target CPU for the LLVM target, enabling the extensions and features of that CPU. The default value is "generic". + + + +### -llvm-features + +**-llvm-features <a1,+enable,-disable,...>** + +Sets a comma-separates list of architecture-specific features for the LLVM targets. + + + + +## Downstream + +Downstream compiler options + + +### -<compiler>-path + +**-<[compiler](#compiler)>-path <path>** + +Specify path to a downstream [<compiler>](#compiler) executable or library. + + + + + +### -default-downstream-compiler + +**-default-downstream-compiler <[language](#language)> <[compiler](#compiler)>** + +Set a default compiler for the given language. See [-lang](#lang) for the list of languages. + + + +### -X + +**-X<[compiler](#compiler)> <option> -X<[compiler](#compiler)>... <options> -X.** + +Pass arguments to downstream [<compiler>](#compiler). Just [-X<compiler>](#X) passes just the next argument to the downstream compiler. [-X<compiler>](#X)... options [-X](#X). will pass *all* of the options inbetween the opening [-X](#X) and [-X](#X). to the downstream compiler. + + + +### -pass-through + +**-pass-through <[compiler](#compiler)>** + +Pass the input through mostly unmodified to the existing compiler [<compiler>](#compiler). + +These are intended for debugging/testing purposes, when you want to be able to see what these existing compilers do with the "same" input and options + + + + +## Debugging + +Compiler debugging/instrumentation options + + +### -dump-ast +Dump the AST to a .slang-ast file next to the input. + + + +### -dump-intermediate-prefix + +**-dump-intermediate-prefix <prefix>** + +File name prefix for [-dump-intermediates](#dump-intermediates) outputs, default is no prefix + + + +### -dump-intermediates +Dump intermediate outputs for debugging. + + + +### -dump-ir +Dump the IR after every pass for debugging. + + + +### -dump-ir-ids +Dump the IDs with [-dump-ir](#dump-ir) (debug builds only) + + + +### -E, -output-preprocessor +Output the preprocessing result and exit. + + + +### -no-codegen +Skip the code generation step, just check the code and generate layout. + + + +### -output-includes +Print the hierarchy of the processed source files. + + + +### -serial-ir +\[REMOVED\] Serialize the IR between front-end and back-end. + + + +### -skip-codegen +Skip the code generation phase. + + + +### -validate-ir +Validate the IR after select intermediate passes. + + + +### -validate-ir-detailed +Perform debug validation on IR after each intermediate pass. + + + +### -dump-ir-before + +**-dump-ir-before <pass-names>** + +Dump IR before specified pass, may be specified more than once + + + +### -dump-ir-after + +**-dump-ir-after <pass-names>** + +Dump IR after specified pass, may be specified more than once + + + +### -verbose-paths +When displaying diagnostic output aim to display more detailed path information. In practice this is typically the complete 'canonical' path to the source file used. + + + +### -verify-debug-serial-ir +Verify IR in the front-end. + + + +### -dump-module +Disassemble and print the module IR. + + + +### -get-module-info +Print the name and version of a serialized IR Module + + + +### -get-supported-module-versions +Print the minimum and maximum module versions this compiler supports + + + + +## Repro + +Slang repro system related + + +### -dump-repro-on-error +Dump `.slang-repro` file on any compilation error. + + + +### -extract-repro + +**-extract-repro <name>** + +Extract the repro files into a folder. + + + +### -load-repro-directory + +**-load-repro-directory <path>** + +Use repro along specified path + + + +### -load-repro + +**-load-repro <name>** + +Load repro + + + +### -repro-file-system + +**-repro-file-system <name>** + +Use a repro as a file system + + + +### -dump-repro +Dump a `.slang-repro` file that can be used to reproduce a compilation on another machine. + + + + + +### -repro-fallback-directory + +**Specify a directory to use if a file isn't found in a repro. Should be specified *before* any repro usage such as `load-repro`. +There are two *special* directories: + + * 'none:' indicates no fallback, so if the file isn't found in the repro compliation will fail + * 'default:' is the default (which is the OS file system)** + + + + +## Experimental + +Experimental options (use at your own risk) + + +### -file-system + +**-file-system <[file-system-type](#file-system-type)>** + +Set the filesystem hook to use for a compile request. + + + +### -heterogeneous +Output heterogeneity-related code. + + + +### -no-mangle +Do as little mangling of names as possible. + + + +### -no-hlsl-binding +Do not include explicit parameter binding semantics in the output HLSL code,except for parameters that has explicit bindings in the input source. + + + +### -no-hlsl-pack-constant-buffer-elements +Do not pack elements of constant buffers into structs in the output HLSL code. + + + +### -validate-uniformity +Perform uniformity validation analysis. + + + +### -allow-glsl +Enable GLSL as an input language. + + + +### -enable-experimental-passes +Enable experimental compiler passes + + + +### -enable-experimental-dynamic-dispatch +Enable experimental dynamic dispatch features + + + +### -embed-downstream-ir +Embed downstream IR into emitted slang IR + + + +### -experimental-feature +Enable experimental features (loading builtin neural module) + + + +### -enable-experimental-rich-diagnostics +Enable experimental rich diagnostics with enhanced formatting and details + + + +### -enable-machine-readable-diagnostics +Enable machine-readable diagnostic output in tab-separated format + + + +### -diagnostic-color + +**-diagnostic-color <always|never|auto>** + +Control colored diagnostic output (auto uses color if stderr is a tty) + + + + +## Internal + +Internal-use options (use at your own risk) + + +### -archive-type + +**-archive-type <[archive-type](#archive-type)>** + +Set the archive type for [-save-core-module](#save-core-module). Default is zip. + + + +### -compile-core-module +Compile the core module from embedded sources. Will return a failure if there is already a core module available. + + + +### -doc +Write documentation for [-compile-core-module](#compile-core-module) + + + +### -ir-compression + +**-ir-compression <type>** + +Set compression for IR and AST outputs. + +Accepted compression types: none, lite + + + +### -load-core-module + +**-load-core-module <filename>** + +Load the core module from file. + + + +### -r + +**-r <name>** + +reference module <name> + + + +### -save-core-module + +**-save-core-module <filename>** + +Save the core module to an archive file. + + + +### -save-core-module-bin-source + +**-save-core-module-bin-source <filename>** + +Same as [-save-core-module](#save-core-module) but output the data as a C array. + + + + + +### -save-glsl-module-bin-source + +**-save-glsl-module-bin-source <filename>** + +Save the serialized glsl module as a C array. + + + + + +### -track-liveness +Enable liveness tracking. Places SLANG_LIVE_START, and SLANG_LIVE_END in output source to indicate value liveness. + + + +### -loop-inversion +Enable loop inversion in the code-gen optimization. Default is off + + + +### -whole-program +Generate code for all entry points in a single output (library mode). + + + + +## Deprecated + +Deprecated options (allowed but ignored; may be removed in future) + + +### -parameter-blocks-use-register-spaces +Parameter blocks will use register spaces + + + +### -zero-initialize +Initialize all variables to zero.Structs will set all struct-fields without an init expression to 0.All variables will call their default constructor if not explicitly initialized as usual. + + + + +## compiler + +Downstream Compilers (aka Pass through) + +* `none` : Unknown +* `fxc` : FXC HLSL compiler +* `dxc` : DXC HLSL compiler +* `glslang` : GLSLANG GLSL compiler +* `spirv-dis` : spirv-tools SPIRV disassembler +* `clang` : Clang C/C++ compiler +* `visualstudio`, `vs` : Visual Studio C/C++ compiler +* `gcc` : GCC C/C++ compiler +* `genericcpp`, `c`, `cpp` : A generic C++ compiler (can be any one of visual studio, clang or gcc depending on system and availability) +* `nvrtc` : NVRTC CUDA compiler +* `llvm` : LLVM/Clang `slang-llvm` +* `spirv-opt` : spirv-tools SPIRV optimizer +* `metal` : Metal shader compiler +* `tint` : Tint compiler + + +## language + +Language + +* `c`, `C` : C language +* `cpp`, `c++`, `C++`, `cxx` : C++ language +* `slang` : Slang language +* `glsl` : GLSL language +* `hlsl` : HLSL language +* `cu`, `cuda` : CUDA + + +## language-version + +Language Version + +* `legacy`, `default`, `2018` : Legacy Slang language +* `2025` : Slang language rules for 2025 and older +* `2026`, `latest` : Slang language rules for 2026 and newer + + +## archive-type + +Archive Type + +* `riff-deflate` : Slang RIFF using deflate compression +* `riff-lz4` : Slang RIFF using LZ4 compression +* `zip` : Zip file +* `riff` : Slang RIFF without compression + + +## line-directive-mode + +Line Directive Mode + +* `none` : Don't emit `#line` directives at all +* `source-map` : Use source map to track line associations (doen't emit #line) +* `default` : Default behavior +* `standard` : Emit standard C-style `#line` directives. +* `glsl` : Emit GLSL-style directives with file *number* instead of name. + + +## debug-info-format + +Debug Info Format + +* `default-format` : Use the default debugging format for the target +* `c7` : CodeView C7 format (typically means debugging infomation is embedded in the binary) +* `pdb` : Program database +* `stabs` : STABS debug format +* `coff` : COFF debug format +* `dwarf` : DWARF debug format + + +## fp-mode + +Floating Point Mode + +* `precise` : Disable optimization that could change the output of floating-point computations, including around infinities, NaNs, denormalized values, and negative zero. Prefer the most precise versions of special functions supported by the target. +* `fast` : Allow optimizations that may change results of floating-point computations. Prefer the fastest version of special functions supported by the target. +* `default` : Default floating point mode + + +## fp-denormal-mode + +Floating Point Denormal Handling Mode + +* `any` : Use any denormal handling mode (default). The mode used is implementation defined. +* `preserve` : Preserve denormal values +* `ftz` : Flush denormals to zero + + +## help-style + +Help Style + +* `text` : Text suitable for output to a terminal +* `markdown` : Markdown +* `no-link-markdown` : Markdown without links + + +## optimization-level + +Optimization Level + +* `0`, `none` : Disable all optimizations +* `1`, `default` : Enable a default level of optimization.This is the default if no [-o](#o) options are used. +* `2`, `high` : Enable aggressive optimizations for speed. +* `3`, `maximal` : Enable further optimizations, which might have a significant impact on compile time, or involve unwanted tradeoffs in terms of code size. + + +## debug-level + +Debug Level + +* `0`, `none` : Don't emit debug information at all. +* `1`, `minimal` : Emit as little debug information as possible, while still supporting stack traces. +* `2`, `standard` : Emit whatever is the standard level of debug information for each target. +* `3`, `maximal` : Emit as much debug information as possible for each target. + + +## file-system-type + +File System Type + +* `default` : Default file system. +* `load-file` : Just implements loadFile interface, so will be wrapped with CacheFileSystem internally. +* `os` : Use the OS based file system directly (without file system caching) + + +## source-embed-style + +Source Embed Style + +* `none` : No source level embedding +* `default` : The default embedding for the type to be embedded +* `text` : Embed as text. May change line endings. If output isn't text will use 'default'. Size will *not* contain terminating 0. +* `binary-text` : 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. + + +## target + +Target + +* `unknown` +* `none` +* `hlsl` : HLSL source code +* `dxbc` : DirectX shader bytecode binary +* `dxbc-asm`, `dxbc-assembly` : DirectX shader bytecode assembly +* `dxil` : DirectX Intermediate Language binary +* `dxil-asm`, `dxil-assembly` : DirectX Intermediate Language assembly +* `glsl` : GLSL(Vulkan) source code +* `spirv` : SPIR-V binary +* `spirv-asm`, `spirv-assembly` : SPIR-V assembly +* `c` : C source code +* `cpp`, `c++`, `cxx` : C++ source code +* `hpp` : C++ source header +* `torch`, `torch-binding`, `torch-cpp`, `torch-cpp-binding` : C++ for pytorch binding +* `host-cpp`, `host-c++`, `host-cxx` : C++ source for host execution +* `exe`, `executable` : Executable binary +* `shader-sharedlib`, `shader-sharedlibrary`, `shader-dll` : Shared library/Dll for shader kernel +* `sharedlib`, `sharedlibrary`, `dll` : Shared library/Dll for host execution +* `cuda`, `cu` : CUDA source code +* `cuh` : CUDA source header +* `ptx` : PTX assembly +* `cuobj`, `cubin` : CUDA binary +* `host-callable`, `callable` : Host callable +* `object-code`, `shader-object-code` : Object code for host execution (shader style) +* `host-host-callable` : Host callable for host execution +* `metal` : Metal shader source +* `metallib` : Metal Library Bytecode +* `metallib-asm` : Metal Library Bytecode assembly +* `wgsl` : WebGPU shading language source +* `wgsl-spirv-asm`, `wgsl-spirv-assembly` : SPIR-V assembly via WebGPU shading language +* `wgsl-spirv` : SPIR-V via WebGPU shading language +* `slangvm`, `slang-vm` : Slang VM byte code +* `host-object-code` : Object code for host execution (host style) +* `llvm-host-ir`, `llvm-ir` : LLVM IR assembly (host style) +* `llvm-shader-ir` : LLVM IR assembly (shader style) + + +## stage + +Stage + +* `vertex` +* `hull`, `tesscontrol` +* `domain`, `tesseval` +* `geometry` +* `pixel`, `fragment` +* `compute` +* `raygeneration` +* `intersection` +* `anyhit` +* `closesthit` +* `miss` +* `callable` +* `mesh` +* `amplification`, `task` +* `dispatch` + + +## vulkan-shift + +Vulkan Shift + +* `b` : Constant buffer view +* `s` : Sampler +* `t` : Shader resource view +* `u` : Unorderd access view + + +## capability + +A capability describes an optional feature that a target may or may not support. When a [-capability](#capability-1) is specified, the compiler may assume that the target supports that capability, and generate code accordingly. + +* `spirv_1_{ 0`, `1`, `2`, `3`, `4`, `5 }` : minimum supported SPIR - V version +* `textualTarget` +* `hlsl` +* `glsl` +* `c` +* `cpp` +* `cuda` +* `metal` +* `spirv` +* `wgsl` +* `slangvm` +* `llvm` +* `glsl_spirv_1_0` +* `glsl_spirv_1_1` +* `glsl_spirv_1_2` +* `glsl_spirv_1_3` +* `glsl_spirv_1_4` +* `glsl_spirv_1_5` +* `glsl_spirv_1_6` +* `metallib_2_3` +* `metallib_2_4` +* `metallib_3_0` +* `metallib_3_1` +* `hlsl_nvapi` +* `hlsl_2018` +* `optix_coopvec` +* `optix_multilevel_traversal` +* `vertex` +* `fragment` +* `compute` +* `hull` +* `domain` +* `geometry` +* `dispatch` +* `SPV_EXT_fragment_shader_interlock` : enables the SPV_EXT_fragment_shader_interlock extension +* `SPV_EXT_physical_storage_buffer` : enables the SPV_EXT_physical_storage_buffer extension +* `SPV_EXT_fragment_fully_covered` : enables the SPV_EXT_fragment_fully_covered extension +* `SPV_EXT_descriptor_indexing` : enables the SPV_EXT_descriptor_indexing extension +* `SPV_EXT_shader_atomic_float_add` : enables the SPV_EXT_shader_atomic_float_add extension +* `SPV_EXT_shader_atomic_float16_add` : enables the SPV_EXT_shader_atomic_float16_add extension +* `SPV_EXT_shader_atomic_float_min_max` : enables the SPV_EXT_shader_atomic_float_min_max extension +* `SPV_EXT_mesh_shader` : enables the SPV_EXT_mesh_shader extension +* `SPV_EXT_demote_to_helper_invocation` : enables the SPV_EXT_demote_to_helper_invocation extension +* `SPV_KHR_maximal_reconvergence` : enables the SPV_KHR_maximal_reconvergence extension +* `SPV_KHR_quad_control` : enables the SPV_KHR_quad_control extension +* `SPV_KHR_fragment_shader_barycentric` : enables the SPV_KHR_fragment_shader_barycentric extension +* `SPV_KHR_non_semantic_info` : enables the SPV_KHR_non_semantic_info extension +* `SPV_KHR_device_group` : enables the SPV_KHR_device_group extension +* `SPV_KHR_variable_pointers` : enables the SPV_KHR_variable_pointers extension +* `SPV_KHR_ray_tracing` : enables the SPV_KHR_ray_tracing extension +* `SPV_KHR_ray_query` : enables the SPV_KHR_ray_query extension +* `SPV_KHR_ray_tracing_position_fetch` : enables the SPV_KHR_ray_tracing_position_fetch extension +* `SPV_KHR_shader_clock` : enables the SPV_KHR_shader_clock extension +* `SPV_NV_shader_subgroup_partitioned` : enables the SPV_NV_shader_subgroup_partitioned extension +* `SPV_KHR_subgroup_rotate` : enables the SPV_KHR_subgroup_rotate extension +* `SPV_NV_ray_tracing_motion_blur` : enables the SPV_NV_ray_tracing_motion_blur extension +* `SPV_NV_shader_invocation_reorder` : enables the SPV_NV_shader_invocation_reorder extension +* `SPV_EXT_shader_invocation_reorder` : enables the SPV_EXT_shader_invocation_reorder extension +* `SPV_NV_cluster_acceleration_structure` : enables the SPV_NV_cluster_acceleration_structure extension +* `SPV_NV_linear_swept_spheres` : enables the SPV_NV_linear_swept_spheres extension +* `SPV_NV_shader_image_footprint` : enables the SPV_NV_shader_image_footprint extension +* `SPV_KHR_compute_shader_derivatives` : enables the SPV_KHR_compute_shader_derivatives extension +* `SPV_GOOGLE_user_type` : enables the SPV_GOOGLE_user_type extension +* `SPV_EXT_replicated_composites` : enables the SPV_EXT_replicated_composites extension +* `SPV_KHR_vulkan_memory_model` : enables the SPV_KHR_vulkan_memory_model extension +* `SPV_NV_cooperative_vector` : enables the SPV_NV_cooperative_vector extension +* `SPV_KHR_cooperative_matrix` : enables the SPV_KHR_cooperative_matrix extension +* `SPV_NV_tensor_addressing` : enables the SPV_NV_tensor_addressing extension +* `SPV_NV_cooperative_matrix2` : enables the SPV_NV_cooperative_matrix2 extension +* `SPV_NV_bindless_texture` : enables the SPV_NV_bindless_texture extension +* `SPV_EXT_float8` : enables the SPV_EXT_float8 extension +* `SPV_KHR_bfloat16` : enables the SPV_KHR_bfloat16 extension +* `spvDeviceGroup` +* `spvAtomicFloat32AddEXT` +* `spvAtomicFloat16AddEXT` +* `spvAtomicFloat64AddEXT` +* `spvInt64Atomics` +* `spvAtomicFloat32MinMaxEXT` +* `spvAtomicFloat16MinMaxEXT` +* `spvAtomicFloat64MinMaxEXT` +* `spvDerivativeControl` +* `spvImageQuery` +* `spvImageGatherExtended` +* `spvSparseResidency` +* `spvImageFootprintNV` +* `spvMinLod` +* `spvFloat8EXT` +* `spvBFloat16KHR` +* `spvFragmentShaderPixelInterlockEXT` +* `spvFragmentBarycentricKHR` +* `spvFragmentFullyCoveredEXT` +* `spvGroupNonUniformBallot` +* `spvGroupNonUniformShuffle` +* `spvGroupNonUniformArithmetic` +* `spvGroupNonUniformQuad` +* `spvGroupNonUniformVote` +* `spvGroupNonUniformPartitionedNV` +* `spvGroupNonUniformRotateKHR` +* `spvRayTracingMotionBlurNV` +* `spvMeshShadingEXT` +* `spvRayTracingKHR` +* `spvRayTracingPositionFetchKHR` +* `spvRayQueryKHR` +* `spvRayQueryPositionFetchKHR` +* `spvShaderInvocationReorderNV` +* `spvShaderInvocationReorderEXT` +* `spvRayTracingClusterAccelerationStructureNV` +* `spvRayTracingLinearSweptSpheresGeometryNV` +* `spvShaderClockKHR` +* `spvShaderNonUniformEXT` +* `spvShaderNonUniform` +* `spvDemoteToHelperInvocationEXT` +* `spvDemoteToHelperInvocation` +* `spvReplicatedCompositesEXT` +* `spvCooperativeVectorNV` +* `spvCooperativeVectorTrainingNV` +* `spvCooperativeMatrixKHR` +* `spvCooperativeMatrixReductionsNV` +* `spvCooperativeMatrixConversionsNV` +* `spvCooperativeMatrixPerElementOperationsNV` +* `spvCooperativeMatrixTensorAddressingNV` +* `spvCooperativeMatrixBlockLoadsNV` +* `spvTensorAddressingNV` +* `spvMaximalReconvergenceKHR` +* `spvQuadControlKHR` +* `spvVulkanMemoryModelKHR` +* `spvVulkanMemoryModelDeviceScopeKHR` +* `spvBindlessTextureNV` +* `ser_hlsl_native` +* `metallib_latest` +* `dxil_lib` +* `any_target` +* `any_textual_target` +* `any_gfx_target` +* `any_cpp_target` +* `cpp_cuda` +* `cpp_llvm` +* `cpp_cuda_llvm` +* `cpp_cuda_spirv` +* `cpp_cuda_spirv_llvm` +* `cpp_cuda_metal_spirv` +* `cuda_spirv` +* `cpp_cuda_glsl_spirv` +* `cpp_cuda_glsl_hlsl` +* `cpp_cuda_glsl_hlsl_llvm` +* `cpp_cuda_glsl_hlsl_spirv` +* `cpp_cuda_glsl_hlsl_spirv_llvm` +* `cpp_cuda_glsl_hlsl_spirv_wgsl` +* `cpp_cuda_glsl_hlsl_spirv_wgsl_llvm` +* `cpp_cuda_glsl_hlsl_metal_spirv` +* `cpp_cuda_glsl_hlsl_metal_spirv_llvm` +* `cpp_cuda_glsl_hlsl_metal_spirv_wgsl` +* `cpp_cuda_glsl_hlsl_metal_spirv_wgsl_llvm` +* `cpp_cuda_hlsl` +* `cpp_cuda_hlsl_spirv` +* `cpp_cuda_hlsl_metal_spirv` +* `cpp_glsl` +* `cpp_glsl_hlsl_spirv` +* `cpp_glsl_hlsl_spirv_wgsl` +* `cpp_glsl_hlsl_metal_spirv` +* `cpp_glsl_hlsl_metal_spirv_wgsl` +* `cpp_hlsl` +* `cuda_glsl_hlsl` +* `cuda_hlsl_metal_spirv` +* `cuda_glsl_hlsl_spirv` +* `cuda_glsl_hlsl_spirv_llvm` +* `cuda_glsl_hlsl_spirv_wgsl` +* `cuda_glsl_hlsl_metal_spirv` +* `cuda_glsl_hlsl_metal_spirv_wgsl` +* `cuda_glsl_spirv` +* `cuda_glsl_metal_spirv` +* `cuda_glsl_metal_spirv_wgsl` +* `cuda_glsl_metal_spirv_wgsl_llvm` +* `cuda_hlsl` +* `cuda_hlsl_spirv` +* `glsl_hlsl_spirv` +* `glsl_hlsl_spirv_wgsl` +* `glsl_hlsl_metal_spirv` +* `glsl_hlsl_metal_spirv_wgsl` +* `glsl_metal_spirv` +* `glsl_metal_spirv_wgsl` +* `glsl_spirv` +* `glsl_spirv_wgsl` +* `hlsl_spirv` +* `SPV_NV_compute_shader_derivatives` : enables the SPV_NV_compute_shader_derivatives extension +* `spvShaderInvocationReorderMotionNV` +* `spvShaderInvocationReorderMotionEXT` +* `GL_EXT_buffer_reference` : enables the GL_EXT_buffer_reference extension +* `GL_EXT_buffer_reference_uvec2` : enables the GL_EXT_buffer_reference_uvec2 extension +* `GL_EXT_debug_printf` : enables the GL_EXT_debug_printf extension +* `GL_EXT_demote_to_helper_invocation` : enables the GL_EXT_demote_to_helper_invocation extension +* `GL_EXT_maximal_reconvergence` : enables the GL_EXT_maximal_reconvergence extension +* `GL_EXT_shader_quad_control` : enables the GL_EXT_shader_quad_control extension +* `GL_EXT_device_group` : enables the GL_EXT_device_group extension +* `GL_EXT_fragment_shader_barycentric` : enables the GL_EXT_fragment_shader_barycentric extension +* `GL_EXT_mesh_shader` : enables the GL_EXT_mesh_shader extension +* `GL_EXT_nonuniform_qualifier` : enables the GL_EXT_nonuniform_qualifier extension +* `GL_EXT_ray_query` : enables the GL_EXT_ray_query extension +* `GL_EXT_ray_tracing` : enables the GL_EXT_ray_tracing extension +* `GL_EXT_ray_tracing_position_fetch_ray_tracing` : enables the GL_EXT_ray_tracing_position_fetch_ray_tracing extension +* `GL_EXT_ray_tracing_position_fetch_ray_query` : enables the GL_EXT_ray_tracing_position_fetch_ray_query extension +* `GL_EXT_ray_tracing_position_fetch` : enables the GL_EXT_ray_tracing_position_fetch extension +* `GL_EXT_samplerless_texture_functions` : enables the GL_EXT_samplerless_texture_functions extension +* `GL_EXT_shader_atomic_float` : enables the GL_EXT_shader_atomic_float extension +* `GL_EXT_shader_atomic_float_min_max` : enables the GL_EXT_shader_atomic_float_min_max extension +* `GL_EXT_shader_atomic_float2` : enables the GL_EXT_shader_atomic_float2 extension +* `GL_EXT_shader_atomic_int64` : enables the GL_EXT_shader_atomic_int64 extension +* `GL_EXT_shader_explicit_arithmetic_types` : enables the GL_EXT_shader_explicit_arithmetic_types extension +* `GL_EXT_shader_explicit_arithmetic_types_int64` : enables the GL_EXT_shader_explicit_arithmetic_types_int64 extension +* `GL_EXT_shader_image_load_store` : enables the GL_EXT_shader_image_load_store extension +* `GL_EXT_shader_realtime_clock` : enables the GL_EXT_shader_realtime_clock extension +* `GL_EXT_texture_query_lod` : enables the GL_EXT_texture_query_lod extension +* `GL_EXT_texture_shadow_lod` : enables the GL_EXT_texture_shadow_lod extension +* `GL_ARB_derivative_control` : enables the GL_ARB_derivative_control extension +* `GL_ARB_fragment_shader_interlock` : enables the GL_ARB_fragment_shader_interlock extension +* `GL_ARB_gpu_shader5` : enables the GL_ARB_gpu_shader5 extension +* `GL_ARB_shader_image_load_store` : enables the GL_ARB_shader_image_load_store extension +* `GL_ARB_shader_image_size` : enables the GL_ARB_shader_image_size extension +* `GL_ARB_texture_multisample` : enables the GL_ARB_texture_multisample extension +* `GL_ARB_shader_texture_image_samples` : enables the GL_ARB_shader_texture_image_samples extension +* `GL_ARB_sparse_texture` : enables the GL_ARB_sparse_texture extension +* `GL_ARB_sparse_texture2` : enables the GL_ARB_sparse_texture2 extension +* `GL_ARB_sparse_texture_clamp` : enables the GL_ARB_sparse_texture_clamp extension +* `GL_ARB_texture_gather` : enables the GL_ARB_texture_gather extension +* `GL_ARB_texture_query_levels` : enables the GL_ARB_texture_query_levels extension +* `GL_ARB_shader_clock` : enables the GL_ARB_shader_clock extension +* `GL_ARB_shader_clock64` : enables the GL_ARB_shader_clock64 extension +* `GL_ARB_gpu_shader_int64` : enables the GL_ARB_gpu_shader_int64 extension +* `GL_KHR_memory_scope_semantics` : enables the GL_KHR_memory_scope_semantics extension +* `GL_KHR_shader_subgroup_arithmetic` : enables the GL_KHR_shader_subgroup_arithmetic extension +* `GL_KHR_shader_subgroup_ballot` : enables the GL_KHR_shader_subgroup_ballot extension +* `GL_KHR_shader_subgroup_basic` : enables the GL_KHR_shader_subgroup_basic extension +* `GL_KHR_shader_subgroup_clustered` : enables the GL_KHR_shader_subgroup_clustered extension +* `GL_KHR_shader_subgroup_quad` : enables the GL_KHR_shader_subgroup_quad extension +* `GL_KHR_shader_subgroup_shuffle` : enables the GL_KHR_shader_subgroup_shuffle extension +* `GL_KHR_shader_subgroup_shuffle_relative` : enables the GL_KHR_shader_subgroup_shuffle_relative extension +* `GL_KHR_shader_subgroup_vote` : enables the GL_KHR_shader_subgroup_vote extension +* `GL_KHR_shader_subgroup_rotate` : enables the GL_KHR_shader_subgroup_rotate extension +* `GL_NV_compute_shader_derivatives` : enables the GL_NV_compute_shader_derivatives extension +* `GL_NV_fragment_shader_barycentric` : enables the GL_NV_fragment_shader_barycentric extension +* `GL_NV_gpu_shader5` : enables the GL_NV_gpu_shader5 extension +* `GL_NV_ray_tracing` : enables the GL_NV_ray_tracing extension +* `GL_NV_ray_tracing_motion_blur` : enables the GL_NV_ray_tracing_motion_blur extension +* `GL_NV_shader_atomic_fp16_vector` : enables the GL_NV_shader_atomic_fp16_vector extension +* `GL_NV_shader_invocation_reorder` : enables the GL_NV_shader_invocation_reorder extension +* `GL_EXT_shader_invocation_reorder` : enables the GL_EXT_shader_invocation_reorder extension +* `GL_NV_shader_invocation_reorder_motion` : enables the GL_NV_shader_invocation_reorder_motion extension +* `GL_EXT_shader_invocation_reorder_motion` : enables the GL_EXT_shader_invocation_reorder_motion extension +* `GL_NV_shader_subgroup_partitioned` : enables the GL_NV_shader_subgroup_partitioned extension +* `GL_NV_shader_texture_footprint` : enables the GL_NV_shader_texture_footprint extension +* `GL_NV_cluster_acceleration_structure` : enables the GL_NV_cluster_acceleration_structure extension +* `GL_NV_cooperative_vector` : enables the GL_NV_cooperative_vector extension +* `nvapi` +* `raytracing` +* `ser_nvapi` +* `ser_dxr` +* `ser` +* `ser_nv` +* `motionblur_nv` +* `rayquery` +* `raytracing_motionblur` +* `ser_motion` +* `ser_nv_motion` +* `shaderclock` +* `fragmentshaderinterlock` +* `atomic64` +* `atomicfloat` +* `atomicfloat2` +* `fragmentshaderbarycentric` +* `shadermemorycontrol` +* `bufferreference` +* `bufferreference_int64` +* `cooperative_vector` +* `cooperative_vector_training` +* `cooperative_matrix` +* `cooperative_matrix_spirv` +* `cooperative_matrix_reduction` +* `cooperative_matrix_conversion` +* `cooperative_matrix_map_element` +* `cooperative_matrix_tensor_addressing` +* `cooperative_matrix_block_load` +* `tensor_addressing` +* `cooperative_matrix_2` +* `vk_mem_model` +* `descriptor_handle` +* `pixel` +* `tesscontrol` +* `tesseval` +* `raygen` +* `raygeneration` +* `intersection` +* `anyhit` +* `closesthit` +* `callable` +* `miss` +* `mesh` +* `task` +* `amplification` +* `any_stage` +* `amplification_mesh` +* `raytracing_stages` +* `anyhit_closesthit` +* `anyhit_intersection` +* `raygen_closesthit_miss` +* `anyhit_closesthit_intersection` +* `anyhit_closesthit_intersection_miss` +* `raygen_closesthit_miss_callable` +* `compute_tesscontrol_tesseval` +* `compute_fragment` +* `compute_fragment_geometry_vertex` +* `domain_hull` +* `raytracingstages_fragment` +* `raytracingstages_compute` +* `raytracingstages_compute_amplification_mesh` +* `raytracingstages_compute_fragment` +* `raytracingstages_compute_fragment_geometry_vertex` +* `meshshading` +* `shadermemorycontrol_compute` +* `subpass` +* `spirv_latest` +* `SPIRV_1_0` +* `SPIRV_1_1` +* `SPIRV_1_2` +* `SPIRV_1_3` +* `SPIRV_1_4` +* `SPIRV_1_5` +* `SPIRV_1_6` +* `sm_4_0_version` +* `sm_4_0` +* `sm_4_1_version` +* `sm_4_1` +* `sm_5_0_version` +* `sm_5_0` +* `sm_5_1_version` +* `sm_5_1` +* `sm_6_0_version` +* `sm_6_0` +* `sm_6_1_version` +* `sm_6_1` +* `sm_6_2_version` +* `sm_6_2` +* `sm_6_3_version` +* `sm_6_3` +* `sm_6_4_version` +* `sm_6_4` +* `sm_6_5_version` +* `sm_6_5` +* `sm_6_6_version` +* `sm_6_6` +* `sm_6_7_version` +* `sm_6_7` +* `sm_6_8_version` +* `sm_6_8` +* `sm_6_9_version` +* `sm_6_9` +* `DX_4_0` +* `DX_4_1` +* `DX_5_0` +* `DX_5_1` +* `DX_6_0` +* `DX_6_1` +* `DX_6_2` +* `DX_6_3` +* `DX_6_4` +* `DX_6_5` +* `DX_6_6` +* `DX_6_7` +* `DX_6_8` +* `DX_6_9` +* `GLSL_130` : enables the GLSL_130 extension +* `GLSL_140` : enables the GLSL_140 extension +* `GLSL_150` : enables the GLSL_150 extension +* `GLSL_330` : enables the GLSL_330 extension +* `GLSL_400` : enables the GLSL_400 extension +* `GLSL_410` : enables the GLSL_410 extension +* `GLSL_420` : enables the GLSL_420 extension +* `GLSL_430` : enables the GLSL_430 extension +* `GLSL_440` : enables the GLSL_440 extension +* `GLSL_450` : enables the GLSL_450 extension +* `GLSL_460` : enables the GLSL_460 extension +* `GLSL_410_SPIRV_1_0` : enables the GLSL_410_SPIRV_1_0 extension +* `GLSL_420_SPIRV_1_0` : enables the GLSL_420_SPIRV_1_0 extension +* `GLSL_430_SPIRV_1_0` : enables the GLSL_430_SPIRV_1_0 extension +* `cuda_sm_1_0` +* `cuda_sm_2_0` +* `cuda_sm_3_0` +* `cuda_sm_3_5` +* `cuda_sm_4_0` +* `cuda_sm_5_0` +* `cuda_sm_6_0` +* `cuda_sm_7_0` +* `cuda_sm_8_0` +* `cuda_sm_9_0` +* `atomic_reduce` +* `atomic_bfloat16` +* `METAL_2_3` +* `METAL_2_4` +* `METAL_3_0` +* `METAL_3_1` +* `appendstructuredbuffer` +* `atomic_hlsl` +* `atomic_hlsl_nvapi` +* `atomic_hlsl_sm_6_6` +* `byteaddressbuffer` +* `byteaddressbuffer_rw` +* `consumestructuredbuffer` +* `structuredbuffer` +* `structuredbuffer_rw` +* `implicit_derivatives_sampling` +* `fragmentprocessing` +* `fragmentprocessing_derivativecontrol` +* `getattributeatvertex` +* `memorybarrier` +* `texture_sm_4_0` +* `texture_sm_4_1` +* `texture_sm_4_1_samplerless` +* `texture_sm_4_1_compute_fragment` +* `texture_sm_4_0_fragment` +* `texture_sm_4_1_clamp_fragment` +* `texture_sm_4_1_vertex_fragment_geometry` +* `texture_gather` +* `image_samples` +* `image_size` +* `texture_size` +* `texture_querylod` +* `texture_querylevels` +* `texture_shadowlod` +* `texture_shadowgrad` +* `atomic_glsl_float1` +* `atomic_glsl_float2` +* `atomic_glsl_halfvec` +* `atomic_glsl` +* `atomic_glsl_int64` +* `GLSL_430_SPIRV_1_0_compute` : enables the GLSL_430_SPIRV_1_0_compute extension +* `image_loadstore` +* `nonuniformqualifier` +* `printf` +* `texturefootprint` +* `texturefootprintclamp` +* `shader5_sm_4_0` +* `shader5_sm_5_0` +* `pack_vector` +* `subgroup_basic` +* `subgroup_ballot` +* `subgroup_ballot_activemask` +* `subgroup_basic_ballot` +* `subgroup_vote` +* `shaderinvocationgroup` +* `subgroup_arithmetic` +* `subgroup_shuffle` +* `subgroup_shufflerelative` +* `subgroup_clustered` +* `subgroup_quad` +* `subgroup_partitioned` +* `subgroup_rotate` +* `atomic_glsl_hlsl_nvapi_cuda_metal_float1` +* `atomic_glsl_hlsl_nvapi_cuda5_int64` +* `atomic_glsl_hlsl_nvapi_cuda6_int64` +* `atomic_glsl_hlsl_nvapi_cuda9_int64` +* `atomic_glsl_hlsl_cuda_metal` +* `atomic_glsl_hlsl_cuda9_int64` +* `helper_lane` +* `quad_control` +* `breakpoint` +* `raytracing_allstages` +* `raytracing_anyhit` +* `raytracing_intersection` +* `raytracing_anyhit_closesthit` +* `raytracing_lss` +* `raytracing_lss_ho` +* `raytracing_anyhit_closesthit_intersection` +* `raytracing_object_space_ray` +* `raytracing_raygen_closesthit_miss` +* `raytracing_anyhit_closesthit_intersection_miss` +* `raytracing_raygen_closesthit_miss_callable` +* `raytracing_position` +* `raytracing_motionblur_anyhit_closesthit_intersection_miss` +* `raytracing_motionblur_raygen_closesthit_miss` +* `rayquery_position` +* `ser_raygen` +* `ser_raygen_closesthit_miss` +* `ser_nv_raygen` +* `ser_nv_raygen_closesthit_miss` +* `ser_nv_motion_raygen_closesthit_miss` +* `ser_any_closesthit_intersection_miss` +* `ser_anyhit_closesthit_intersection` +* `ser_anyhit_closesthit` +* `ser_motion_raygen_closesthit_miss` +* `ser_motion_raygen` +* `ser_dxr_raygen_closesthit_miss` +* `ser_dxr_raygen` +* `all` + + +## file-extension + +A [<language>](#language), <format>, and/or [<stage>](#stage) may be inferred from the extension of an input or [-o](#o) path + +* `hlsl`, `fx` : hlsl +* `dxbc` +* `dxbc-asm` : dxbc-assembly +* `dxil` +* `dxil-asm` : dxil-assembly +* `glsl` +* `vert` : glsl (vertex) +* `frag` : glsl (fragment) +* `geom` : glsl (geoemtry) +* `tesc` : glsl (hull) +* `tese` : glsl (domain) +* `comp` : glsl (compute) +* `mesh` : glsl (mesh) +* `task` : glsl (amplification) +* `slang` +* `spv` : SPIR-V +* `spv-asm` : SPIR-V assembly +* `c` +* `cpp`, `c++`, `cxx` : C++ +* `hpp` : C++ Header +* `exe` : executable +* `dll`, `so` : sharedlibrary/dll +* `cu` : CUDA +* `cuh` : CUDA Header +* `ptx` : PTX +* `obj`, `o` : object-code +* `zip` : container +* `slang-module`, `slang-library` : Slang Module/Library +* `dir` : Container as a directory + + +## help-category + +Available help categories for the [-h](#h) option + +* `General` : General options +* `Target` : Target code generation options +* `Downstream` : Downstream compiler options +* `Debugging` : Compiler debugging/instrumentation options +* `Repro` : Slang repro system related +* `Experimental` : Experimental options (use at your own risk) +* `Internal` : Internal-use options (use at your own risk) +* `Deprecated` : Deprecated options (allowed but ignored; may be removed in future) +* `compiler` : Downstream Compilers (aka Pass through) +* `language` : Language +* `language-version` : Language Version +* `archive-type` : Archive Type +* `line-directive-mode` : Line Directive Mode +* `debug-info-format` : Debug Info Format +* `fp-mode` : Floating Point Mode +* `fp-denormal-mode` : Floating Point Denormal Handling Mode +* `help-style` : Help Style +* `optimization-level` : Optimization Level +* `debug-level` : Debug Level +* `file-system-type` : File System Type +* `source-embed-style` : Source Embed Style +* `target` : Target +* `stage` : Stage +* `vulkan-shift` : Vulkan Shift +* `capability` : A capability describes an optional feature that a target may or may not support. When a [-capability](#capability-1) is specified, the compiler may assume that the target supports that capability, and generate code accordingly. +* `file-extension` : A [<language>](#language), <format>, and/or [<stage>](#stage) may be inferred from the extension of an input or [-o](#o) path +* `help-category` : Available help categories for the [-h](#h) option + diff --git a/lib/All/slang/share/doc/slang/cpu-target.md b/lib/All/slang/share/doc/slang/cpu-target.md new file mode 100644 index 0000000..c2c80b1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/cpu-target.md @@ -0,0 +1,650 @@ +Slang CPU Target Support +======================== + +Slang has preliminary support for producing CPU source and binaries. + +# Features + +* Can compile C/C++/Slang source to binaries (executables, shared libraries or [directly executable](#host-callable)) +* Does *not* require a C/C++ compiler to be installed if [slang-llvm](#slang-llvm) is available (as distributed with slang binary distributions) +* Can compile Slang source into C++ source code +* Supports compute style shaders + +# Limitations + +These limitations apply to Slang transpiling to C++. + +* Barriers are not supported (making these work would require an ABI change) +* Atomics are not currently supported +* Limited support for [out of bounds](#out-of-bounds) accesses handling +* Entry point/s cannot be named `main` (this is because downstream C++ compiler/s expecting a regular `main`) +* `float16_t` type is not currently supported + +For current C++ source output, the compiler needs to support partial specialization. + +# How it works + +The initial version works by using a 'downstream' C/C++ compiler. A C++ compiler does *not* in general need to be installed on a system to compile and execute code as long as [slang-llvm](#slang-llvm) is available. A [regular C/C++](#regular-cpp) compiler can also be used, allowing access to tooling, such as profiling and debuggers, as well as being able to use regular host development features such as linking, libraries, shared libraries/dlls and executables. + +The C/C++ backend can be directly accessed much like 'dxc', 'fxc' of 'glslang' can, using the pass-through mechanism with the following new backends... + +``` +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_LLVM, ///< slang-llvm 'compiler' - includes LLVM and Clang +SLANG_PASS_THROUGH_GENERIC_C_CPP, ///< Generic C or C++ compiler, which is decided by the source type +``` + +Sometimes it is not important which C/C++ compiler is used, and this can be specified via the 'Generic C/C++' option. This will aim to use the compiler that is most likely binary compatible with the compiler that was used to build the Slang binary being used. + +To make it possible for Slang to produce CPU code, in this first iteration we convert Slang code into C/C++ which can subsequently be compiled into CPU code. If source is desired instead of a binary this can be specified via the SlangCompileTarget. These can be specified on the `slangc` command line as `-target cpp`. + +When using the 'pass through' mode for a CPU based target it is currently necessary to set an entry point, even though it's basically ignored. + +In the API the `SlangCompileTarget`s are + +``` +SLANG_C_SOURCE ///< The C language +SLANG_CPP_SOURCE ///< The C++ language +SLANG_CPP_HEADER ///< The C++ language (header) +SLANG_HOST_CPP_SOURCE, ///< C++ code for `host` style +``` + +Using the `-target` command line option + +* `C_SOURCE`: c +* `CPP_SOURCE`: cpp,c++,cxx +* `CPP_HEADER`: hpp +* `HOST_CPP_SOURCE`: host-cpp,host-c++,host-cxx + +Note! Output of C source is not currently supported. + +If a CPU binary is required this can be specified as a `SlangCompileTarget` of + +``` +SLANG_EXECUTABLE ///< Executable (for hosting CPU/OS) +SLANG_SHADER_SHARED_LIBRARY ///< A shared library/Dll (for hosting CPU/OS) +SLANG_SHADER_HOST_CALLABLE ///< A CPU target that makes `compute kernel` compiled code available to be run immediately +SLANG_HOST_HOST_CALLABLE ///< A CPU target that makes `scalar` compiled code available to be run immediately +SLANG_OBJECT_CODE, ///< Object code that can be used for later linking +``` + +Using the `-target` command line option + +* `EXECUTABLE`: exe, executable +* `SHADER_SHARED_LIBRARY`: sharedlib, sharedlibrary, dll +* `SHADER_HOST_CALLABLE`: callable, host-callable +* `OBJECT_CODE`: object-conde +* `HOST_HOST_CALLABLE`: host-host-callable + +Using `host-callable` types from the the command line, other than to test such code compile and can be loaded for host execution. + +For launching a [shader like](#compile-style) Slang code on the CPU, there typically needs to be binding of values passed the entry point function. How this works is described in the [ABI section](#abi). Functions *can* be executed directly but care must be taken to [export](#visibility) them and such that there isn't an issue with [context threading](#context-threading). + +If a binary target is requested, the binary contents can be returned in a ISlangBlob just like for other targets. When using a [regular C/C++ compiler](#regular-cpp) the CPU binary typically must be saved as a file and then potentially marked for execution by the OS. It may be possible to load shared libraries or dlls from memory - but doing so is a non standard feature, that requires unusual work arounds. If possible it is typically fastest and easiest to use [slang-llvm](#slang-llvm) to directly execute slang or C/C++ code. + +## Compilation Styles + +There are currently two styles of *compilation style* supported - `host` and `shader`. + +The `shader` style implies + +* The code *can* be executed in a GPU-kernel like execution model, launched across multiple threads (as described in the [ABI](#abi)) +* Currently no reference counting +* Only functionality from the Slang core module, built in HLSL or anything supplied by a [COM interfaces](#com-interface) is available +* Currently [slang-llvm](#slang-llvm) only supports the `shader` style + +The `host` style implies + +* Execution style is akin to more regular CPU scalar code +* Typically requires linking with `slang-rt` and use of `slang-rt` types such as `Slang::String` +* Allows use of `new` +* Allows the use of `class` for reference counted types +* COM interfaces are reference counted + +The styles as used with [host-callable](#host-callable) are indicated via the API by + +``` +SLANG_SHADER_HOST_CALLABLE ///< A CPU target that makes `compute kernel` compiled code available to be run immediately +SLANG_HOST_HOST_CALLABLE ///< A CPU target that makes `scalar` compiled code available to be run immediately +``` + +Or via the `-target` command line options + +* For 'shader' `callable` `host-callable` +* For 'host' `host-host-callable` + +For an example of the `host` style please look at "examples/cpu-hello-world". + +## Host callable + +Slang supports `host-callable` compilation targets which allow for the direct execution of the compiled code on the CPU. Currently this style of execution is supported if [slang-llvm](#slang-llvm) or a [regular C/C++ compiler](#regular-cpp) are available. + +There are currently two [compilation styles](#compile-style) supported. + +In order to call into `host-callable` code after compilation it's necessary to access the result via the `ISlangSharedLibrary` interface. + +Please look at the [ABI](#abi) section for more specifics around ABI usage especially for `shader` [compile styles](#compile-style). + +```C++ + slang::ICompileRequest* request = ...; + + const SlangResult compileRes = request->compile(); + + // Even if there were no errors that forced compilation to fail, the + // compiler may have produced "diagnostic" output such as warnings. + // We will go ahead and print that output here. + // + 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). + ComPtr sharedLibrary; + SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef())); + + // We can now find exported functions/variables via findSymbolAddressByName + + // For a __global public __extern_cpp int myGlobal; + { + auto myGlobalPtr = (int*)sharedLibrary->findSymbolAddressByName("myGlobal"); + if (myGlobalPtr) + { + *myGlobalPtr = 10; + } + } + + // To get a function + // + // public __extern_cpp int add(int a, int b); + + // Test a free function + { + typedef int (*AddFunc)(int a, int b); + auto func = (AddFunc)sharedLibrary->findFuncByName("add"); + + if (func) + { + // Let's add! + int c = func(10, 20): + } + } +``` + +## slang-llvm + +`slang-llvm` is a special Slang version of [LLVM](https://llvm.org/). It's current main purpose is to allow compiling C/C++ such that it is [directly available](#host-callable) for execution using the LLVM JIT feature. If `slang-llvm` is available it is the default downstream compiler for [host-callable](#host-callable). This is because it allows for faster compilation, avoids the file system, and can execute the compiled code directly. [Regular C/C++ compilers](#regular-cpp) can be used for [host-callable](#host-callable) but requires writing source files to the file system and creating/loading shared-libraries/dlls to make the feature work. Additionally using `slang-llvm` avoids the need for a C/C++ compiler installed on a target system. + +`slang-llvm` contains the Clang C++ compiler, so it is possible to also compile and execute C/C++ code in the [host-callable](#host-callable) style. + +Limitations of using `slang-llvm` + +* Can only currently be used for [shader style](#compile-style) + * Cannot produce object files, libraries, OS executables or binaries +* Is *limited* because it is not possible to directly access libraries such as the C or C++ standard libraries (see [COM interface](#com-interface) for a work-around) +* It's not possible to source debug into `slang-llvm` compiled code running on the JIT (see [debugging](#debugging) for a work-around) +* Not currently possible to return as a ISlangBlob representation + +You can detect if `slang-llvm` is available via + +```C++ + slang::IGlobalSession* slangSession = ...; + const bool hasSlangLlvm = SLANG_SUCCEEDED(slangSession->checkPassThroughSupport(SLANG_PASS_THROUGH_LLVM)); +``` + +## Regular C/C++ compilers + +Slang can work with regular C/C++ 'downstream' compilers. It has been tested to work with Visual Studio, Clang and G++/Gcc on Windows and Linux. + +Under the covers when Slang is used to generate a binary via a C/C++ compiler, it must do so through the file system. Currently this means the source (say generated by Slang) and the binary (produced by the C/C++ compiler) must all be files. To make this work Slang uses temporary files. The reasoning for hiding this mechanism, other than simplicity, is that it allows using with [slang-llvm](#slang-llvm) without any changes. + +## Visibility + +In a typical Slang [shader like](#compile-style) scenario, functionality is exposed via entry points. It can be convenient and desirable to be able to call Slang functions directly from application code, and not just via entry points. By default non entry point functions are *removed* if they are not reachable by the specified entry point. Additionally for non entry point functions Slang typically generates function names that differ from the original name. + +To work around these two issues the `public` and `__extern_cpp` modifiers can be used. + +`public` makes the variable or function visible outside of the module even if it isn't used within the module. For the function to work it will also keep around any function or variable it accesses. + +Note! Some care is needed here around [context threading](#context-threading) - if a function or any function a function accesses requires state held in the context, the signature of the function will be altered to include the context as the first parameter. + +Making a function or variable `public` does not mean that the name remains the same. To indicate that the name should not be altered use the `__extern_cpp` modifier. For example + +``` +// myGlobal will be visible to the application (note the __global modifier additionally means it has C++ global behavior) +__global public __extern_cpp int myGlobal; + +// myFunc is available to the application +public __extern_cpp myFunc(int a) +{ + return a * a; +} +``` + +## COM interface support + +Slang has preliminary support for [Component Object Model (COM)](https://en.wikipedia.org/wiki/Component_Object_Model) interfaces in CPU code. + +``` +[COM] +interface IDoThings +{ + int doThing(int a, int b); + int calcHash(NativeString in); + void printMessage(NativeString nativeString); +} +``` + +This support provides a way for an application to provide access to functionality in the application runtime - essentially it allows Slang code to call into application code. To do this a COM interface can be created that exposes the desired functionality. The interface/s can be made available through any of the normal mechanisms - such as through a constant buffer variable. Additionally [`__global`](#actual-global) provides a way to make functions available to Slang code without the need for [context threading](#context-threading). + +The example "examples/cpu-com-example" shows this at work. + +## Global support + +The Slang language is based on the HLSL language. This heritage means that globals have slightly different meaning to typical C/C++ usage. + +``` +int myGlobal; ///< A constant value stored in a constant buffer +static int staticMyGlobal; ///< A global that cannot be seen by the application +static const int staticConstMyGlobal; ///< A fixed value +``` + +The variable `myGlobal` will be a member of a constant buffer, meaning it's value can only change via bindings and not during execution. For some uses having `myGlobal` in the constant buffer might be appropriate, for example + +* It's use is reached from a [shader style](#compile-style) entry point +* It's value is constant across the launch + +In Slang a variable can be declared as global in the C/C++ sense via the `__global` modifier. For example + +``` +__global int myGlobal; +``` + +Doing so means + +* `myGlobal` will not be defined in the constant buffer +* It can be used in functions that do not have access to the [constant buffer](#context-threading) +* It can be modified in the kernel +* Can only be used on CPU targets (currently `__global` is not supported on the GPU targets) + +One disadvantage of using `__global` is in multi-threaded environments, with multiple launches on multiple CPU threads, there is only one global and will likely cause problems unless the global value is the same across all threads. + +It may be useful to set a global directly via host code, without having to write a function to enable the access. This is possible by using [`public`](#visibility) and [`__extern_cpp`](#visibility) modifiers. For example + +``` +__global public __extern_cpp int myGlobal; +``` + +The global can now be set from host code via + +```C++ + slang::ICompileRequest = ...; + + // 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())); + + // Set myGlobal to 20 + { + auto myGlobalPtr = (int*)sharedLibrary->findSymbolAddressByName("myGlobal"); + *myGlobalPtr = 20; + } +``` + +In terms of reflection `__global` variables are not visible. + +## NativeString + +Slang supports a rich 'String' type when using the [host style](#compile-style), which for C++ targets is implemented as the `Slang::String` C++ type. The type is only available on CPU targets that support `slang-rt`. + +Some limited String-like support is available via `NativeString` type which for C/C++ CPU targets is equivalent to `const char*`. For GPU targets this will use the same hash mechanism as normally available. + +`NativeString` is supported by all [shader compilation styles](#compile-style) including [slang-llvm](#slang-llvm). + +TODO(JS): What happens with String with shader compile style on CPU? Shouldn't it be the same as GPU (and reflected as such in reflection)? + +## Debugging + +It is currently not possible to step into LLVM-JIT code when using [slang-llvm](#slang-llvm). Fortunately it is possible to step into code compiled via a [regular C/C++ compiler](#regular-cpp). + +Below is a code snippet showing how to switch to a [regular C/C++ compiler](#regular-cpp) at runtime. + +```C++ + SlangPassThrough findRegularCppCompiler(slang::IGlobalSession* slangSession) + { + // Current list of 'regular' C/C++ compilers + const SlangPassThrough cppCompilers[] = + { + SLANG_PASS_THROUGH_VISUAL_STUDIO, + SLANG_PASS_THROUGH_GCC, + SLANG_PASS_THROUGH_CLANG, + }; + // Do we have a C++ compiler + for (const auto compiler : cppCompilers) + { + if (SLANG_SUCCEEDED(slangSession->checkPassThroughSupport(compiler))) + { + return compile; + } + } + return SLANG_PASS_THROUGH_NONE; + } + + SlangResult useRegularCppCompiler(slang::IGlobalSession* session) + { + const auto regularCppCompiler = findRegularCppCompiler(session) + if (regularCppCompiler != SLANG_PASS_THROUGH_NONE) + { + slangSession->setDownstreamCompilerForTransition(SLANG_CPP_SOURCE, SLANG_SHADER_HOST_CALLABLE, regularCppCompiler); + slangSession->setDownstreamCompilerForTransition(SLANG_CPP_SOURCE, SLANG_HOST_HOST_CALLABLE, regularCppCompiler); + return SLANG_OK; + } + return SLANG_FAIL; + } +``` + +It is generally recommended to use [slang-llvm](#slang-llvm) if that is appropriate, but to switch to using a [regular C/C++ compiler](#regular-cpp) when debugging is needed. This should be largely transparent to most code. + +Executing CPU Code +================== + +In typical Slang operation when code is compiled it produces either source or a binary that can then be loaded by another API such as a rendering API. With CPU code the binary produced could be saved to a file and then executed as an exe or a shared library/dll. In practice though it is common to want to be able to execute compiled code immediately. Having to save off to a file and then load again can be awkward. It is also not necessarily the case that code needs to be saved to a file to be executed. + +To handle being able call code directly, code can be compiled using the [host-callable](#host-callable). + +For pass through compilation of C/C++ this mechanism allows any functions marked for export to be directly queried. Marking for export is a C/C++ compiler specific feature. Look at the definition of `SLANG_PRELUDE_EXPORT` in the [C++ prelude](#prelude). + +For a complete example on how to execute CPU code using `spGetEntryPointHostCallable`/`getEntryPointHostCallable` look at code in `example/cpu-hello-world`. + +Application Binary Interface (ABI) +=== + +Say we have some Slang source like the following: + +``` +struct Thing { int a; int b; } + +Texture2D tex; +SamplerState sampler; +RWStructuredBuffer outputBuffer; +ConstantBuffer thing3; + +[numthreads(4, 1, 1)] +void computeMain( + uint3 dispatchThreadID : SV_DispatchThreadID, + uniform Thing thing, + uniform Thing thing2) +{ + // ... +} +``` + +When compiled into a [shader compile style](#compile-style) shared library/dll/host-callable - how is it invoked? An entry point in the Slang source code produces several exported functions. The 'default' exported function has the same name as the entry point in the original source. It has the signature + +``` +void computeMain(ComputeVaryingInput* varyingInput, UniformEntryPointParams* uniformParams, UniformState* uniformState); +``` + +NOTE! Using `main` as an entry point name should be avoided if CPU is a target because it typically causes compilation errors due it's normal C/C++ usage. + +ComputeVaryingInput is defined in the prelude as + +``` +struct ComputeVaryingInput +{ + uint3 startGroupID; + uint3 endGroupID; +}; +``` + +`ComputeVaryingInput` allows specifying a range of groupIDs to execute - all the ids in a grid from startGroup to endGroup, but not including the endGroupIDs. Most compute APIs allow specifying an x,y,z extent on 'dispatch'. This would be equivalent as having startGroupID = { 0, 0, 0} and endGroupID = { x, y, z }. The exported function allows setting a range of groupIDs such that client code could dispatch different parts of the work to different cores. This group range mechanism was chosen as the 'default' mechanism as it is most likely to achieve the best performance. + +There are two other functions that consist of the entry point name postfixed with `_Thread` and `_Group`. For the entry point 'computeMain' these functions would be accessible from the shared library interface as `computeMain_Group` and `computeMain_Thread`. `_Group` has the same signature as the listed for computeMain, but it doesn't execute a range, only the single group specified by startGroupID (endGroupID is ignored). That is all of the threads within the group (as specified by `[numthreads]`) will be executed in a single call. + +It may be desirable to have even finer control of how execution takes place down to the level of individual 'thread's and this can be achieved with the `_Thread` style. The signature looks as follows + +``` +struct ComputeThreadVaryingInput +{ + uint3 groupID; + uint3 groupThreadID; +}; + +void computeMain_Thread(ComputeThreadVaryingInput* varyingInput, UniformEntryPointParams* uniformParams, UniformState* uniformState); +``` + +When invoking the kernel at the `thread` level it is a question of updating the groupID/groupThreadID, to specify which thread of the computation to execute. For the example above we have `[numthreads(4, 1, 1)]`. This means groupThreadID.x can vary from 0-3 and .y and .z must be 0. That groupID.x indicates which 'group of 4' to execute. So groupID.x = 1, with groupThreadID.x=0,1,2,3 runs the 4th, 5th, 6th and 7th 'thread'. Being able to invoke each thread in this way is flexible - in that any specific thread can specified and executed. It is not necessarily very efficient because there is the call overhead and a small amount of extra work that is performed inside the kernel. + +Note that the `_Thread` style signature is likely to change to support 'groupshared' variables in the near future. + +In terms of performance the 'default' function is probably the most efficient for most common usages. The `_Group` style allows for slightly less loop overhead, but with many invocations this will likely be drowned out by the extra call/setup overhead. The `_Thread` style in most situations will be the slowest, with even more call overhead, and less options for the C/C++ compiler to use faster paths. + +The UniformState and UniformEntryPointParams struct typically vary by shader. UniformState holds 'normal' bindings, whereas UniformEntryPointParams hold the uniform entry point parameters. Where specific bindings or parameters are located can be determined by reflection. The structures for the example above would be something like the following... + +``` +struct UniformEntryPointParams +{ + Thing thing; + Thing thing2; +}; + +struct UniformState +{ + Texture2D tex; + SamplerState sampler; + RWStructuredBuffer outputBuffer; + Thing* thing3; +}; +``` + +Notice that of the entry point parameters `dispatchThreadID` is not part of UniformEntryPointParams and this is because it is not uniform. + +`ConstantBuffer` and `ParameterBlock` will become pointers to the type they hold (as `thing3` is in the above structure). + +`StructuredBuffer`,`RWStructuredBuffer` become + +``` + T* data; + size_t count; +``` + +`ByteAddressBuffer`, `RWByteAddressBuffer` become + +``` + uint32_t* data; + size_t sizeInBytes; +``` + + +Resource types become pointers to interfaces that implement their features. For example `Texture2D` become a pointer to a `ITexture2D` interface that has to be implemented in client side code. Similarly SamplerState and SamplerComparisonState become `ISamplerState` and `ISamplerComparisonState`. + +The actual definitions for the interfaces for resource types, and types are specified in 'slang-cpp-types.h' in the `prelude` directory. + +## Unsized arrays + +Unsized arrays can be used, which are indicated by an array with no size as in `[]`. For example + +``` + RWStructuredBuffer arrayOfArrays[]; +``` + +With normal 'sized' arrays, the elements are just stored contiguously within wherever they are defined. With an unsized array they map to `Array` which is... + +``` + T* data; + size_t count; +``` + +Note that there is no method in the shader source to get the `count`, even though on the CPU target it is stored and easily available. This is because of the behavior on GPU targets + +* That the count has to be stored elsewhere (unlike with CPU) +* On some GPU targets there is no bounds checking - accessing outside the bound values can cause *undefined behavior* +* The elements may be laid out *contiguously* on GPU + +In practice this means if you want to access the `count` in shader code it will need to be passed by another mechanism - such as within a constant buffer. It is possible in the future support may be added to allow direct access of `count` work across targets transparently. + +It is perhaps worth noting that the CPU allows us to have an indirection (a pointer to the unsized arrays contents) which has the potential for more flexibility than is possible on GPU targets. GPU target typically require the elements to be placed 'contiguously' from their location in their `container` - be that registers or in memory. This means on GPU targets there may be other restrictions on where unsized arrays can be placed in a structure for example, such as only at the end. If code needs to work across targets this means these restrictions will need to be followed across targets. + +## Context Threading + +The [shader compile style](#compile-style) brings some extra issues to bare. In the HLSL compute kernel launch model application visible variables and resource are bound. As described in the [ABI](#abi) section these bindings and additional information identifying a compute thread are passed into the launch as a context. Take for example the code snippet below + +``` +int myGlobal; + +int myFunc(int v) +{ + return myGlobal + v; +} + +int anotherFunc(int a, int b) +{ + return a + b; +} + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + outputBuffer[dispatchThreadID.x] = myFunc(dispatchThreadID.x) + anotherFunc(1, dispatchThreadID.y); +} +``` + +The function `myFunc` accesses a variable `myGlobal` that is held within a constant buffer. The function cannot be meaningfully executed without access to the context, and the context is available as a parameter passed through `computeMain` entry point at launch. This means the *actual* signature of this function in output code will be something like + +``` +int32_t myFunc_0(KernelContext_0 * kernelContext_0) +{ + return *(&(*(&kernelContext_0->globalParams_0))->myGlobal_0) + int(1); +} +``` + +The context parameter has been *threaded* into this function. This *threading* will happen to any function that accesses any state that is held in the context. This behavior also happens transitively - if a function *could* call *any* another function that requires the context, the context will be threaded through to it also. + +If application code assumed `myFunc` could be called with no parameters a crash would likely ensue. Note that `anotherFunc` does not have the issue because it doesn't perform an access that needs the context, and so no context threading is added. + +If a global is desired in a function that wants to be called from the application, the [`__global`](#actual-global) modifier can be used. + +## Prelude + +For C++ targets, there is code to support the Slang generated source defined within the 'prelude'. The prelude is inserted text placed before the Slang generated C++ source. For the Slang command line tools as well as the test infrastructure, the prelude functionality is achieved through a `#include` in the prelude text of the `prelude/slang-cpp-prelude.h` specified with an absolute path. Doing so means other files the `slang-cpp-prelude.h` might need can be specified relatively, and include paths for the backend C/C++ compiler do not need to be modified. + +The prelude needs to define + +* 'Built in' types (vector, matrix, 'object'-like Texture, SamplerState etc) +* Scalar intrinsic function implementations +* Compiler based definations/tweaks + +For the Slang prelude this is split into the following files... + +* 'prelude/slang-cpp-prelude.h' - Header that includes all the other requirements & some compiler tweaks +* 'prelude/slang-cpp-scalar-intrinsics.h' - Scalar intrinsic implementations +* 'prelude/slang-cpp-types.h' - The 'built in types' +* 'slang.h' - Slang header is used for majority of compiler based definitions + +For a client application - as long as the requirements of the generated code are met, the prelude can be implemented by whatever mechanism is appropriate for the client. For example the implementation could be replaced with another implementation, or the prelude could contain all of the required text for compilation. Setting the prelude text can be achieved with the method on the global session... + +``` +/** 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; +``` + +It may be useful to be able to include `slang-cpp-types.h` in C++ code to access the types that are used in the generated code. This introduces a problem in that the types used in the generated code might clash with types in client code. To work around this problem, you can wrap all of the types defined in the prelude with a namespace of your choosing. For example + +``` +#define SLANG_PRELUDE_NAMESPACE CPPPrelude +#include "../../prelude/slang-cpp-types.h" +``` + +Would wrap all the Slang prelude types in the namespace `CPPPrelude`, such that say a `StructuredBuffer` could be specified in C++ source code as `CPPPrelude::StructuredBuffer`. + +The code that sets up the prelude for the test infrastructure and command line usage can be found in ```TestToolUtil::setSessionDefaultPrelude```. Essentially this determines what the absolute path is to `slang-cpp-prelude.h` is and then just makes the prelude `#include "the absolute path"`. + +The *default* prelude is set to the contents of the files for C++ held in the prelude directory and is held within the Slang shared library. It is therefore typically not necessary to distribute Slang with prelude files. + +Language aspects +================ + +# Arrays passed by Value + +Slang follows the HLSL convention that arrays are passed by value. This is in contrast the C/C++ where arrays are passed by reference. To make generated C/C++ follow this convention an array is turned into a 'FixedArray' struct type. Sinces classes by default in C/C++ are passed by reference the wrapped array is also. + +To get something similar to C/C++ operation the array can be marked `inout` to make it passed by reference. + +Limitations +=========== + +# Out of bounds access + +In HLSL code if an access is made out of bounds of a StructuredBuffer, execution proceceeds. If an out of bounds read is performed, a zeroed value is returned. If an out of bounds write is performed it's effectively a noop, as the value is discarded. On the CPU target this behavior is *not* supported by default. + +For a debug CPU build an out of bounds access will assert, for a release build the behaviour is by default undefined. A limited Limited [zero index](#zero-index) out of bounds mechanism is supported, but must be enabled. + +The reason for this is that such an access is difficult and/or slow to implement the identical GPU behavior on the CPU. The underlying problem is `operator[]` typically returns a reference to the contained value. If this is out of bounds - it's not clear what to return, in particular because the value may be read or written and moreover elements of the type might be written. In practice this means a global zeroed value cannot be returned. + +This could be somewhat supported if code gen worked as followed for say + +``` +RWStructuredBuffer values; +values[3].x = 10; +``` + +Produces + +``` +template +struct RWStructuredBuffer +{ + T& at(size_t index, T& defValue) { return index < size ? values[index] : defValue; } + + T* values; + size_t size; +}; + +RWStructuredBuffer values; + +// ... +Vector defValue = {}; // Zero initialize such that read access returns default values +values.at(3).x = 10; +``` + +Note that '[] 'would be turned into the `at` function, which takes the default value as a parameter provided by the caller. If this is then written to then only the defValue is corrupted. Even this mechanism not be quite right, because if we write and then read again from the out of bounds reference in HLSL we may expect that 0 is returned, whereas here we get the value that was last written. + +## Zero index bound checking + +If bounds checking is wanted in order to avoid undefined behavior and limit how memory is accessed `zero indexed` bounds checking might be appropriate. When enabled if an access is out of bounds the value at the zero index is returned. This is quite different behavior than the typical GPU behavior, but is fairly efficient and simple to implement. Importantly it means behavior is well defined and always 'in range' assuming there is an element. + +To enable zero indexing bounds checking pass in the define `SLANG_ENABLE_BOUND_ZERO_INDEX` to a Slang compilation. This define is passed down to C++ and CUDA compilations, and the code in the CUDA and C++ preludes implement the feature. Note that zero indexed bounds checking will slow down accesses that are checked. + +The C++ implementation of the feature can be seen by looking at the file "prelude/slang-cpp-types.h". For CUDA "prelude/slang-cuda-prelude.h". + +The bounds checking macros are guarded such it is possible to replace the implementations, without directly altering the prelude. + +TODO +==== + +# Main + +* groupshared is not yet supported +* Output of header files +* Output multiple entry points + +# Internal Slang compiler features + +These issues are more internal Slang features/improvements + +* Currently only generates C++ code, it would be fairly straight forward to support C (especially if we have 'intrinsic definitions') +* Have 'intrinsic definitions' in standard library - such that they can be generated where appropriate + + This will simplify the C/C++ code generation as means Slang language will generate must of the appropriate code +* Currently 'construct' IR inst is supported as is, we may want to split out to separate instructions for specific scenarios +* Refactoring around swizzle. Currently in emit it has to check for a variety of scenarios - could be simplified with an IR pass and perhaps more specific instructions. diff --git a/lib/All/slang/share/doc/slang/cuda-target.md b/lib/All/slang/share/doc/slang/cuda-target.md new file mode 100644 index 0000000..56ab272 --- /dev/null +++ b/lib/All/slang/share/doc/slang/cuda-target.md @@ -0,0 +1,333 @@ +Slang CUDA Target Support +========================= + +Slang has preliminary support for producing CUDA source, and PTX binaries using [NVRTC](https://docs.nvidia.com/cuda/nvrtc/index.html). + +NOTE! NVRTC is only available for 64-bit operating systems. On Windows Visual Studio make sure you are compiling for 'x64' and/or use 64 bit Slang binaries. + +# Features + +* Can compile Slang source into CUDA source code +* Supports compute style shaders +* Supports a 'bindless' CPU like model +* Can compile CUDA source to PTX through 'pass through' mechansism + +# Limitations + +These limitations apply to Slang transpiling to CUDA. + +* Only supports the 'texture object' style binding (The texture object API is only supported on devices of compute capability 3.0 or higher. ) +* Samplers are not separate objects in CUDA - they are combined into a single 'TextureObject'. So samplers are effectively ignored on CUDA targets. +* When using a TextureArray.Sample (layered texture in CUDA) - the index will be treated as an int, as this is all CUDA allows +* Care must be used in using `WaveGetLaneIndex` wave intrinsic - it will only give the right results for appropriate launches +* CUDA 'surfaces' are used for textures which are read/write (aka RWTexture). + +The following are a work in progress or not implemented but are planned to be so in the future + +* Some resource types remain unsupported, and not all methods on all types are supported + +# How it works + +For producing PTX binaries Slang uses [NVRTC](https://docs.nvidia.com/cuda/nvrtc/index.html). NVRTC dll/shared library has to be available to Slang (for example in the appropriate PATH for example) for it to be able to produce PTX. + +The NVRTC compiler can be accessed directly via the pass through mechanism and is identified by the enum value `SLANG_PASS_THROUGH_NVRTC`. + +Much like other targets that use downstream compilers Slang can be used to compile CUDA source directly to PTX via the pass through mechansism. The Slang command line options will broadly be mapped down to the appropriate options for the NVRTC compilation. In the API the `SlangCompileTarget` for CUDA is `SLANG_CUDA_SOURCE` and for PTX is `SLANG_PTX`. These can also be specified on the Slang command line as `-target cuda` and `-target ptx`. + +## Locating NVRTC + +Finding NVRTC can require some nuance if a specific version is required. On the command line the `-nvrtc-path` option can be used to set the `path` to NVRTC. Also `spProcessCommandLineArguments`/`processCommandLineArguments` with `-nvrtc-path` or `setDownstreamCompilerPath` with `SLANG_PASS_THROUGH_NVRTC` can be used to set the location and/or name of NVRTC via the API. + +Important points of note are + +* The name of the shared library should *not* include any extension (such as `.dll`/`.so`/`.dynlib`) or prefix (such as `lib`). +* The path also *doesn't* have to be path, it can just be the shared library name. Doing so will mean it will be searched for by whatever the default mechanism is on the target. +* If a path and/or name is specified for NVRTC - this will be the *only* version searched for. + +If a path/name is *not* specified for NVRTC, Slang will attempt to load a shared library called `nvrtc`. For non Windows targets this should be enough to find and load the latest version. + +On Windows NVRTC dlls have a name the contains the version number, for example `nvrtc64_102_0.dll`. This will lead to the load of just `nvrtc` to fail. One approach to fix this is to place the NVRTC dll and associated files in the same directory as `slang-compiler.dll`, and rename the main dll to `nvrtc.dll`. Another approach is to specify directly on the command line the name including the version, as previously discussed. For example + +`-nvrtc-path nvrtc64_102_0` + +will load NVRTC 10.2 assuming that version of the dll can be found via the normal lookup mechanism. + +On Windows if NVRTC is not loadable directly as 'nvrtc' Slang will attempt to search for the newest version of NVRTC on your system. The places searched are... + +* The instance directory (where the slang-compiler.dll and/or program exe is) +* The CUDA_PATH enivonment variable (if set) +* Directories in PATH that look like a CUDA installation. + +If a candidate is found via an earlier mechanism, subsequent searches are not performed. If multiple candidates are found, Slang tries the newest version first. + +Binding +======= + +Say we have some Slang source like the following: + +``` +struct Thing { int a; int b; } + +Texture2D tex; +SamplerState sampler; +RWStructuredBuffer outputBuffer; +ConstantBuffer thing3; + +[numthreads(4, 1, 1)] +void computeMain( + uint3 dispatchThreadID : SV_DispatchThreadID, + uniform Thing thing, + uniform Thing thing2) +{ + // ... +} +``` + +This will be turned into a CUDA entry point with + +``` +struct UniformEntryPointParams +{ + Thing thing; + Thing thing2; +}; + +struct UniformState +{ + CUtexObject tex; // This is the combination of a texture and a sampler(!) + SamplerState sampler; // This variable exists within the layout, but it's value is not used. + RWStructuredBuffer outputBuffer; // This is implemented as a template in the CUDA prelude. It's just a pointer, and a size + Thing* thing3; // Constant buffers map to pointers +}; + +// [numthreads(4, 1, 1)] +extern "C" __global__ void computeMain(UniformEntryPointParams* params, UniformState* uniformState) +``` + +With CUDA - the caller specifies how threading is broken up, so `[numthreads]` is available through reflection, and in a comment in output source code but does not produce varying code. + +The UniformState and UniformEntryPointParams struct typically vary by shader. UniformState holds 'normal' bindings, whereas UniformEntryPointParams hold the uniform entry point parameters. Where specific bindings or parameters are located can be determined by reflection. The structures for the example above would be something like the following... + +`StructuredBuffer`,`RWStructuredBuffer` become + +``` + T* data; + size_t count; +``` + +`ByteAddressBuffer`, `RWByteAddressBuffer` become + +``` + uint32_t* data; + size_t sizeInBytes; +``` + +## Texture + +Read only textures will be bound as the opaque CUDA type CUtexObject. This type is the combination of both a texture AND a sampler. This is somewhat different from HLSL, where there can be separate `SamplerState` variables. This allows access of a single texture binding with different types of sampling. + +If code relies on this behavior it will be necessary to bind multiple CtexObjects with different sampler settings, accessing the same texture data. + +Slang has some preliminary support for TextureSampler type - a combined Texture and SamplerState. To write Slang code that can target CUDA and other platforms using this mechanism will expose the semantics appropriately within the source. + +Load is only supported for Texture1D, and the mip map selection argument is ignored. This is because there is tex1Dfetch and no higher dimensional equivalents. CUDA also only allows such access if the backing array is linear memory - meaning the bound texture cannot have mip maps - thus making the mip map parameter superfluous anyway. RWTexture does allow Load on other texture types. + +## RWTexture + +RWTexture types are converted into CUsurfObject type. + +In regular CUDA it is not possible to do a format conversion on an access to a CUsurfObject. Slang does add support for hardware write conversions where they are available. To enable the feature it is necessary to attribute your RWTexture with `format`. For example + +``` +[format("rg16f")] +RWTexture2D rwt2D_2; +``` + +The format names used are the same as for [GLSL layout format types](https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)). If no format is specified Slang will *assume* that the format is the same as the type specified. + +Note that the format attribution is on variables/parameters/fields and not part of the type system. This means that if you have a scenario like... + +``` +[format(rg16f)] +RWTexture2d g_texture; + +float2 getValue(RWTexture2D t) +{ + return t[int2(0, 0)]; +} + +void doThing() +{ + float2 v = getValue(g_texture); +} +``` + +Even `getValue` will receive t *without* the format attribute, and so will access it, presumably erroneously. A workaround for this specific scenario would be to attribute the parameter + +``` +float2 getValue([format("rg16f")] RWTexture2D t) +{ + return t[int2(0, 0)]; +} +``` + +This will only work correctly if `getValue` is called with a `t` that has that format attribute. As it stands no checking is performed on this matching so no error or warning will be produced if there is a mismatch. + +There is limited software support for doing a conversion on reading. Currently this only supports only 1D, 2D, 3D RWTexture, backed with half1, half2 or half4. For this path to work NVRTC must have the `cuda_fp16.h` and associated files available. Please check the section on `Half Support`. + +If hardware read conversions are desired, this can be achieved by having a Texture that uses the surface of a RWTexture. Using the Texture not only allows hardware conversion but also filtering. + +It is also worth noting that CUsurfObjects in CUDA are NOT allowed to have mip maps. + +By default surface access uses cudaBoundaryModeZero, this can be replaced using the macro SLANG_CUDA_BOUNDARY_MODE in the CUDA prelude. For HW format conversions the macro SLANG_PTX_BOUNDARY_MODE. These boundary settings are in effect global for the whole of the kernel. + +`SLANG_CUDA_BOUNDARY_MODE` can be one of + +* cudaBoundaryModeZero causes an execution trap on out-of-bounds addresses +* cudaBoundaryModeClamp stores data at the nearest surface location (sized appropriately) +* cudaBoundaryModeTrap drops stores to out-of-bounds addresses + +`SLANG_PTX_BOUNDARY_MODE` can be one of `trap`, `clamp` or `zero`. In general it is recommended to have both set to the same type of value, for example `cudaBoundaryModeZero` and `zero`. + +## Sampler + +Samplers are in effect ignored in CUDA output. Currently we do output a variable `SamplerState`, but this value is never accessed within the kernel and so can be ignored. More discussion on this behavior is in `Texture` section. + +## Unsized arrays + +Unsized arrays can be used, which are indicated by an array with no size as in `[]`. For example + +``` + RWStructuredBuffer arrayOfArrays[]; +``` + +With normal 'sized' arrays, the elements are just stored contiguously within wherever they are defined. With an unsized array they map to `Array` which is... + +``` + T* data; + size_t count; +``` + +Note that there is no method in the shader source to get the `count`, even though on the CUDA target it is stored and easily available. This is because of the behavior on GPU targets + +* That the count has to be stored elsewhere (unlike with CUDA) +* On some GPU targets there is no bounds checking - accessing outside the bound values can cause *undefined behavior* +* The elements may be laid out *contiguously* on GPU + +In practice this means if you want to access the `count` in shader code it will need to be passed by another mechanism - such as within a constant buffer. It is possible in the future support may be added to allow direct access of `count` work across targets transparently. + +## Prelude + +For CUDA the code to support the code generated by Slang is partly defined within the 'prelude'. The prelude is inserted text placed before the generated CUDA source code. For the Slang command line tools as well as the test infrastructure, the prelude functionality is achieved through a `#include` in the prelude text of the `prelude/slang-cuda-prelude.h` specified with an absolute path. Doing so means other files the `slang-cuda-prelude.h` might need can be specified relatively, and include paths for the backend compiler do not need to be modified. + +The prelude needs to define + +* 'Built in' types (vector, matrix, 'object'-like Texture, SamplerState etc) +* Scalar intrinsic function implementations +* Compiler based definations/tweaks + +For a client application - as long as the requirements of the generated code are met, the prelude can be implemented by whatever mechanism is appropriate for the client. For example the implementation could be replaced with another implementation, or the prelude could contain all of the required text for compilation. Setting the prelude text can be achieved with the method on the global session... + +``` +/** 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. +*/ + +void setDownstreamCompilerPrelude(SlangPassThrough passThrough, const char* preludeText); +``` + +The code that sets up the prelude for the test infrastructure and command line usage can be found in ```TestToolUtil::setSessionDefaultPrelude```. Essentially this determines what the absolute path is to `slang-cpp-prelude.h` is and then just makes the prelude `#include "the absolute path"`. + +Half Support +============ + +Slang supports the half/float16 types on CUDA. To do so NVRTC must have access to the `cuda_fp16.h` and `cuda_fp16.hpp` files that are typically distributed as part of the CUDA SDK. When Slang detects the use of half in source, it will define `SLANG_CUDA_ENABLE_HALF` when `slang-cuda-prelude.h` is included. This will in turn try to include `cuda_fp16.h` and enable extra functionality within the prelude for half support. + +Slang tries several mechanisms to locate `cuda_fp16.h` when NVRTC is initiated. The first mechanism is to look in the include paths that are passed to Slang. If `cuda_fp16.h` can be found in one of these paths, no more searching will be performed. + +If this fails, the path where NVRTC is located will be searched. In that path "include" and "CUDA/include" paths will be searched. This is probably most suitable for Windows based targets, where NVRTC dll is placed along with other binaries. The "CUDA/include" path is used to try and make clear in this scenario what the contained files are for. + +If this fails Slang will look for the CUDA_PATH environmental variable, as is typically set during a CUDA SDK installation. + +If this fails - the prelude include of `cuda_fp16.h` will most likely fail on NVRTC invocation. + +CUDA has the `__half` and `__half2` types defined in `cuda_fp16.h`. The `__half2` can produce results just as quickly as doing the same operation on `__half` - in essence for some operations `__half2` is [SIMD](https://en.wikipedia.org/wiki/SIMD) like. The half implementation in Slang tries to take advantage of this optimization. + +Since Slang supports up to 4 wide vectors Slang has to build on CUDAs half support. The types `__half3` and `__half4` are implemented in `slang-cuda-prelude.h` for this reason. It is worth noting that `__half3` is made up of a `__half2` and a `__half`. As `__half2` is 4 byte aligned, this means `__half3` is actually 8 bytes, rather than 6 bytes that might be expected. + +One area where this optimization isn't fully used is in comparisons - as in effect Slang treats all the vector/matrix half comparisons as if they are scalar. This could be perhaps be improved on in the future. Doing so would require using features that are not directly available in the CUDA headers. + +Wave Intrinsics +=============== + +There is broad support for [HLSL Wave intrinsics](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12), including support for [SM 6.5 intrinsics](https://microsoft.github.io/DirectX-Specs/d3d/HLSL_ShaderModel6_5.html). + +Most Wave intrinsics will work with vector, matrix or scalar types of typical built in types - `uint`, `int`, `float`, `double`, `uint64_t`, `int64_t`. + +The support is provided via both the Slang core module as well as the Slang CUDA prelude found in 'prelude/slang-cuda-prelude.h'. Many Wave intrinsics are not directly applicable within CUDA which supplies a more low level mechanisms. The implementation of most Wave functions work most optimally if a 'Wave' where all lanes are used. If all lanes from index 0 to pow2(n) -1 are used (which is also true if all lanes are used) a binary reduction is typically applied. If this is not the case the implementation fallsback on a slow path which is linear in the number of active lanes, and so is typically significantly less performant. + +For more a more concrete example take + +``` +int sum = WaveActiveSum(...); +``` + +When computing the sum, if all lanes (32 on CUDA), the computation will require 5 steps to complete (2^5 = 32). If say just one lane is not being used it will take 31 steps to complete (because it is now linear in amount of lanes). So just having one lane disabled required 6 times as many steps. If lanes with 0 - 15 are active, it will take 4 steps to complete (2^4 = 16). + +In the future it may be possible to improve on the performance of the 'slow' path, however it will always remain the most efficient generally for all of 0 to pow2(n) - 1 lanes to be active. + +It is also worth noting that lane communicating intrinsics performance will be impacted by the 'size' of the data communicated. The size here is at a minimum the amount of built in scalar types used in the processing. The CUDA language only allows direct communication with built in scalar types. + +Thus + +``` +int3 v = ...; +int3 sum = WaveActiveSum(v); +``` + +Will require 3 times as many steps as the earlier scalar example just using a single int. + +## WaveGetLaneIndex + +'WaveGetLaneIndex' defaults to `(threadIdx.x & SLANG_CUDA_WARP_MASK)`. Depending on how the kernel is launched this could be incorrect. There are other ways to get lane index, for example using inline assembly. This mechanism though is apparently slower than the simple method used here. There is support for using the asm mechanism in the CUDA prelude using the `SLANG_USE_ASM_LANE_ID` preprocessor define to enable the feature. + +There is potential to calculate the lane id using the [numthreads] markup in Slang/HLSL, but that also requires some assumptions of how that maps to a lane index. + +## Unsupported Intrinsics + +* Intrinsics which only work in pixel shaders + + QuadXXXX intrinsics + +OptiX Support +============= + +Slang supports OptiX for raytracing. To compile raytracing programs, NVRTC must have access to the `optix.h` and dependent files that are typically distributed as part of the OptiX SDK. When Slang detects the use of raytracing in source, it will define `SLANG_CUDA_ENABLE_OPTIX` when `slang-cuda-prelude.h` is included. This will in turn try to include `optix.h`. + +Slang tries several mechanisms to locate `optix.h` when NVRTC is initiated. The first mechanism is to look in the include paths that are passed to Slang. If `optix.h` can be found in one of these paths, no more searching will be performed. + +If this fails, the default OptiX SDK install locations are searched. On Windows this is `%{PROGRAMDATA}\NVIDIA Corporation\OptiX SDK X.X.X\include`. On Linux this is `${HOME}/NVIDIA-OptiX-SDK-X.X.X-suffix`. + +If OptiX headers cannot be found, compilation will fail. + +Limitations +=========== + +Some features are not available because they cannot be mapped with appropriate behavior to a target. Other features are unavailable because of resources to devote to more unusual features. + +* Not all Wave intrinsics are supported +* There is not complete support for all methods on 'objects' like textures etc. +* Does not currently support combined 'TextureSampler'. A Texture behaves equivalently to a TextureSampler and Samplers are ignored. +* Half type is not currently supported +* GetDimensions is not available on any Texture type currently - as there doesn't appear to be a CUDA equivalent + +Language aspects +================ + +# Arrays passed by Value + +Slang follows the HLSL convention that arrays are passed by value. This is in contrast with CUDA where arrays follow C++ conventions and are passed by reference. To make generated CUDA follow this convention an array is turned into a 'FixedArray' struct type. + +To get something more similar to CUDA/C++ operation the array can be marked in out or inout to make it passed by reference. diff --git a/lib/All/slang/share/doc/slang/debugging.md b/lib/All/slang/share/doc/slang/debugging.md new file mode 100644 index 0000000..8946eee --- /dev/null +++ b/lib/All/slang/share/doc/slang/debugging.md @@ -0,0 +1,70 @@ +# Debugging Slang + +This document gives examples showing how to run debuggers in the Slang codebase. +Follow the [Building Slang From Source](/docs/building.md) instructions first. + +## Visual Studio + +This repo includes multiple `*.natvis` files which Visual Studio picks up +automatically; no extra configuration is required. + +## LLDB + +If you use [LLDB][], we provide a `.lldbinit` file which enables data formatters +for types in the Slang codebase. You can use this with LLDB in your terminal via +the [`--local-lldbinit`][] flag; for example: + +``` +$ cmake --build --preset debug +$ lldb --local-lldbinit build/Debug/bin/slangc -- tests/byte-code/hello.slang -dump-ir +(lldb) breakpoint set --name dumpIR +(lldb) run +``` + +LLDB can be used with either GCC or Clang, but Clang seems to behave better +about respecting breakpoint locations and not having missing variables. + +### VS Code + +If instead you prefer to debug within VS Code, you can run LLDB via the +[CodeLLDB][] extension. For example, to recreate the same debugging session as +above, create a `.vscode/tasks.json` file with these contents: + +```json +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Debug build", + "type": "shell", + "command": "cmake", + "args": ["--build", "--preset", "debug"] + } + ] +} +``` + +Then create a `.vscode/launch.json` file with these contents: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "LLDB", + "preLaunchTask": "Debug build", + "type": "lldb", + "request": "launch", + "initCommands": ["command source .lldbinit"], + "program": "build/Debug/bin/slangc", + "args": ["tests/byte-code/hello.slang", "-dump-ir"] + } + ] +} +``` + +Finally, place any breakpoints you want, and hit F5. + +[`--local-lldbinit`]: https://lldb.llvm.org/man/lldb.html#cmdoption-lldb-local-lldbinit +[codelldb]: https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb +[lldb]: https://lldb.llvm.org/index.html diff --git a/lib/All/slang/share/doc/slang/deprecated/a1-02-slangpy.md b/lib/All/slang/share/doc/slang/deprecated/a1-02-slangpy.md new file mode 100644 index 0000000..beac179 --- /dev/null +++ b/lib/All/slang/share/doc/slang/deprecated/a1-02-slangpy.md @@ -0,0 +1,814 @@ +--- +layout: deprecated +permalink: "docs/user-guide/a1-02-slangpy" +--- + +Using Slang to Write PyTorch Kernels +========================================================= + +> #### Note +> This documentation is about `slang-torch`, a way to use Slang with Python and PyTorch. +> For new projects, we recommend exploring SlangPy as an alternative. +> We plan to deprecate `slang-torch` in favor of SlangPy in the near future, and we will communicate any plans in advance. + +If you are a PyTorch user seeking to write complex, high-performance, and automatically differentiated kernel functions using a per-thread programming model, we invite you to try Slang. Slang is a cutting-edge shading language that provides a straightforward way to define kernel functions that run incredibly fast in graphics applications. With the latest addition of automatic differentiation and PyTorch interop features, Slang offers an efficient solution for developing auto-differentiated kernels that run at lightning speed with a strongly typed, per-thread programming model. + +One of the primary advantages of a per-thread programming model in kernel programming is the elimination of concerns regarding maintaining masks for branches. When developing a kernel in Slang, you can use all control flow statements, composite data types (structs, arrays, etc.), and function calls without additional effort. Code created with these language constructs can be automatically differentiated by the compiler without any restrictions. Additionally, Slang is a strongly typed language, which ensures that you will never encounter type errors at runtime. Most code errors can be identified as you type thanks to the [compiler's coding assistance service](https://marketplace.visualstudio.com/items?itemName=shader-slang.slang-language-extension), further streamlining the development process. + +In addition, using a per-thread programming model also results in more optimized memory usage. When writing a kernel in Slang, most intermediate results do not need to be written out to global memory and then read back, reducing global memory bandwidth consumption and the delay caused by these memory operations. As a result, a Slang kernel can typically run at higher efficiency compared to the traditional bulk-synchronous programming model. + +## Getting Started with SlangTorch + +In this tutorial, we will use a simple example to walk through the steps to use Slang in your PyTorch project. + +### Installation +`slangtorch` is available via PyPI, so you can install it simply through +```sh +pip install slangtorch +``` + +Note that `slangtorch` requires `torch` with CUDA support. See the [pytorch](https://pytorch.org/) installation page to find the right version for your platform. + +You can check that you have the right installation by running: +```sh +python -c "import torch; print(f'cuda: {torch.cuda.is_available()}')" +``` + +### Writing Slang kernels for `slangtorch` >= **v1.1.5** + +From **v2023.4.0**, Slang supports auto-binding features that make it easier than ever to invoke Slang kernels from python, and interoperate seamlessly with `pytorch` tensors. + +Here's a barebones example of a simple squaring kernel written in Slang (`square.slang`): + +```csharp +[AutoPyBindCUDA] +[CUDAKernel] +void square(TensorView input, TensorView output) +{ + // Get the 'global' index of this thread. + uint3 dispatchIdx = cudaThreadIdx() + cudaBlockIdx() * cudaBlockDim(); + + // If the thread index is beyond the input size, exit early. + if (dispatchIdx.x >= input.size(0)) + return; + + output[dispatchIdx.x] = input[dispatchIdx.x] * input[dispatchIdx.x]; +} + +``` + +This code follows the standard pattern of a typical CUDA kernel function. It takes as input +two tensors, `input` and `output`. +It first obtains the global dispatch index of the current thread and performs range check to make sure we don't read or write out +of the bounds of input and output tensors, and then calls `square()` to compute the per-element result, and +store it at the corresponding location in `output` tensor. + + +`slangtorch` works by compiling kernels to CUDA and it identifies the functions to compile by checking for the `[CUDAKernel]` attribute. +The second attribute `[AutoPyBindCUDA]` allows us to call `square` directly from python without having to write any host code. If you would like to write the host code yourself for finer control, see the other version of this example [here](#manually-binding-kernels). + +You can now simply invoke this kernel from python: + +```python +import torch +import slangtorch + +m = slangtorch.loadModule('square.slang') + +A = torch.randn((1024,), dtype=torch.float).cuda() + +output = torch.zeros_like(A).cuda() + +# Number of threads launched = blockSize * gridSize +m.square(input=A, output=output).launchRaw(blockSize=(32, 1, 1), gridSize=(64, 1, 1)) + +print(output) +``` + +The python script `slangtorch.loadModule("square.slang")` returns a scope that contains a handle to the `square` kernel. + +The kernel can be invoked by +1. calling `square` and binding `torch` tensors as arguments for the kernel, and then +2. launching it using `launchRaw()` by specifying CUDA launch arguments to `blockSize` & `gridSize`. (Refer to the [CUDA documentation](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications) for restrictions around `blockSize`) + +Note that for semantic clarity reasons, calling a kernel requires the use of keyword arguments with names that are lifted from the `.slang` implementation. + +### Invoking derivatives of kernels using slangtorch + +The `[AutoPyBindCUDA]` attribute can also be used on differentiable functions defined in Slang, and will automatically bind the derivatives. To do this, simply add the `[Differentiable]` attribute. + +One key point is that the basic `TensorView` objects are not differentiable. They can be used as buffers for data that does not require derivatives, or even as buffers for the manual accumulation of derivatives. + +Instead, use the `DiffTensorView` type for when you need differentiable tensors. Currently, `DiffTensorView` only supports the `float` dtype variety. + +Here's a barebones example of a differentiable version of `square`: + +```csharp +[AutoPyBindCUDA] +[CUDAKernel] +[Differentiable] +void square(DiffTensorView input, DiffTensorView output) +{ + uint3 dispatchIdx = cudaThreadIdx() + cudaBlockIdx() * cudaBlockDim(); + + if (dispatchIdx.x >= input.size(0)) + return; + + output[dispatchIdx.x] = input[dispatchIdx.x] * input[dispatchIdx.x]; +} +``` + +Now, `slangtorch.loadModule("square.slang")` returns a scope with three callable handles `square`, `square.fwd` for the forward-mode derivative & `square.bwd` for the reverse-mode derivative. + +You can invoke `square()` normally to get the same effect as the previous example, or invoke `square.fwd()` / `square.bwd()` by binding pairs of tensors to compute the derivatives. + + +```python +import torch +import slangtorch + +m = slangtorch.loadModule('square.slang') + +input = torch.tensor((0, 1, 2, 3, 4, 5), dtype=torch.float).cuda() +output = torch.zeros_like(input).cuda() + +# Invoke normally +m.square(input=input, output=output).launchRaw(blockSize=(6, 1, 1), gridSize=(1, 1, 1)) + +print(output) + +# Invoke reverse-mode autodiff by first allocating tensors to hold the gradients +input = torch.tensor((0, 1, 2, 3, 4, 5), dtype=torch.float).cuda() +input_grad = torch.zeros_like(input).cuda() + +output = torch.zeros_like(input) +# Pass in all 1s as the output derivative for our example +output_grad = torch.ones_like(output) + +m.square.bwd( + input=(input, input_grad), output=(output, output_grad) +).launchRaw( + blockSize=(6, 1, 1), gridSize=(1, 1, 1)) + +# Derivatives get propagated to input_grad +print(input_grad) + +# Note that the derivatives in output_grad are 'consumed'. +# i.e. all zeros after the call. +print(output_grad) +``` + +`slangtorch` also binds the forward-mode version of your kernel (propagate derivatives of inputs to the output) which can be invoked the same way using `module.square.fwd()` + +You can refer to [this documentation](autodiff) for a detailed reference of Slang's automatic differentiation feature. + +### Wrapping your kernels as pytorch functions + +`pytorch` offers an easy way to define a custom operation using `torch.autograd.Function`, and defining the `.forward()` and `.backward()` members. + +This can be a very helpful way to wrap your Slang kernels as pytorch-compatible operations. Here's an example of the `square` kernel as a differentiable pytorch function. + +```python +import torch +import slangtorch + +m = slangtorch.loadModule("square.slang") + +class MySquareFunc(torch.autograd.Function): + @staticmethod + def forward(ctx, input): + output = torch.zeros_like(input) + + kernel_with_args = m.square(input=input, output=output) + kernel_with_args.launchRaw( + blockSize=(32, 32, 1), + gridSize=((input.shape[0] + 31) // 32, (input.shape[1] + 31) // 32, 1)) + + ctx.save_for_backward(input, output) + + return output + + @staticmethod + def backward(ctx, grad_output): + (input, output) = ctx.saved_tensors + + input_grad = torch.zeros_like(input) + + # Note: When using DiffTensorView, grad_output gets 'consumed' during the reverse-mode. + # If grad_output may be reused, consider calling grad_output = grad_output.clone() + # + kernel_with_args = m.square.bwd(input=(input, input_grad), output=(output, grad_output)) + kernel_with_args.launchRaw( + blockSize=(32, 32, 1), + gridSize=((input.shape[0] + 31) // 32, (input.shape[1] + 31) // 32, 1)) + + return input_grad +``` + +Now we can use the autograd function `MySquareFunc` in our python script: + +```python +x = torch.tensor((3.0, 4.0), requires_grad=True, device='cuda') +print(f"X = {x}") +y_pred = MySquareFunc.apply(x) +loss = y_pred.sum() +loss.backward() +print(f"dX = {x.grad.cpu()}") +``` + +Output: +``` +X = tensor([3., 4.], + device='cuda:0', requires_grad=True) +dX = tensor([6., 8.]) +``` + +And that's it! `slangtorch.loadModule` uses JIT compilation to compile your Slang source into CUDA binary. +It may take a little longer the first time you execute the script, but the compiled binaries will be cached and as long as the kernel code is not changed, future runs will not rebuild the CUDA kernel. + +Because the PyTorch JIT system requires `ninja`, you need to make sure `ninja` is installed on your system +and is discoverable from the current environment, you also need to have a C++ compiler available on the system. +On Windows, this means that Visual Studio need to be installed. + +## Specializing shaders using slangtorch + +`slangtorch.loadModule` allows specialization parameters to be specified since it might be easier to write shaders with placeholder definitions that can be substituted at load-time. +For instance, here's a sphere tracer that uses a _compile-time_ specialization parameter for its maximum number of steps (`N`): + +```csharp +float sphereTrace(Ray ray, SDF sdf) +{ + var pt = ray.o; + for (int i = 0; i < N; i++) + { + pt += sdf.eval(pt) * ray.d; + } + + return pt; +} + +float render(Ray ray) +{ + // Use N=20 for sphere tracing. + float3 pt = sphereTrace<20>(ray, sdf); + return shade(pt, sdf.normal()); +} +``` + +However, instead of using a fixed `20` steps, the renderer can be configured to use an arbitrary compile-time constant. + +```csharp +// Compile-time constant. Expect "MAX_STEPS" to be set by the loadModule call. +static const uint kMaxSteps = MAX_STEPS; + +float render(Ray ray) +{ + float3 pt = sphereTrace(ray, sdf); + return shade(pt, sdf.normal()); +} +``` + +Then multiple versions of this shader can be compiled from Python using the `defines` argument: +```python +import slangtorch + +sdfRenderer20Steps = slangtorch.loadModule('sdf.slang', defines={"MAX_STEPS": 20}) +sdfRenderer50Steps = slangtorch.loadModule('sdf.slang', defines={"MAX_STEPS": 50}) +... +``` + +This is often helpful for code re-use, parameter sweeping, comparison/ablation studies, and more, from the convenience of Python. + +## Back-propagating Derivatives through Complex Access Patterns + +In most common scenarios, a kernel function will access input tensors in a complex pattern instead of mapping +1:1 from an input element to an output element, like the `square` example shown above. When you have a kernel +function that access many different elements from the input tensors and use them to compute an output element, +the derivatives of each input element can't be represented directly as a function parameter, like the `x` in `square(x)`. + +Consider a 3x3 box filtering kernel that computes for each pixel in a 2D image, the average value of its +surrounding 3x3 pixel block. We can write a Slang function that computes the value of an output pixel: +```csharp +float computeOutputPixel(TensorView input, uint2 pixelLoc) +{ + int width = input.size(0); + int height = input.size(1); + + // Track the sum of neighboring pixels and the number + // of pixels currently accumulated. + int count = 0; + float sumValue = 0.0; + + // Iterate through the surrounding area. + for (int offsetX = -1; offsetX <= 1; offsetX++) + { + // Skip out of bounds pixels. + int x = pixelLoc.x + offsetX; + if (x < 0 || x >= width) continue; + + for (int offsetY = -1; offsetY <= 1; offsetY++) + { + int y = pixelLoc.y + offsetY; + if (y < 0 || y >= height) continue; + sumValue += input[x, y]; + count++; + } + } + + // Compute the average value. + sumValue /= count; + + return sumValue; +} +``` + +We can define our kernel function to compute the entire output image by calling `computeOutputPixel`: + +```csharp +[CudaKernel] +void boxFilter_fwd(TensorView input, TensorView output) +{ + uint2 pixelLoc = (cudaBlockIdx() * cudaBlockDim() + cudaThreadIdx()).xy; + int width = input.dim(0); + int height = input.dim(1); + if (pixelLoc.x >= width) return; + if (pixelLoc.y >= height) return; + + float outputValueAtPixel = computeOutputPixel(input, pixelLoc) + + // Write to output tensor. + output[pixelLoc] = outputValueAtPixel; +} +``` + +How do we define the backward derivative propagation kernel? Note that in this example, there +isn't a function like `square` that we can just mark as `[Differentiable]` and +call `bwd_diff(square)` to get back the derivative of an input parameter. + +In this example, the input comes from multiple elements in a tensor. How do we propagate the +derivatives to those input elements? + +The solution is to wrap tensor access with a custom function: +```csharp +float getInputElement( + TensorView input, + TensorView inputGradToPropagateTo, + uint2 loc) +{ + return input[loc]; +} +``` + +Note that the `getInputElement` function simply returns `input[loc]` and is not using the +`inputGradToPropagateTo` parameter. That is intended. The `inputGradToPropagateTo` parameter +is used to hold the backward propagated derivatives of each input element, and is reserved for later use. + +Now we can replace all direct accesses to `input` with a call to `getInputElement`. The +`computeOutputPixel` can be implemented as following: + +```csharp +[Differentiable] +float computeOutputPixel( + TensorView input, + TensorView inputGradToPropagateTo, + uint2 pixelLoc) +{ + int width = input.dim(0); + int height = input.dim(1); + + // Track the sum of neighboring pixels and the number + // of pixels currently accumulated. + int count = 0; + float sumValue = 0.0; + + // Iterate through the surrounding area. + for (int offsetX = -1; offsetX <= 1; offsetX++) + { + // Skip out of bounds pixels. + int x = pixelLoc.x + offsetX; + if (x < 0 || x >= width) continue; + + for (int offsetY = -1; offsetY <= 1; offsetY++) + { + int y = pixelLoc.y + offsetY; + if (y < 0 || y >= height) continue; + sumValue += getInputElement(input, inputGradToPropagateTo, uint2(x, y)); + count++; + } + } + + // Compute the average value. + sumValue /= count; + + return sumValue; +} +``` + +The main changes compared to our original version of `computeOutputPixel` are: +- Added a `inputGradToPropagateTo` parameter. +- Modified `input[x,y]` with a call to `getInputElement`. +- Added a `[Differentiable]` attribute to the function. + +With that, we can define our backward kernel function: + +```csharp +[CudaKernel] +void boxFilter_bwd( + TensorView input, + TensorView resultGradToPropagateFrom, + TensorView inputGradToPropagateTo) +{ + uint2 pixelLoc = (cudaBlockIdx() * cudaBlockDim() + cudaThreadIdx()).xy; + int width = input.dim(0); + int height = input.dim(1); + if (pixelLoc.x >= width) return; + if (pixelLoc.y >= height) return; + + bwd_diff(computeOutputPixel)(input, inputGradToPropagateTo, pixelLoc); +} +``` + +The kernel function simply calls `bwd_diff(computeOutputPixel)` without taking any return values from the call +and without writing to any elements in the final `inputGradToPropagateTo` tensor. But when exactly does the propagated +output get written to the output gradient tensor (`inputGradToPropagateTo`)? + +And that logic is defined in our final piece of code: +```csharp +[BackwardDerivativeOf(getInputElement)] +void getInputElement_bwd( + TensorView input, + TensorView inputGradToPropagateTo, + uint2 loc, + float derivative) +{ + float oldVal; + inputGradToPropagateTo.InterlockedAdd(loc, derivative, oldVal); +} +``` + +Here, we are providing a custom defined backward propagation function for `getInputElement`. +In this function, we simply add `derivative` to the element in `inputGradToPropagateTo` tensor. + +When we call `bwd_diff(computeOutputPixel)` in `boxFilter_bwd`, the Slang compiler will automatically +differentiate all operations and function calls in `computeOutputPixel`. By wrapping the tensor element access +with `getInputElement` and by providing a custom backward propagation function of `getInputElement`, we are effectively +telling the compiler what to do when a derivative propagates to an input tensor element. Inside the body +of `getInputElement_bwd`, we define what to do then: atomically adds the derivative propagated to the input element +in the `inputGradToPropagateTo` tensor. Therefore, after running `boxFilter_bwd`, the `inputGradToPropagateTo` tensor will contain all the +back propagated derivative values. + +Again, to understand all the details of the automatic differentiation system, please refer to the +[Automatic Differentiation](autodiff) chapter for a detailed explanation. + +## Manually binding kernels +`[AutoPyBindCUDA]` works for most use cases, but in certain situations, it may be necessary to write the *host* function by hand. The host function can also be written in Slang, and `slangtorch` handles its compilation to C++. + +Here's the same `square` example from before: + +```csharp +// square.slang +float compute_square(float x) +{ + return x * x; +} + +[CudaKernel] +void square_kernel(TensorView input, TensorView output) +{ + uint3 globalIdx = cudaBlockIdx() * cudaBlockDim() + cudaThreadIdx(); + + if (globalIdx.x >= input.size(0)) + return; + + float result = compute_square(input[globalIdx.x]); + + output[globalIdx.x] = result; +} +``` + +To manually invoke this kernel, we then need to write a CPU(host) function that defines how this kernel is dispatched. This can be defined in the same Slang file: + +```csharp +[TorchEntryPoint] +TorchTensor square(TorchTensor input) +{ + var result = TorchTensor.zerosLike(input); + let blockCount = uint3(1); + let groupSize = uint3(result.size(0), result.size(1), 1); + __dispatch_kernel(square_kernel, blockCount, groupSize)(input, result); + return result; +} +``` + +Here, we mark the function with the `[TorchEntryPoint]` attribute, so it will be compiled to C++ and exported as a python callable. +Since this is a host function, we can perform tensor allocations. For instance, `square()` calls `TorchTensor.zerosLike` to allocate a 2D-tensor that has the same size as the input. +`zerosLike` returns a `TorchTensor` object that represents a CPU handle of a PyTorch tensor. + +Then we launch `square_kernel` with the `__dispatch_kernel` syntax. Note that we can directly pass +`TorchTensor` arguments to a `TensorView` parameter and the compiler will automatically convert the type and obtain a view into the tensor that can be accessed by the GPU kernel function. + +### Calling a `[TorchEntryPoint]` function from Python + +You can use the following code to call `square` from Python: + +```python +import torch +import slangtorch + +m = slangtorch.loadModule("square.slang") + +x = torch.randn(2,2) +print(f"X = {x}") +y = m.square(x) +print(f"Y = {y.cpu()}") +``` + +Result output: +``` +X = tensor([[ 0.1407, 0.6594], + [-0.8978, -1.7230]]) +Y = tensor([[0.0198, 0.4349], + [0.8060, 2.9688]]) +``` + +### Manual binding for kernel derivatives + +The above example demonstrates how to write a simple kernel function in Slang and call it from Python. +Another major benefit of using Slang is that the Slang compiler support generating backward derivative +propagation functions automatically. + +In the following section, we walk through how to use Slang to generate a backward propagation function +for `square`, and expose it to PyTorch as an autograd function. + +First we need to tell Slang compiler that we need the `square` function to be considered a differentiable function, so Slang compiler can generate a backward derivative propagation function for it: +```csharp +[Differentiable] +float square(float x) +{ + return x * x; +} +``` +This is done by simply adding a `[Differentiable]` attribute to our `square` function. + +With that, we can now define `square_bwd_kernel` that performs backward propagation as: + +```csharp +[CudaKernel] +void square_bwd_kernel(TensorView input, TensorView grad_out, TensorView grad_propagated) +{ + uint3 globalIdx = cudaBlockIdx() * cudaBlockDim() + cudaThreadIdx(); + + if (globalIdx.x >= input.size(0) || globalIdx.y >= input.size(1)) + return; + + DifferentialPair dpInput = diffPair(input[globalIdx.xy]); + var gradInElem = grad_out[globalIdx.xy]; + bwd_diff(square)(dpInput, gradInElem); + grad_propagated[globalIdx.xy] = dpInput.d; +} +``` + +Note that the function follows the same structure of `square_fwd_kernel`, with the only difference being that +instead of calling into `square` to compute the forward value for each tensor element, we are calling `bwd_diff(square)` +that represents the automatically generated backward propagation function of `square`. +`bwd_diff(square)` will have the following signature: +```csharp +void bwd_diff_square(inout DifferentialPair dpInput, float dOut); +``` + +Where the first parameter, `dpInput` represents a pair of original and derivative value for `input`, and the second parameter, +`dOut`, represents the initial derivative with regard to some latent variable that we wish to back-prop through. The resulting +derivative will be stored in `dpInput.d`. For example: + +```csharp +// construct a pair where the primal value is 3, and derivative value is 0. +var dp = diffPair(3.0); +bwd_diff(square)(dp, 1.0); +// dp.d is now 6.0 +``` + +Similar to `square_fwd`, we can define the host side function `square_bwd` as: + +```csharp +[TorchEntryPoint] +TorchTensor square_bwd(TorchTensor input, TorchTensor grad_out) +{ + var grad_propagated = TorchTensor.zerosLike(input); + let blockCount = uint3(1); + let groupSize = uint3(input.size(0), input.size(1), 1); + __dispatch_kernel(square_bwd_kernel, blockCount, groupSize)(input, grad_out, grad_propagated); + return grad_propagated; +} +``` + +## Builtin Library Support for PyTorch Interop + +As shown in previous tutorial, Slang has defined the `TorchTensor` and `TensorView` type for interop with PyTorch +tensors. The `TorchTensor` represents the CPU view of a tensor and provides methods to allocate a new tensor object. +The `TensorView` represents the GPU view of a tensor and provides accessors to read write tensor data. + +Following is a list of built-in methods and attributes for PyTorch interop. + +### `TorchTensor` methods + +#### `static TorchTensor TorchTensor.alloc(uint x, uint y, ...)` +Allocates a new PyTorch tensor with the given dimensions. If `T` is a vector type, the length of the vector is implicitly included as the last dimension. +For example, `TorchTensor.alloc(4, 4)` allocates a 3D tensor of size `(4,4,3)`. + +#### `static TorchTensor TorchTensor.emptyLike(TorchTensor other)` +Allocates a new PyTorch tensor that has the same dimensions as `other` without initializing it. + +#### `static TorchTensor TorchTensor.zerosLike(TorchTensor other)` +Allocates a new PyTorch tensor that has the same dimensions as `other` and initialize it to zero. + +#### `uint TorchTensor.dims()` +Returns the tensor's dimension count. + +#### `uint TorchTensor.size(int dim)` +Returns the tensor's size (in number of elements) at `dim`. + +#### `uint TorchTensor.stride(int dim)` +Returns the tensor's stride (in bytes) at `dim`. + +### `TensorView` methods + +#### `TensorView.operator[uint x, uint y, ...]` +Provide an accessor to data content in a tensor. + +#### `TensorView.operator[vector index]` +Provide an accessor to data content in a tensor, indexed by a uint vector. +`tensor[uint3(1,2,3)]` is equivalent to `tensor[1,2,3]`. + +#### `uint TensorView.dims()` +Returns the tensor's dimension count. + +#### `uint TensorView.size(int dim)` +Returns the tensor's size (in number of elements) at `dim`. + +#### `uint TensorView.stride(int dim)` +Returns the tensor's stride (in bytes) at `dim`. + +#### `void TensorView.fillZero()` +Fills the tensor with zeros. Modifies the tensor in-place. + +#### `void TensorView.fillValue(T value)` +Fills the tensor with the specified value, modifies the tensor in-place. + +#### `T* TensorView.data_ptr_at(vector index)` +Returns a pointer to the element at `index`. + +#### `void TensorView.InterlockedAdd(vector index, T val, out T oldVal)` +Atomically add `val` to element at `index`. + +#### `void TensorView.InterlockedMin(vector index, T val, out T oldVal)` +Atomically computes the min of `val` and the element at `index`. Available for 32 and 64 bit integer types only. + +#### `void TensorView.InterlockedMax(vector index, T val, out T oldVal)` +Atomically computes the max of `val` and the element at `index`. Available for 32 and 64 bit integer types only. + +#### `void TensorView.InterlockedAnd(vector index, T val, out T oldVal)` +Atomically computes the bitwise and of `val` and the element at `index`. Available for 32 and 64 bit integer types only. + +#### `void TensorView.InterlockedOr(vector index, T val, out T oldVal)` +Atomically computes the bitwise or of `val` and the element at `index`. Available for 32 and 64 bit integer types only. + +#### `void TensorView.InterlockedXor(vector index, T val, out T oldVal)` +Atomically computes the bitwise xor of `val` and the element at `index`. Available for 32 and 64 bit integer types only. + +#### `void TensorView.InterlockedExchange(vector index, T val, out T oldVal)` +Atomically swaps `val` into the element at `index`. Available for `float` and 32/64 bit integer types only. + +#### `void TensorView.InterlockedCompareExchange(vector index, T compare, T val)` +Atomically swaps `val` into the element at `index` if the element equals to `compare`. Available for `float` and 32/64 bit integer types only. + +### `DiffTensorView` methods + +#### `DiffTensorView.operator[uint x, uint y, ...]` +Provide an accessor to data content in a tensor. This method is **differentiable**, and has the same semantics as using a `.load()` to get data, and `.store()` to set data. + +#### `DiffTensorView.operator[vector index]` +Provide an accessor to data content in a tensor, indexed by a uint vector.`tensor[uint3(1,2,3)]` is equivalent to `tensor[1,2,3]`. This method is **differentiable**, and has the same semantics as using a `.load()` to get data, and `.store()` to set data. + +#### `float DiffTensorView.load(vector index)` +Loads the 32-bit floating point data at the specified multi-dimensional `index`. This method is **differentiable**, and in reverse-mode will perform an atomic-add. + +#### `void DiffTensorView.store(vector index, float val)` +Stores the 32-bit floating point value `val` at the specified multi-dimensional `index`. This method is **differentiable**, and in reverse-mode will perform an *atomic exchange* to retrieve the derivative and replace with 0. + +#### `float DiffTensorView.loadOnce(vector index)` +Loads the 32-bit floating point data at the specified multi-dimensional `index`. This method is **differentiable**, and uses a simple `store` for the reverse-mode for faster gradient aggregation, but `loadOnce` **must** be used at most once per index. `loadOnce` is ideal for situations where each thread loads data from a unique index, but will cause incorrect gradients when an index may be accessed multiple times. + +#### `void DiffTensorView.storeOnce(vector index, float val)` +Stores the 32-bit floating point value `val` at the specified multi-dimensional `index`. This method is **differentiable**, and uses a simple `load` for the reverse-mode for faster gradient loading, but `storeOnce` **must** be used at most once per index. `loadOnce` is ideal for situations where each thread stores data to a unique index, but will cause incorrect gradient propagation when an index may be accessed multiple times. + +#### `uint DiffTensorView.size(int dim)` +Returns the underlying primal tensor's size (in number of elements) at `dim`. + +#### `uint DiffTensorView.dims()` +Returns the underlying primal tensor's dimension count. + +#### `uint DiffTensorView.stride(uint dim)` +Returns the stride of the underlying primal tensor's `dim` dimension + +### CUDA Support Functions + +#### `cudaThreadIdx()` +Returns the `threadIdx` variable in CUDA. + +#### `cudaBlockIdx()` +Returns the `blockIdx` variable in CUDA. + +#### `cudaBlockDim()` +Returns the `blockDim` variable in CUDA. + +#### `syncTorchCudaStream()` +Waits for all pending CUDA kernel executions to complete on host. + +### Attributes for PyTorch Interop + +#### `[CudaKernel]` attribute +Marks a function as a CUDA kernel (maps to a `__global__` function) + +#### `[TorchEntryPoint]` attribute +Marks a function for export to Python. Functions marked with `[TorchEntryPoint]` will be accessible from a loaded module returned by `slangtorch.loadModule`. + +#### `[CudaDeviceExport]` attribute +Marks a function as a CUDA device function, and ensures the compiler to include it in the generated CUDA source. + +#### `[AutoPyBindCUDA]` attribute +Marks a cuda kernel for automatic binding generation so that it may be invoked from python without having to hand-code the torch entry point. The marked function **must** also be marked with `[CudaKernel]`. If the marked function is also marked with `[Differentiable]`, this will also generate bindings for the derivative methods. + +Restriction: methods marked with `[AutoPyBindCUDA]` will not operate + +## Type Marshalling Between Slang and Python + + +### Python-CUDA type marshalling for functions using `[AutoPyBindCUDA]` + +When using auto-binding, aggregate types like structs are converted to Python `namedtuples` and are made available when using `slangtorch.loadModule`. + +```csharp +// mesh.slang +struct Mesh +{ + TensorView vertices; + TensorView indices; +}; + +[AutoPyBindCUDA] +[CUDAKernel] +void processMesh(Mesh mesh) +{ + /* ... */ +} +``` + +Here, since `Mesh` is being used by `renderMesh`, the loaded module will provide `Mesh` as a python `namedtuple` with named fields. +While using the `namedtuple` is the best way to use structured arguments, they can also be passed as a python `dict` or `tuple` + +```python +m = slangtorch.loadModule('mesh.slang') + +vertices = torch.tensor() +indices = torch.tensor() + +# use namedtuple to provide structured input. +mesh = m.Mesh(vertices=vertices, indices=indices) +m.processMesh(mesh=mesh).launchRaw(blockSize=(32, 32, 1), gridSize=(1, 1, 1)) + +# use dict to provide input. +mesh = {'vertices': vertices, 'indices':indices} +m.processMesh(mesh=mesh).launchRaw(blockSize=(32, 32, 1), gridSize=(1, 1, 1)) + +# use tuple to provide input (warning: user responsible for right order) +mesh = (vertices, indices) +m.processMesh(mesh=mesh).launchRaw(blockSize=(32, 32, 1), gridSize=(1, 1, 1)) +``` + + +### Python-CUDA type marshalling for functions using `[TorchEntryPoint]` + +The return types and parameters types of an exported `[TorchEntryPoint]` function can be a basic type (e.g. `float`, `int` etc.), a vector type (e.g. `float3`), a `TorchTensor` type, an array type, or a struct type. + +When you use struct or array types in the function signature, it will be exposed as a Python tuple. +For example, +```csharp +struct MyReturnType +{ + TorchTensor tensors[3]; + float v; +} + +[TorchEntryPoint] +MyReturnType myFunc() +{ + ... +} +``` + +Calling `myFunc` from python will result in a python tuple in the form of +``` +[[tensor, tensor, tensor], float] +``` + +The same transform rules apply to parameter types. diff --git a/lib/All/slang/share/doc/slang/design/README.md b/lib/All/slang/share/doc/slang/design/README.md new file mode 100644 index 0000000..58e1e39 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/README.md @@ -0,0 +1,25 @@ +Slang Design and Implementation Notes +===================================== + +This directory contains documents that are primarily intended for developers working on the Slang implementation. +They are not intended to be helpful to Slang users. + +These documents can only be trusted to reflect the state of the codebase or the plans of their authors at the time they were written. Changes to the implementation are not expected to always come with matching changes to these documents, so some amount of drift is to be expected. + +Developers interested in contributing to Slang might want to start with the [Overview](overview.md) document, which describes the overall compilation pipeline that Slang uses and the purpose of the various steps (both implemented and planned). + +The [Coding Conventions](coding-conventions.md) document describes the conventions that should be followed in all code added to the Slang project. + +The [Interfaces](interfaces.md) document describes the high-level design plan for Slang's interfaces and generics features. + +The [Declaration References](decl-refs.md) document is intended to help out developers who are mystified by the heavily used `DeclRef` type in the compiler implementation. + +The [Intermediate Representation (IR)](ir.md) document describes the design of Slang's internal IR. + +The [Existential Types](existential-types.md) document goes into some detail about what "existential types" are in the context of the Slang language, and explains how we may go about supporting them. + +The [Capabilities](capabilities.md) document explains the proposed model for how Slang will support general notions of profile- or capability-based overloading/dispatch. + +The [Casting](casting.md) document explains how casting works in the slang C++ compiler code base. + +The [Experimental API Interfaces](experimental.md) document explains how experimental Slang API changes are to be deployed. \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/design/autodiff.md b/lib/All/slang/share/doc/slang/design/autodiff.md new file mode 100644 index 0000000..8bf26ba --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/autodiff.md @@ -0,0 +1,333 @@ +Reverse Mode Autodiff (Out of Date) +================================== + + +This document serves as a design reference for reverse-mode auto-diff in the Slang compiler. + +## Reverse-Mode Passes + +Rather than implementing reverse-mode as a separate pass, Slang implements this as a series of independent passes: + +If a function needs a reverse-mode version generated: + - *Linearize* the function, and all dependencies. + - *Propagate* differential types through the linearized code. + - *Unzip* by moving primal insts to before differential insts. + - *Transpose* the differential insts. + + +## Linearization (Forward-mode) + +### Overview +(This is a incomplete section. More details coming soon) + +Consider an arbitrary function `float f(float a, float b, float c, ..., z)` which takes in N inputs and generates one output `y`. Linearization aims to generate the first-order Taylor expansion of f about _all_ of it's inputs. + +Mathematically, the forward derivative `fwd_f` represents `df/da * (a_0 - a) + df/db * (b_0 - b) + ...`, where `a_0` is the value at which the Taylor expansion was produced. The quantity `a_0 - a` is known as the 'differential' (for brevity we'll denote them da, db, dc, etc..), and there is at-most one differential per input. + +Thus, the new function's signature should be `fwd_f(float a, float da, float b, float db, float c, float dc, ...)`. For simplicity, we'll use *pairs* instead of interleaving the original and differential parameters. We use the intrinsic `DifferentialPair` (or for short: `DP`) to denote this. + +The signature we use is then `fwd_f(DP a, DP b, DP c)` + +An example of linearization: +```C + +float f(float a, float b) +{ + if (a > 0) + { + return a + b + 2.0 * a * b; + } + else + { + return sqrt(a); + } +} +``` + +We'll write out the SSA form of this function. + +```C +float f_SSA(float a, float b) +{ + bool _b1 = a > 0; + if (_b1) + { + float _t1 = a + b; + float _t2 = 2.0 * a; + float _t3 = _t2 * b; + float _t4 = _t1 + _t3; + + return _t4; + } + else + { + float _t1 = sqrt(a); + return _t1; + } +} + +DP f_SSA(DP dpa, DP dpb) +{ + + bool _b1 = dpa.p > 0; + if (_b1) + { + float _t1 = dpa.p + dpb.p; + float _t1_d = dpa.d + dpb.d; + + float _t2 = 2.0 * dpa.p; + float _t2_d = 0.0 * dpa.p + 2.0 * dpa.d; + + float _t3 = _t2 * dpb.p; + float _t3_d = _t2_d * dpb.p + _t2 * dpb.d; + + float _t4 = _t1 + _t3; + float _t4_d = _t1_d + _t3_d; + + return DP(_t4, _t4_d); + } + else + { + DP _t1_dp = sqrt_fwd(dpa); + return DP(_t1_dp.p, _t1_dp.d); + } +} + +``` + +In the result, the primal part of the pair holds the original computation, while the differential part computes the dot product of the differentials with the derivatives of the function's output w.r.t each input. + + +## Propagation + +This step takes a linearized function and propagates information about which instructions are computing a differential and which ones are part of the primal (original) computation. + +Assuming first-order differentiation only: +The approach will be to mark any instructions that extract the differential from the differential pair as a differential. Then any instruction that uses the differential is itself marked as a differential and so on. The only exception is the call instruction which is either non-differentiable (do nothing) or differentiable and returns a pair (follow the same process) + + +Here's the above example with propagated type information (we use float.D to denote intermediaries that have been marked as differential, and also expand everything so that each line has a single operation) + +```C + +DP f_SSA_Proped(DP dpa, DP dpb) +{ + bool _b1 = dpa.p > 0; + if (_b1) + { + float _t1 = dpa.p + dpb.p; + + float.D _q1_d = dpa.d; + float.D _q2_d = dpb.d; + + float.D _t1_d = _q1_d + _q2_d; + + float _t2 = 2.0 * dpa.p; + + float.D _q2_d = dpa.d; + float.D _q3_d = 2.0 * dpa.d; + + float _q4 = dpa.p; + float.D _q4_d = 0.0 * dpa.p; + + float.D _t2_d = _q4_d + _q3_d; + + float _t3 = _t2 * dpb.p; + + float _q5 = dpb.p; + float.D _q6_d = _q5 * _t2_d; + + float.D _q7_d = dpb.d; + float.D _q8_d = _t2 * _q7_d + + float _t3_d = _q6_d + _q8_d; + + float _t4 = _t1 + _t3; + + float.D _t4_d = _t1_d + _t3_d; + + return DP(_t4, _t4_d); + } + else + { + DP _t1_dp = sqrt_fwd(dpa); + + float _q1 = _t1_dp.p; + float.D _q1_d = _t1_dp.d; + + return DP(_q1, _q1_d); + } +} + +``` + +## Unzipping + + +This is a fairly simple process when there is no control flow. We simply move all non-differential instructions to before the first differential instruction. + +When there is control flow, we need to be a bit more careful: the key is to *replicate* the control flow graph once for primal and once for the differential. + +Here's the previous example unzipped: + + +```C + +DP f_SSA_Proped(DP dpa, DP dpb) +{ + bool _b1 = dpa.p > 0; + + float _t1, _t2, _q4, _t3, _q5, _t3_d, _t4, _q1; + + if (_b1) + { + _t1 = dpa.p + dpb.p; + + _t2 = 2.0 * dpa.p; + + _q4 = dpa.p; + + _t3 = _t2 * dpb.p; + + _q5 = dpb.p; + + _t4 = _t1 + _t3; + + } + else + { + + _q1 = sqrt_fwd(DP(dpa.p, 0.0)); + } + + // Note here that we have to 'store' all the intermediaries + // _t1, _t2, _q4, _t3, _q5, _t3_d, _t4 and _q1. This is fundamentally + // the tradeoff between fwd_mode and rev_mode + + if (_b1) + { + float.D _q1_d = dpa.d; + float.D _q2_d = dpb.d; + + float.D _t1_d = _q1_d + _q2_d; + + float.D _q2_d = dpa.d; + float.D _q3_d = 2.0 * dpa.d; + + float.D _q4_d = 0.0 * dpa.p; + + float.D _t2_d = _q4_d + _q3_d; + + float.D _q6_d = _q5 * _t2_d; + + float.D _q7_d = dpb.d; + float.D _q8_d = _t2 * _q7_d + + float.D _t3_d = _q6_d + _q8_d; + + float.D _t4_d = _t1_d + _t3_d; + + return DP(_t4, _t4_d); + } + else + { + DP _t1_dp = sqrt_fwd(dpa); + + float.D _q1_d = _t1_dp.d; + + return DP(_q1, _q1_d); + } +} + +``` + +## Transposition + +### Overview + +This transposition pass _assumes_ that provided function is linear in it's differentials. +It is out of scope of this project to attempt to enforce that constraint for user-defined differential code. + +For transposition we walk all differential instructions in reverse starting from the return statement, and apply the following rules: + +We'll have an accumulator dictionary `Dictionary accMap` holding assignments for +intermediaries which don't have concrete variables. When we add a pair (A, C) and (A, B) already exists, this will form the pair (A, ADD(C, B)) in the dictionary. (ADD will be replaced with a call to `T.dadd` for a generic type T) + + - If `inst` is a `RETURN(A)`, add pair `(A, d_out)` to `accMap` + - If an instruction is `MUL(P, D)` where D is the differential, add pair `(D, MUL(P, accMap[this_inst]))` to `accMap` + - If an instruction is `ADD(D1, D2)`, where both D1 and D2 are differentials (this is the only config that should occur), then add pair `(D1, accMap[this_inst])` to `accMap` + - If an instruction is `CALL(f_fwd, (P1, D1), (P2, D2), ...)`, create variables D1v, D2v, ... for D1, D2, ..., then replace with `CALL(f_rev, (P1, D1v), (P2, D2v), ..., accMap[this_inst])`, and finally add pairs `(D1, LOAD[D1v]), (D2, LOAD[D2v]), ...` to `accMap` + + ```C + +void f_SSA_Rev(inout DP dpa, inout DP dpb, float dout) +{ + bool _b1 = dpa.p > 0; + + float _t1, _t2, _q4, _t3, _q5, _t3_d, _t4, _q1; + + if (_b1) + { + _t1 = dpa.p + dpb.p; + + _t2 = 2.0 * dpa.p; + + _q4 = dpa.p; + + _t3 = _t2 * dpb.p; + + _q5 = dpb.p; + + _t4 = _t1 + _t3; + + } + else + { + + _q1 = sqrt_fwd(DP(dpa.p, 0.0)); + } + + // Note here that we have to 'store' all the intermediaries + // _t1, _t2, _q4, _t3, _q5, _t3_d, _t4 and _q1. This is fundamentally + // the tradeoff between fwd_mode and rev_mode + + if (_b1) + { + + float.D _t4_rev = d_out; + + float.D _t1_rev = _t4_rev; + float.D _t3_rev = _t4_rev; + + float.D _q8_rev = _t3_rev; + float.D _q6_rev = _t3_rev; + + float.D _q7_rev = _t2 * _q8_rev; + + dpb.d += _q7_rev; + + float.D _t2_rev = _q5 * _q6_rev; + + float.D _q4_rev = _t2_rev; + float.D _q3_rev = _t2_rev; + + dpa.d += 2.0 * _q3_rev; + + float.D _q1_rev = _t1_rev; + float.D _q2_rev = _t1_rev; + + dpb.d += _q2_rev; + dpa.d += _q1_rev; + } + else + { + _q1_rev = d_out; + + DP dpa_copy; + sqrt_rev(dpa_copy, _q1_rev); + + dpa.d += dpa_copy.d; + } +} + +``` diff --git a/lib/All/slang/share/doc/slang/design/autodiff/basics.md b/lib/All/slang/share/doc/slang/design/autodiff/basics.md new file mode 100644 index 0000000..43ed164 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/autodiff/basics.md @@ -0,0 +1,396 @@ + + +This documentation is intended for Slang contributors and is written from a compiler engineering point of view. For Slang users, see the user-guide at this link: [https://shader-slang.com/slang/user-guide/autodiff.html](https://shader-slang.com/slang/user-guide/autodiff.html) + +## What is Automatic Differentiation? + +Before diving into the design of the automatic differentiation (for brevity, we will call it 'auto-diff') passes, it is important to understand the end goal of what auto-diff tries to achieve. + +The over-arching goal of Slang's auto-diff is to enable the user to compute derivatives of a given shader program or function's output w.r.t its input parameters. This critical compiler feature enables users to quickly use their shaders with gradient-based parameter optimization algorithms, which forms the backbone of modern machine learning systems. It enables users to train and deploy graphics systems that contain ML primitives (like multi-layer perceptron's or MLPs) or use their shader programs as differentiable primitives within larger ML pipelines. + +### More Resources +Here are some links to resources that talk more about differentiable programming from a more mathematical perspective: +1. UCSD CSE 291 (Spring 2024): https://cseweb.ucsd.edu/~tzli/cse291/sp2024/ +2. UW CSE 5990 (Winter 2024): https://sites.google.com/cs.washington.edu/cse-599o-dppl + +## Definition of Derivatives + +This section is based off of these slides: https://cseweb.ucsd.edu/~tzli/cse291/sp2024/lectures/03_forward_mode.pdf. + +Here, we establish the mathematical definition of derivatives, starting with a simple 1D case (function with a single input and output), and extending to the general case of functions mapping multiple inputs to multiple outputs. + +To avoid confusion, we will denote mathematical functions using LaTeX italic script ($f$, $g$, etc..) and programs that compute these functions with markdown code (`f`, `g`, etc..) + +### Derivatives of scalar (1D) functions + +Consider the simplest case: a smooth scalar mathematical function that maps a real number to another real number: + +$$f : \mathbb{R} \to \mathbb{R}$$ + +There are several definitions for a derivative, but we will use the definition that a derivative is the *closest linear approximation* of the output function at a given input location. +Concretely, given a specific input $x$, we can create a linear approximation of the function $f$ around $x$ as follows: + +$$ f(x + dx) \approx f(x) + Df(x) \cdot dx $$ + + +This can also be understood as a geometric 'tangent' to the function at $x$. $Df(x)$ is the slope of $f$ at $x$, i.e. $\frac{\partial f}{\partial x}$, and $dx$ is the perturbation away from $x$. Our approximation is linear as a function of the perturbation $dx$. Note that no matter how non-linear or complex the underlying function $f(x)$ is, the approximation is always linear (this property becomes very important later). + +### Forward-mode derivative functions + +Now consider a concrete program `f` that computes some function. + +```C +// Computes square of x +float f(float x) +{ + return x * x; +} +``` + +What should its derivative program look like? We the need the output $f(x)$ and the product of derivative at $x$, $Df(x)$ with the differential $dx$. + +In Slang, we put both of these together into a single function, called the *forward-mode derivative* function, which takes in a pair $(x, dx)$ returns a pair $(f(x), Df(x)\cdot dx)$ Note that in auto-diff literature, this is also often referred to as the *total derivative* function. + +```C +DifferentialPair fwd_f(DifferentialPair dpx) +{ + float x = dpx.getPrimal(); // Can also be accessed via property dpx.p + float dx = dpx.getDifferential(); // Can also be accessed via property dpx.d + return makePair(x * x, (2 * x) * dx); +} +``` + +Note that `(2 * x)` is the multiplier corresponding to $Df(x)$. We refer to $x$ and $f(x)$ as "*primal*" values and the perturbations $dx$ and $Df(x)\cdot dx$ as "*differential*" values. The reason for this separation is that the "*differential*" output values are always linear w.r.t their "*differential*" inputs. + +As the name implies, `DifferentialPair` is a special pair type used by Slang to hold values and their corresponding differentials. + + +### Forward-mode derivatives for higher-dimensional functions +In practice, most functions tend to have multiple inputs and multiple outputs, i.e. $f: \mathbb{R}^N \to \mathbb{R}^M$ + +The definition above can be extended to higher dimensions, using the closest-linear-approximation idea. The main difference is that the derivative function represents a hyperplane rather than a line. + +Effectively, we want our forward-mode derivative to compute the following: + +$$ f(\mathbf{x} + \mathbf{dx}) \approx f(\mathbf{x}) + \langle Df(\mathbf{x}),\mathbf{dx}\rangle $$ + +Here, the input and its differential can be represented as a vector quantity $\mathbf{x}, \mathbf{dx} \in \mathbb{R}^N$ and the multiplier $Df(\mathbf{x})$ (also known as the *Jacobian* matrix) is a NxM matrix, and $\left\< \cdot,\cdot \right\>$ denotes the inner product (i.e. matrix-vector multiplication) + +Here's an example of a Slang function taking in two inputs (N=2) and generating one output (M=1) + +```C +// Compute length of hypotenuse. +float f(float x, float y) +{ + return sqrt(x * x + y * y); +} +``` + +and its forward-mode derivative: + +```C +// Closest linear approximation at x, y +DifferentialPair fwd_f(DifferentialPair dpx, DifferentialPair dpy) +{ + float x = dpx.p; + float y = dpy.p; + float dx = dpx.d; + float dy = dpx.d; + + return DifferentialPair( + sqrt(x * x + y * y), // f(x, y) + (x * dx + y * dy) / sqrt(x * x, y * y)); // +} +``` + +Important note: the forward-mode function only needs to compute the inner product $\langle Df(\mathbf{x}),\mathbf{dx} \rangle$. The Jacobian matrix itself never needs to be fully materialized. This is a key design element of automatic differentiation, one which allows it to scale to huge input/output counts. + +### Building Blocks: Forward-mode derivatives compose in forward order of execution. + +In practice, we compute forward-mode derivatives of a complex function by decomposing them into constituent functions (or in compiler-speak: instructions) and composing the forward-mode derivative of each piece in the **same** order. +This is because of each forward derivative is a 'right-side' product (or product of Jacobian matrix with a vector) + +Here's an example of this in action (consider a complex function $h$ composed of $f$ and $g$): + +$$ h(\mathbf{x}) = f(g(\mathbf{x})) $$ + +It's forward-mode derivative is then: + +$$ \langle Dh(\mathbf{x}), \mathbf{dx}\rangle = \big\langle Df(\mathbf{x}), \langle Dg(\mathbf{x}), \mathbf{dx}\rangle\big\rangle $$ + +which is the forward-mode derivative of the outer function $f$ evaluated on the result of the forward-mode derivative of the inner function $g$. + +An example of this in Slang code: +```C +// Compute square. +float sqr(float x) +{ + return x * x; +} + +// Compute length of hypotenuse. +float f(float x, float y) +{ + float x_sqr = sqr(x); + float y_sqr = sqr(y) + return sqrt(x_sqr + y_sqr); +} +``` + +The resulting derivative of `f` can be computed by composition: +```C +// Forward-mode derivative of sqr() +DifferentialPair fwd_sqr(DifferentialPair dpx) +{ + float x = dpx.getPrimal(); + float dx = dpx.getDifferential(); + + return DifferentialPair(x * x, 2 * x * dx); +} + +// Forward-mode derivative of f() +DifferentialPair fwd_f(DifferentialPair dpx, DifferentialPair dpy) +{ + DifferentialPair dp_x_sqr = fwd_sqr(dpx); + DifferentialPair dp_y_sqr = fwd_sqr(dpy); + + float x_sqr = dp_x_sqr.getPrimal(); + float y_sqr = dp_y_sqr.getPrimal(); + float x_sqr_d = dp_x_sqr.getDifferential(); + float y_sqr_d = dp_y_sqr.getDifferential(); + + return DifferentialPair( + sqrt(x_sqr + y_sqr), + (x_sqr_d + y_sqr_d) / sqrt(x_sqr + y_sqr)); +} +``` + +### Tip: Extracting partial derivatives from a forward-mode derivative (i.e. a 'total' derivative) + +As we discussed above, forward-mode derivatives compute $\langle Df(\mathbf{x}),\mathbf{dx}\rangle$ rather than what you may be used to seeing in a calculus course (e.g. partial derivatives like $\frac{\partial f}{\partial x}$). + +In fact, the forward-mode derivative is simply an product of the partial derivative w.r.t each input parameter multiplied by their differential perturbations $\frac{\partial f}{\partial x} * dx + \frac{\partial f}{\partial x} * dy$. This is the reason for the alternative name: *total derivative*. + +Thus, partial derivative can be obtained by successively setting each input's differential to 1 (and 0 for everything else) +Example: +```C +// Compute partial derivative w.r.t x (pass dx=1.0) +float df_dx = fwd_f(DifferentialPair(x, 1.0), DifferentialPair(y, 0.0)).d; + +// Compute partial derivaive w.r.t y (pass dy=1.0) +float df_dy = fwd_f(DifferentialPair(x, 0.0), DifferentialPair(y, 1.0)).d; +``` + +### Tip: Testing forward-mode derivatives using the first principles of calculus (i.e. the *finite difference* method) + +In Calculus, partial derivatives of a function are often defined in a 'black box' manner using limits, by perturbing a single parameter by an infinitesimal amount: + +$$ \frac{\partial f}{\partial x} = \lim_{dx\to 0} \frac{f(x + dx) - f(x - dx)}{2 * dx} $$ + +At the moment, we cannot leverage programming languages to compute true inifinitesimal limits, but we can replace $dx \to 0$ with a sufficiently small $\epsilon$ leading to the following 'test' to check if derivatives produced by automatic differentiation match with their true mathematical expected values. + +Here's an example of using this idea to test functions (many autodiff tests were written this way) + +```C +// Compute partial derivative w.r.t x analytically +float df_dx_ad = fwd_f(DifferentialPair(x, 1.0), DifferentialPair(y, 0.0)) + +// Compute partial derivative w.r.t x through the finite difference (FD) method. +float eps = 1e-4 +float df_dx_fd = (f(x + eps, y) - f(x - eps, y)) / (2 * eps); + +// If computed correctly, df_dx_ad and df_dx_fd are very close. +``` + +**Caveats:** +Since the finite difference method only produces a biased estimate of the derivative, the result is only numerically *close* to the auto-diff-based result. Poorly behaved functions (those that rapidly change, or are discontinuous or otherwise non-differentiable) will result in a (expected) mismatch between FD and AD results. + +## Reverse-mode derivative functions + +This section is based off of these slides: https://cseweb.ucsd.edu/~tzli/cse291/sp2024/lectures/05_reverse_mode.pdf. + +### Motivation: Challenges with scaling forward-mode derivatives + +A big problem with forward-mode derivatives is their inability to scale to great parameter counts. + +Machine learning pipelines often compute derivatives of a large complex pipeline with millions or even billions of input parameters, but a single output value, i.e. the *loss* or *objective* function, frequently denoted by $\mathcal{L}$. +Computing $\frac{\partial \mathcal{L}}{\partial x_i}$ for $N$ inputs $x_i$ using the one-hot vector approach will involve invoking the forward-mode derivative function $N$ times. + +The reason for this limitation is that forward-mode derivatives pass derivatives from the inputs through to the outputs by computing the dot-product $\left\< Df(\mathbf{x}),\mathbf{dx}\right\>$. +Instead, we employ a different approach called the reverse-mode derivative, which propagates differentials *backwards* from outputs to inputs. + +### Key Idea: Generate code to compute $\langle \frac{\partial \mathcal{L}}{\partial f}, Df(\mathbf{x})\rangle$ rather than $\langle Df(\mathbf{x}),\mathbf{dx}\rangle$ + +The fundamental building blocks of reverse-mode derivatives are the **left-side inner product**. That is, the product of a vector of derivatives of w.r.t outputs $\frac{\partial \mathcal{L}}{\partial f}$ with the Jacobian matrix $Df(\mathbf{x})$. + +An important thing to keep in mind is that it does not necessarily matter what the scalar quantity $\mathcal{L}$ is. The goal of this product is to propagate the derivatives of any scalar value $\mathcal{L}$ w.r.t output vector $f(\mathbf{x})$ (i.e., $\frac{\partial \mathcal{L}}{\partial f}$) into derivatives of that same scalar value $\mathcal{L}$ w.r.t the input vector $\mathbf{x}$ (i.e., $\frac{\partial \mathcal{L}}{\partial \mathbf{x}}$). + +Here's an example of a Slang function computing the `reverse-mode derivative`. + +```C +// Compute length of hypotenuse +float f(float x, float y) +{ + return sqrt(x * x + y * y); +} + +// Reverse-mode derivative of f. dOutput represents the derivative dL/dOutput of the output w.r.t scalar value. +void rev_f(inout DifferentialPair dpx, inout DifferentialPair dpy, float dOutput) +{ + float x = dpx.getPrimal(); + float y = dpy.getPrimal(); + + float t = 1.0 / (sqrt(x * x + y * y)); + + dpx = DifferentialPair( + x, // The primal part of the return value is *always* copied in from the input as-is. + dOutput * x * t); // The differential part for x is the derivative dL/dx computed as + // (dL/dOutput) * (dOutput/dx), where dOutput/dx = x / sqrt(x*x+y*y). + + dpy = DifferentialPair( + y, + dOutput * y * t); // The differential part for y is the derivative dL/dy computed as + // (dL/dOutput) * (dOutput/dy), where dOutput/dy = y / sqrt(x*x+y*y). +} +``` + +Note that `rev_f` accepts derivatives w.r.t the output value as the input, and returns derivatives w.r.t inputs as its output (through `inout` parameters). `rev_f` still needs the primal values `x` and `y` to compute the derivatives, so those are still passed in as an input through the primal part of the differential pair. + +Also note that the reverse-mode derivative function does not have to compute the primal result value (its return is void). The reason for this is a matter of convenience: reverse-mode derivatives are often invoked after all the primal functions, and there is typically no need for these values. We go into more detail on this topic in the checkpointing chapter. + +The reverse mode function can be used to compute both `dOutput/dx` and `dOutput/dy` with a single invocation (unlike the forward-mode case where we had to invoke `fwd_f` once for each input) + +```C +DifferentialPair dpx = makePair(x, 0.f); // Initialize diff-value to 0 (not necessary) +DifferentialPair dpx = makePair(y, 0.f); // Initialize diff-value to 0 (not necessary) + +rev_f(dpx, dpy, 1.0); // Pass 1.0 for dL/dOutput so that the results are (1.0 * dOutput/dx) and (1.0 * dOutput/dy) + +float doutput_dx = dpx.getDifferential(); +float doutput_dy = dpy.getDifferential(); +``` + +### Extension to multiple outputs +The extension to multiple outputs is fairly natural. Each output gets a separate input for its derivative. +Here is an example: +```C +// Computation involving multiple inputs and outputs. +float2 f_multi_output(float x, float y) +{ + return float2( + x * x, + x + y); +} + +// Reverse-mode derivative of 'f_multi_output'. The derivative of the outputs is also a vector quantity +// (type follows from return type of f_multi_output) +void rev_f_multi_output(DifferentialPair dpx, DifferentialPair dpy, float2 dOut) +{ + float x = dpx.getPrimal(); + float y = dpy.getPrimal(); + + dpx = DifferentialPair(x, dOut[0] * 2 * x + dOut[1]); + dpy = DifferentialPair(x, dOut[1]); +} +``` + +### Jacobian method: Generate forward- and reverse-mode derivatives from first principles. +A simple way to figure out what the generated reverse (or forward) derivative function is supposed to compute is to write down the entire Jacobian function. That is, write down the partial derivative of each input w.r.t each output + +$$ +D\mathbf{f}(\mathbf{x}) = \begin{bmatrix} +\partial f_0 / \partial x & \partial f_0 / \partial y \\ +\partial f_1 / \partial x & \partial f_1 / \partial y \\ +\end{bmatrix} = +\begin{bmatrix} +2x & 0.0 \\ +1.0 & 1.0 \\ +\end{bmatrix} +$$ + +The **reverse-mode derivative**'s outputs should match the left-product of this matrix with the vector of derivatives w.r.t outputs: + +$$ \left\langle \frac{\partial \mathcal{L}}{\partial \mathbf{f}}, D\mathbf{f}(\mathbf{x})\right\rangle = +\begin{bmatrix} +\frac{\partial \mathcal{L}}{\partial f_0} & \frac{\partial \mathcal{L}}{\partial f_1} +\end{bmatrix} +\begin{bmatrix} +2x & 0.0 \\ +1.0 & 1.0 \\ +\end{bmatrix} = +\begin{bmatrix} \left(\frac{\partial \mathcal{L}}{\partial f_0} \cdot 2x + \frac{\partial \mathcal{L}}{\partial f_1}\right) & \frac{\partial \mathcal{L}}{\partial f_1} \end{bmatrix} +$$ + +and the **forward-mode derivative**'s outputs should match the right-product of this matrix with the vector of differentials of the inputs: + +$$ \langle D\mathbf{f}(\mathbf{x}), d\mathbf{x}\rangle = +\begin{bmatrix} +2x & 0.0 \\ +1.0 & 1.0 \\ +\end{bmatrix} +\begin{bmatrix} +dx \\ dy +\end{bmatrix} = +\begin{bmatrix} 2x \cdot dx & dx + dy \end{bmatrix} +$$ + +Note that when we generate derivative code in practice, we do not materialize the full Jacobian matrix, and instead use the composition property to chain together derivatives at the instruction level. +However, the resulting code is equivalent to the Jacobian method (mathematically), and it is a good, analytical way to confirm that the generated code is indeed correct (or when thinking about what the derivative of a particular instruction/set of instructions should be) + + +### Building Blocks: Reverse-mode derivatives compose in reverse order of execution. +A consequence of using the 'left-side inner product' is that derivatives of a composite function must be computed in the reverse of the order of primal computation. + +Here's an example of a composite function $h$ (similar to the example used in forward-mode building blocks): + +$$ h(\mathbf{x}) = f(g(\mathbf{x})) $$ + +where (for brevity): + +$$ \mathbf{y} = g(\mathbf{x}) $$ + +The reverse-mode derivative function for $h$ can be written as the composition of the reverse-mode derivatives of $f$ and $g$ + +$$ \left\langle \frac{\partial L}{\partial h}, Dh(\mathbf{x})\right\rangle = \left\langle \left\langle \frac{\partial L}{\partial h}, Df(\mathbf{y})\right\rangle , Dg(\mathbf{x})\right\rangle $$ + +Note the 'backward' order here. We must first pass the derivatives through the outer function $f$, and then pass the result through the inner function $g$ to compute derivatives w.r.t inner-most inputs $\mathbf{x}$. This process of passing derivatives backwards is often referred to as *backpropagation*. + +A more concrete Slang example of the same: + +```C +// Compute square +float sqr(float x) +{ + return x * x; +} + +// Compute length of hypotenuse +float f(float x, float y) +{ + return sqrt(sqr(x) + sqr(y)); +} +``` + +The derivative functions are then: +```C +void rev_sqr(DifferentialPair dpx, float dOutput) +{ + float x = dpx.getPrimal(); + + dpx = DifferentialPair(x, dOutput * 2 * x); +} + +void rev_f(DifferentialPair dpx, DifferentialPair dpy, float dOut) +{ + float t = 0.5f / sqrt(x * x + y * y); + + float d_xsqr = t * dOut; // Calculate derivatives w.r.t output of sqr(x) + float d_ysqr = t * dOut; // Calculate derivatives w.r.t output of sqr(y) + + rev_sqr(dpx, d_xsqr); // Propagate to x + rev_sqr(dpx, d_ysqr); // Propagate to y +} +``` + +When comparing `rev_f`'s implementation to `fwd_f`, note the order of computing derivative w.r.t `sqr` (in `rev_f`, `rev_sqr` is called at the end, while in `fwd_f` it is called at the beginning) + diff --git a/lib/All/slang/share/doc/slang/design/autodiff/decorators.md b/lib/All/slang/share/doc/slang/design/autodiff/decorators.md new file mode 100644 index 0000000..27bf0e3 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/autodiff/decorators.md @@ -0,0 +1,92 @@ +This document details auto-diff-related decorations that are lowered in to the IR to help annotate methods with relevant information. + +## `[Differentiable]` +The `[Differentiable]` attribute is used to mark functions as being differentiable. The auto-diff process will only touch functions that are marked explicitly as `[Differentiable]`. All other functions are considered non-differentiable and calls to such functions from a differentiable function are simply copied as-is with no transformation. + +Further, only `[Differentiable]` methods are checked during the derivative data-flow pass. This decorator is translated into `BackwardDifferentiableAttribute` (which implies both forward and backward differentiability), and then lowered into the IR `OpBackwardDifferentiableDecoration` + +**Note:** `[Differentiable]` was previously implemented as two separate decorators `[ForwardDifferentiable]` and `[BackwardDifferentiable]` to denote differentiability with each type of auto-diff transformation. However, these are now **deprecated**. The preferred approach is to use only `[Differentiable]` + +`fwd_diff` and `bwd_diff` cannot be directly called on methods that don't have the `[Differentiable]` tag (will result in an error). If non-`[Differentiable]` methods are called from within a `[Differentiable]` method, they must be wrapped in `no_diff()` operation (enforced by the [derivative data-flow analysis pass](./types.md#derivative-data-flow-analysis) ) + +### `[Differentiable]` for `interface` Requirements +The `[Differentiable]` attribute can also be used to decorate interface requirements. In this case, the attribute is handled in a slightly different manner, since we do not have access to the concrete implementations. + +The process is roughly as follows: +1. During the semantic checking step, when checking a method that is an interface requirement (in `checkCallableDeclCommon` in `slang-check-decl.cpp`), we check if the method has a `[Differentiable]` attribute +2. If yes, we construct create a set of new method declarations, one for the forward-mode derivative (`ForwardDerivativeRequirementDecl`) and one for the reverse-mode derivative (`BackwardDerivativeRequirementDecl`), with the appropriate translated function types and insert them into the same interface. +3. Insert a new member into the original method to reference the new declarations (`DerivativeRequirementReferenceDecl`) +4. When lowering to IR, the `DerivativeRequirementReferenceDecl` member is converted into a custom derivative reference by adding the `OpBackwardDerivativeDecoration(deriv-fn-req-key)` and `OpForwardDerivativeDecoration(deriv-fn-req-key)` decorations on the primal method's requirement key. + +Here is an example of what this would look like: + +```C +interface IFoo +{ + [Differentiable] + float bar(float); +}; + +// After checking & lowering +interface IFoo_after_checking_and_lowering +{ + [BackwardDerivative(bar_bwd)] + [ForwardDerivative(bar_fwd)] + float bar(float); + + void bar_bwd(inout DifferentialPair, float); + + DifferentialPair bar_fwd(DifferentialPair); +}; +``` + +**Note:** All conforming types must _also_ declare their corresponding implementations as differentiable so that their derivative implementations are synthesized to match the interface signature. In this sense, the `[Differentiable]` attribute is part of the functions signature, so a `[Differentiable]` interface requirement can only be satisfied by a `[Differentiable]` function implementation + +### `[TreatAsDifferentiable]` +In large codebases where some interfaces may have several possible implementations, it may not be reasonable to have to mark all possible implementations with `[Differentiable]`, especially if certain implementations use hacks or workarounds that need additional consideration before they can be marked `[Differentiable]` + +In such cases, we provide the `[TreatAsDifferentiable]` decoration (AST node: `TreatAsDifferentiableAttribute`, IR: `OpTreatAsDifferentiableDecoration`), which instructs the auto-diff passes to construct an 'empty' function that returns a 0 (or 0-equivalent) for the derivative values. This allows the signature of a `[TreatAsDifferentiable]` function to match a `[Differentiable]` requirement without actually having to produce a derivative. + +## Custom derivative decorators +In many cases, it is desirable to manually specify the derivative code for a method rather than let the auto-diff pass synthesize it from the method body. This is usually desirable if: +1. The body of the method is too complex, and there is a simpler, mathematically equivalent way to compute the same value (often the case for intrinsics like `sin(x)`, `arccos(x)`, etc..) +2. The method involves global/shared memory accesses, and synthesized derivative code may cause race conditions or be very slow due to overuse of synchronization. For this reason Slang assumes global memory accesses are non-differentiable by default, and requires that the user (or the core module) define separate accessors with different derivative semantics. + +The Slang front-end provides two sets of decorators to facilitate this: +1. To reference a custom derivative function from a primal function: `[ForwardDerivative(fn)]` and `[BackwardDerivative(fn)]` (AST Nodes: `ForwardDerivativeAttribute`/`BackwardDerivativeAttribute`, IR: `OpForwardDervativeDecoration`/`OpBackwardDerivativeDecoration`), and +2. To reference a primal function from its custom derivative function: `[ForwardDerivativeOf(fn)]` and `[BackwardDerivativeOf(fn)]` (AST Nodes: `ForwardDerivativeAttributeOf`/`BackwardDerivativeAttributeOf`). These attributes are useful to provide custom derivatives for existing methods in a different file without having to edit/change that module. For instance, we use `diff.meta.slang` to provide derivatives for the core module functions in `hlsl.meta.slang`. When lowering to IR, these references are placed on the target (primal function). That way both sets of decorations are lowered on the primal function. + +These decorators also work on generically defined methods, as well as struct methods. Similar to how function calls work, these decorators also work on overloaded methods (and reuse the `ResolveInoke` infrastructure to perform resolution) + +### Checking custom derivative signatures +To ensure that the user-provided derivatives agree with the expected signature, as well as resolve the appropriate method when multiple overloads are available, we check the signature of the custom derivative function against the translated version of the primal function. This currently occurs in `checkDerivativeAttribute()`/`checkDerivativeOfAttribute()`. + +The checking process re-uses existing infrastructure from `ResolveInvoke`, by constructing a temporary invoke expr to call the user-provided derivative using a set of 'imaginary' arguments according to the translated type of the primal method. If `ResolveInvoke` is successful, the provided derivative signature is considered to be a match. This approach also automatically allows us to resolve overloaded methods, account for generic types and type coercion. + +## `[PrimalSubstitute(fn)]` and `[PrimalSubstituteOf(fn)]` +In some cases, we face the opposite problem that inspired custom derivatives. That is, we want the compiler to auto-synthesize the derivative from the function body, but there _is_ no function body to translate. +This frequently occurs with hardware intrinsic operations that are lowered into special op-codes that map to hardware units, such as texture sampling & interpolation operations. +However, these operations do have reference 'software' implementations which can be used to produce the derivative. + +To allow user code to use the fast hardware intrinsics for the primal pass, but use synthesized derivatives for the derivative pass, we provide decorators `[PrimalSubstitute(ref-fn)]` and `[PrimalSubstituteOf(orig-fn)]` (AST Node: `PrimalSubstituteAttribute`/`PrimalSubstituteOfAttribute`, IR: `OpPrimalSubstituteDecoration`), that can be used to provide a reference implementation for the auto-diff pass. + +Example: +```C +[PrimalSubstitute(sampleTexture_ref)] +float sampleTexture(TexHandle2D tex, float2 uv) +{ + // Hardware intrinsics +} + +float sampleTexture_ref(TexHandle2D tex, float2 uv) +{ + // Reference SW implementation. +} + +void sampleTexture_bwd(TexHandle2D tex, inout DifferentialPair dp_uv, float dOut) +{ + // Backward derivate code synthesized using the reference implementation. +} +``` + +The implementation of `[PrimalSubstitute(fn)]` is relatively straightforward. When the transcribers are asked to synthesize a derivative of a function, they check for a `OpPrimalSubstituteDecoration`, and swap the current function out for the substitute function before proceeding with derivative synthesis. diff --git a/lib/All/slang/share/doc/slang/design/autodiff/ir-overview.md b/lib/All/slang/share/doc/slang/design/autodiff/ir-overview.md new file mode 100644 index 0000000..dd5f44f --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/autodiff/ir-overview.md @@ -0,0 +1,1462 @@ +This documentation is intended for Slang contributors and is written from a compiler engineering point of view. For Slang users, see the user-guide at this link: [https://shader-slang.com/slang/user-guide/autodiff.html](https://shader-slang.com/slang/user-guide/autodiff.html) + +# Overview of Automatic Differentiation's IR Passes +In this document we will detail how Slang's auto-diff passes generate valid forward-mode and reverse-mode derivative functions. Refer to [Basics](./basics.md) for a review of the two derivative propagation methods and their mathematical connotations & [Types](./types.md) for a review of how types are handled under differentiation. + +## Auto-Diff Pass Invocation +Note that without an explicit auto-diff instruction (`fwd_diff(fn)` or `bwd_diff(fn)`) from the user present anywhere in the code, none of the auto-diff passes will do anything. + +Auto-diff processing operates on a function-by-function basis. Most of the logic is contained in `AutoDiffPass::processReferencedFunctions`. Here is a high-level workflow: +1. Scanning reachable insts in the module looking for `IRForwardDifferentiate` or `IRBackwardDifferentiate` operations. These instructions are added onto a work-list. The subject of a differentiate inst may be a plain function (`IRFunc`), a specialize inst (`IRSpecialize(a : IRGeneric, ...)`) in case of a generic method, or a lookup inst (`IRLookupWitness(a : IRWitnessTableType)`) when differentiating a method of an interface. + +2. Dispatch each differentiation request through the appropriate 'transcriber' class. A transcriber (implements `AutodiffTranscriberBase`) is responsible for accepting a differentiation request and resolving it by replacing it with a generated function or a call to an already existing function that computes its derivative. + +3. Once all currently available derivative insts have been dispatched, the follow-up work-list is checked for more transcription requests. This is a global list that all transcribers can add more follow-up work to. As an example, differentiating a function that calls another function will generate a follow-up task for this inner function, even though the latter never appears directly in a `IRForwardDifferentiate` or `IRBackwardDifferentiate` inst. +At this step, there are 2 other variants that can appear `IRBackwardDifferentiatePrimal` and `IRBackwardDifferentiatePropagate` (though these can't be invoked by the user directly). + +4. This process from (1.) is run in a loop. This is because we can have nested differentiation requests such as `IRForwardDifferentiate(IRBackwardDifferentiate(a : IRFuncType))`. The inner request is processed in the first pass, and the outer request gets processed in the next pass. + +## Auto-Diff Passes for `IRForwardDifferentiate` +For forward-mode derivatives, we only require a single pass implemented wholly in `ForwardDiffTranscriber`. This implements the linearization algorithm, which roughly follows this logic: + +1. Create a clone of the original function +2. Perform pre-autodiff transformations, the most + a. **Temp-Var-For-Mutable-Params** Using `IRVar` to load from + b. **Linkage-Removal**: This is simply so the cloned function can be eliminated by DCE after auto-diff is complete + c. **Force-Inline**: Inline all `__unsafeForceEarlyInline` & `[ForceInline]` functions _prior_ to auto-diff, so their contents can be included in the differentiation pass (even if they aren't actually marked as `[Differentiable]`) + +3. Create a new blank function for the fwd-mode func (usually named `s_fwd_`) with the function type derived by transforming the original function type (See [Types](./types.md) for more information). +4. Create new blocks into the new fwd-func for each block in the orig-func. +5. Go through instructions in each block and dispatch to the appropriate generator function to emit the derivative logic into the corresponding block in the fwd-func. Each generator method is responsible for cloning in the original instruction as well as emitting a corresponding derivative instruction. `mapPrimalInst` and `mapDifferentialInst` are used to keep track of prior results so that operands for new instructions can be looked up. + +The generator for each instruction computes the forward-mode derivative of each *instruction* using the Jacobian method that is detailed in [Basics#Jacobian-Method](./basics.md#jacobian-method-generate-forward--and-reverse-mode-derivatives-from-first-principles). Since forward-mode derivatives can be composed in the same order as the original instructions, our generation process goes through instructions in each block in the order that they appear, creating differential insts which act as operands for future insts. + +Here's an example of this in IR-form + +```Rust +OpModule +{ + %ftype = OpFuncType (%float) (%float) (%float) + %f = OpFunc : %ftype + { + %b = OpBlock + { + %a = OpParam : %float + %b = OpParam : %float + + %1 = OpAdd %a %b : %float + %2 = OpAdd %1 %1 : %float + + OpReturn %2 + } + } + + // Generated function type + %dpfloat = OpDifferentialPairType (%float) (%witness_that_float_is_idifferentiable) + %ftype_fwd = OpFuncType (%dpfloat) (%dpfloat) (%dpfloat) + + // Generated function + %f_fwd = OpFunc : %ftype_fwd + { + %b_fwd = OpBlock + { + %dpa = OpParam : %dpfloat // Convert params to differential pair types + %dpb = OpParam : %dpfloat // Convert params to differential pair types + + // Split block inputs into primals and differentials + %a = OpDifferentialPairGetPrimal %dpa : %float + %da = OpDifferentialPairGetDifferential %dpa : %float + + %b = OpDifferentialPairGetPrimal %dpb : %float + %db = OpDifferentialPairGetDifferential %dpb : %float + + // Clone the primal inst for %1 + %1_primal = OpAdd %a %b : %float + + // Generate the diff inst for %1 + // Here, we consider the 'mini-function' Add(a,b) = a + b, and use the Jacobian method + // to get the result that the fwd-mode derivative should be: + // DAdd((a, da), (b, db)) = da + db = Add(da, db) + // + %1_diff = OpAdd %da %db : %float + + // Do the same for the next inst (%2): clone in the primal + // by looking up primal versions of the operands. + // + %2_primal = OpAdd %1_primal %1_primal : %float + + // Then, generate the derivative inst by looking up the differential + // versions of the operands. + // + %2_diff = OpAdd %1_diff %1_diff : %float + + // Return both the primal and differential + %2_pair = OpDifferentialPairMakePair %2_primal %2_diff : %dpfloat + OpReturn %2_pair + } + } +} +``` + +**Multiple Differential Insts:** +In the above example, the derivative of each inst was a single inst. This is not always the case. +For instance, `OpMul %a %b` translates to **three** insts: +```Rust +%1 = OpMul %a_diff %b_primal : %float +%2 = OpMul %a_primal %b_diff : %float +%3 = OpAdd %1 %2 : %float +``` + +**Combined Primal & Differential Insts:** +In some cases, there is not need to clone in the primal inst since both the primal and differential can be computed in a single inst. An example is `IRCall`, whose deriavative only needs a single call (though it needs plenty of insts to pair and unpair arguments) +```Rust +// Original inst +%1 = OpCall %func %a %b : %float + +// +// Upon differentiation: + +// Pack args into pairs +%a_pair = OpDifferentialPairMakePair %a_primal %a_diff : %dpfloat +%b_pair = OpDifferentialPairMakePair %b_primal %b_diff : %dpfloat + +// Call into fwd-mode deriv which computes *both* primal and differential +// values. +// +%func_fwd = OpForwardDifferentiate %func : %functype_fwd +%1_pair = OpCall %func_fwd %a_pair %b_pair : %float + +// Split into primal and differential so they can be used for future insts. +%1_primal = OpDifferentialPairGetPrimal %1_pair : %float +%1_diff = OpDifferentialPairGetDifferential %1_pair : %float + +``` + + +### Phi Arguments +Block arguments are handled the same way as function arguments (which in the Slang IR, are also simply block arguments of the first block), and are converted into pair type arguments, with `OpDifferentialPairGetPrimal` and `OpDifferentialPairGetDifferential` insts automatically added to extract the primal and differential parts of each argument. + + +## Auto-Diff Passes for `IRBackwardDifferentiate` + +For reverse-mode derivatives, we need several passes that also includes differentiating the forward-mode derivative. Most of this logic is contained in `BackwardDiffTranscriberBase::transcribeFuncImpl`. These passes are inspired by the paper ["You Only Linearize Once: Tangents Transpose to Gradients"](https://arxiv.org/abs/2204.10923), which describes this approach in a functional language setting. These passes extend these ideas to work for a general-purpose imperative language structure. + +### 1. Preparation +The reverse-mode derivative generation involves a lot of large scale control-flow manipulation, including a CFG reversal step that aims to construct a method that flows from the end of the function to the beginning in order to compose reverse-mode derivatives. +To avoid having to deal with too many corner cases (and the maintainability issues that come with it), we bring the function to a 'normal form' before running our differentiation steps. This greatly simplifies the logic of the future passes. + +Another high-level goal of these transformations is to bring the control-flow graph to a **reversible** form. That is, we can represent the reverse of control-flow graph using existing Slang constructs (`IRIfElse`, `IRUnconditionalBranch`, `IRLoop` and `IRSwitch`). This is not necessarily true of any valid Slang IR, so we perform additional transformations. + +Note: These transformations are always applied onto a temporary clone of the original function. The original function is never touched so as to not affect its use in non-autodiff contexts. + +Specifically we: +1. Bring the function into **single-return form**: If there are multiple blocks with return statements (i.e. multiple exit points) in a function, we eliminate this by wrapping the complete function body in a trivial loop (i.e. a single-iteration loop) and replacing existing return statements with breaks (or multi-level breaks) into its break block, which serves as the unique exit point for the function. This pass is currently contained in `convertFuncToSingleReturnForm()` + +2. Eliminate **continue** statements: Loop continue statements introduce a reversibility problem. Since the forward loop can have multiple exit point, the reverse loop needs to have multiple entry points. Slang's loops do not support this. So, we eliminate these statements wrapping the body of the loop in another trivial loop (i.e. single-iteration loop) and turning the **continue** statements into **break** statements. This also involves writing **break** statements in the original loop into **multi-level** breaks. + + Here is an example: + ```C + // Original loop + for (uint i = 0; i < N; i++) + { + if (i > 5) + continue; + + if (i > 9) + break; + + x = x + i; + } + + // After continue-elimination + outer_for: + for (uint i = 0; i < N; i++) + { + inner_for: + for (;;) + { + if (i > 5) + break; + + if (i > 9) + break outer_for; // multi-level break + + x = x + i; + + break; + } + } + ``` + +3. Eliminate **multi-level breaks**: Slang supports breaking out to an outer loop. Unfortunately, this operation is hard to reverse since Slang (and shading languages in general) do not support arbitrary `goto` statements. We eliminate multi-level breaks by assigning each nested loop a nesting index (a constant `uint` denoting the nesting level). All break statements are rewritten to break out to the immediate next level (i.e. a standard break) with a index parameter denoting the intended break level. This parameter is checked at each level and if the break index does not match the level index, we break again to the immediate upper level. This pass is currently contained in `eliminateMultiLevelBreakForFunc` + + Continuing the above example, here is the code after multi-level break elimination. + ```C + // After multi-level-break elimination + uint level = -1; + for (uint i = 0; i < N; i++) + { + for (;;) + { + if (i > 5) + { + level = 1; + break; + } + + if (i > 9) + { + level = 0; + break; + } + + x = x + i; + + level = 1; + break; + } + + if (level != 1) // Level check immediately after breaking out of each loop. + break; + } + ``` + +4. Eliminate **break** statements (enclosed in `normalizeCFG()`): Break statements also pose the same problem as continue statements (i.e. multiple exit points require the reverse loop to have multiple entry points, and Slang does not have a primitive for this). We eliminate break statements by introducing a boolean break flag which is set to `false` to indicate a break instead of using the break statement. Each *region* is enclosed in a if-else statement that checks the break flag and skips to the end if necessary. + + Break elimination proceeds with the following steps; + + Here is the above example code after break elimination. + ```C + // After break elimination + + uint level = -1; + bool bflag_0 = true; // for outer loop (true => keep-going, false => break) + + for (uint i = 0; (i < N) && bflag_0; i++) // Insert flag into the loop condition (&& with the current condition) + { + bool bflag_1 = true; // for inner loop (true => keep-going, false => break) + + for (;bflag_1;) // Insert flag into the loop condition + { + if (i > 5) + { + level = 1; + bflag_1 = false; // break + } + + // Region after any break statement is enclosed in a + // if-else check. + // + if (bflag_1) + { + if (i > 9) + { + level = 0; + bflag_1 = false; // break + } + + // Another if-else enclosure, this time for the second + // break. + // + if (bflag) + { + x = x + i; + level = 1; + } + + bflag_1 = false; + } + } + + if (level != 1) + { + bflag_0 = false; + } + } + ``` + + **Extra evaluation of the condition block:** The CFG normalization passes always attempt to preserve the equivalence of the original function while manipulating the control-flow constructs (i.e. ensure that the transformed code always computes the same thing). However, there is one corner-case exception: after break-elimination, the loop condition code can be evaluated 1 additional time, since we don't directly break out of the loop, but go through an extra loop condition check. This becomes important during the checkpointing step, when arrays are allocated to hold loop variables. The array bounds must account for an additional loop iteration to avoid correctness problems. + + +### 2. Linearization with Inst-Tagging +This is the same as generating the forward-derivative function, and is in-fact handled in the same way, by invoking `ForwardDiffTranscriber`. The **inst-tagging** part of this pass is not necessary for forward-mode auto-diff (simply discarded after the auto-diff pass), but is essential for reverse-mode. + +**Inst-Tagging:** This pass also **tags** every instruction and block with either `IRPrimalInstDecoration`, `IRDifferentialInstDecoration` or `IRMixedDifferentialnstDecoration`, depending on whether an instruction contains/computes/reads/writes a primal value, a differential value or both. + +This assignment is according to the following rules: +1. The result of `.getDifferential()` from an inst of `IRDifferentialPairType` is a *differential* inst and `.getPrimal()` is a primal inst **NOTE:** This does not apply to `IRDifferentialPairUserCodeType`, all of whose operations yield a *primal* inst. +2. Further, any inst which contains a differential inst as an operand **AND** whose output value may be affected by this operand is a differential inst (e.g. if `isDifferentialInst(a) = true` then `isDifferentialInst( IRMul(a, b) ) = true`) +3. If an inst contains multiple outputs, *some* of which are differential and the others are primal, then these are *mixed-differential* insts. E.g. (a value of `IRDifferentialPairType` contains both a primal and differential value, and similarly a call of the form `IRCall(IRForwardDifferentiate(inner_fn))(...)` results in a mixed differential type since the primal part is not affect by differential inputs) +4. All other insts are *primal* by default. +5. Blocks are marked differential or primal if they contain **ONLY** differential or primal insts (respectively). Otherwise they are marked mixed-differential. The vast majority of blocks are mixed-differential. + +Correct tag information is critical for the next steps to correctly transform the forward-mode derivative into the reverse-mode derivative function. + +Here's the same forward-mode example, but with insts tagged accordingly +```Rust +OpModule +{ + // Generated function type + ... + + // Generated function + ... + [OpMixedDifferentiaInstDecoration] + %b_fwd = OpBlock + { + // Block params are mixed differentials since they carry both + // primal and differential values + // + [OpMixedDifferentialInstDecoration] + %dpa = OpParam : %dpfloat + [OpMixedDifferentialInstDecoration] + %dpb = OpParam : %dpfloat + + [OpPrimalInstDecoration] + %a = OpDifferentialPairGetPrimal %dpa : %float + + [OpDifferentialInstDecoration] + %da = OpDifferentialPairGetDifferential %dpa : %float + + [OpPrimalInstDecoration] + %b = OpDifferentialPairGetPrimal %dpb : %float + + [OpDifferentialInstDecoration] + %db = OpDifferentialPairGetDifferential %dpb : %float + + [OpPrimalInstDecoration] + %1_primal = OpAdd %a %b : %float + + [OpDifferentialInstDecoration] + %1_diff = OpAdd %da %db : %float + + [OpPrimalInstDecoration] + %2_primal = OpAdd %1_primal %1_primal : %float + + [OpDifferentialInstDecoration] + %2_diff = OpAdd %1_diff %1_diff : %float + + // Return both the primal and differential + [OpMixedDifferentialInstDecoration] + %2_pair = OpDifferentialPairMakePair %2_primal %2_diff : %dpfloat + + [OpDifferentialInstDecoration] + OpReturn %2_pair + } + ... +} +``` + +### 3. Unzipping +Implemented by `DiffUnzipPass`, this pass is responsible for **separating** primal instructions from differential instructions (as denoted by their decorations), by creating a full set of duplicate blocks that start **after** the last block, i.e. return block (the return statement is removed). + +This separation is possible because the computation of a differential inst may include primal operands but a primal inst can never use a differential operand. + +The unzipping pass uses the decorations from the linearization step to figure out which instructions need to be moved. + +The separation process uses the following high-level logic: +1. Create two clones of all the blocks in the provided function (one for primal insts, one for differential insts), and hold a mapping between each original (mixed) block to each primal and differential block. The return statement of the current final block is **removed**. +2. Process each instruction of each block: instructions marked as **primal** are moved to the corresponding **primal block**, instructions marked **differential** are moved to the corresponding **differential block**. +3. Instructions marked **mixed** need op-specific handling, and so are dispatched to the appropriate splitting function. For instance, block parameters that are holding differential-pair values are split into parameters for holding primal and differential values (the exception is function parameters, which are not affected). Similarly, `IRVar`s, `IRTerminatorInst`s (control-flow) and `IRCall`s are all split into multiple insts. +4. Except for `IRReturn`, all other control-flow insts are effectively duplicated so that the control-flow between the primal blocks and differential blocks both follow the original blocks' control-flow. The main difference is that PHI arguments are split (primal blocks carry primal values in their PHI arguments, and differential blocks carry diff values) between the two. Note that condition values (i.e. booleans) are used by both the primal and differential control-flow insts. However, since booleans are always primal values, they are always defined in the primal blocks. + + +**Block-Tagging:** Blocks are now tagged primal or differential depending on whether they are holding primal or differential insts. This is important for the next step (transposition) to figure out which blocks need to be transposed. + +**Out-of-Scope Accesses:** After unzipping, the resulting IR is often **not valid**. If the control-flow is straight line (i.e. no branching or loops), the resulting IR is valid. However, if there is control-flow, then instructions can use operands whose definition does not dominate the use. This invalid IR is currently allowed to persist until the end of the auto-diff passes, when the checkpointing step occurs (i.e. Running IR validation will fail in between these steps) + + +Here is an example of unzipped code: + +```Rust +OpModule +{ + // Generated function type + ... + + // Unzipped code + ... + // The first block of a function is still mixed differential, and exclusively holds + // function parameter definitions (no other instructions) + // + [OpMixedDifferentialDecoration] + { + [OpMixedDifferentialDecoration] + %dpa = OpParam : %dpfloat + [OpMixedDifferentialDecoration] + %dpb = OpParam : %dpfloat + } + + // Primal version of b containing only primal instructions + [OpPrimalInstDecoration] + %b_primal = OpBlock + { + [OpPrimalInstDecoration] + %a_primal = OpDifferentialPairGetPrimal %dpa : %dpfloat + [OpPrimalInstDecoration] + %b_primal = OpDifferentialPairGetPrimal %dpa : %dpfloat + + [OpPrimalInstDecoration] + %1_primal = OpAdd %a_primal %b_primal : %float + + [OpPrimalInstDecoration] + %2_primal = OpAdd %1_primal %1_primal : %float + + [OpBackwardDerivativePrimalReturnDecoration %2_primal] + OpUnconditionalBranch %b_diff + } + + // Differential version of b containing only differential instructions + // with some exceptions. + // + [OpDifferentialInstDecoration] + %b_diff = OpBlock + { + [OpDifferentialInstDecoration] + %a_diff = OpDifferentialPairGetDifferential %dpa : %dpfloat + [OpDifferentialInstDecoration] + %b_diff = OpDifferentialPairGetDifferential %dpa : %dpfloat + + [OpDifferentialInstDecoration] + %1_diff = OpAdd %a_diff %b_diff : %float + + [OpDifferentialInstDecoration] + %2_diff = OpAdd %1_diff %1_diff : %float + + // Return both the primal and differential + [OpMixedDifferentialInstDecoration] + %2_pair = OpDifferentialPairMakePair %2_primal %2_diff : %dpfloat + + [OpDifferentialInstDecoration] + OpReturn %2_pair + } + + ... +} +``` + +### 4. Transposition + +The next step involves converting each differential instruction into its transpose. Effectively, we are re-writing each forward-mode derivative into its reverse-mode equivalent. + +Recall from auto-diff [basics](./basics.md), that both the forward and reverse mode derivatives can be derived from the Jacobian matrix of any operation. The main difference is whether we multiply the derivatives of the inputs with the Jacobian or multiply the Jacobian with the derivatives w.r.t the outputs. These two operations are the transpose of each other, in that the reverse-mode derivative can be thought of as multiplying with the transpose of the Jacobian. + +We perform this transposition on a per-instruction level. + +Here is an example of a transposition of a multiplication operation: +```Rust +[OpPrimalInstDecoration] +%b = OpLoad %var_b // %b is a primal value + +[OpDifferentialInstDecoration] +%da = OpLoad %var_da // %da is a differential value + +// The operation we want to transpose +[OpDifferentialInstDecoration] +%1d = OpMul %da %b : %float + +[OpDifferentialInstDecoration] +OpStore %1d %var_result +``` + +This multiplication can be represented as a tiny matrix multiplication between a singleton vector `[%da]` and singleton matrix `[%b]`. +It's transpose will be the multiplication of the transpose of that matrix (which is the value itself `[%b]`) with a derivative w.r.t its output `%1d`, i.e. it becomes `%da = OpMul %1d %b`. Note that we now have to provide `%1d` as an **input**, and receive `da` was an output. + +The resulting code is then: +```Rust +[OpPrimalInstDecoration] +%b = OpLoad %var_b : %float // primal values are unaffected (at this stage, they are in primal blocks) + +// Reverse-mode code: (_rev) appended to all variables & insts to keep them distinct from the fwd-mode code. +[OpDifferentialInstDecoration] +%1d_rev = OpLoad %var_result_rev : %float + +// The operation we want to transpose +[OpDifferentialInstDecoration] +%da_rev = OpMul %1d_rev %b : %float + +[OpDifferentialInstDecoration] +OpStore %da_rev %var_da_rev +``` + +Notice that the three differential instructions are effectively run backwards **and** transposed. Loads become stores, +the `OpMul` is transposed into another `OpMul`, and stores become loads. This backwards transposition is because the differential outputs become differential inputs, and thus, we need to process the future instructions first so that the new operands are defined before bring used for the new instruction. + +This reverse order of operations also applies to control-flow. The rule of thumb is: if the forward-mode pass takes a particular path through the code, for a given set of primal values, the reverse-mode must "re-trace" the same path through the code, but in reverse by starting at the end. + +We synthesize a CFG that satisfies this property through the following steps: +1. Clone the provided unzipped forward-mode function (and all blocks + instructions) to serve as the reverse-mode function. +2. Remove all **differential** blocks and create a set of corresponding reverse-mode blocks for each **differential** block removed (**primal** blocks are simply left alone), while holding a map between corresponding blocks. Initially, they are empty. +3. Using the provided unzipped forward-mode function as a reference, process each differential block by walking each instruction from the _last_ (terminator) inst, and dispatching to the appropriate op-specific `transposeXYZ()` method to emit the appropriate transposed instructions into the corresponding reverse-mode block. + + There are several concerns that must be taken care of: + 1. **Multiple Derivaive Outputs:** Unlike forward-mode auto-diff, where an inst producing a single value, would only need a single derivative (corresponding to that value), reverse-mode auto-diff can produce multiple derivatives from an inst. For instance `%dc = IRAdd(%da, %db)` produces two derivatives: `%da_rev = %dc_rev` and `%db_rev = %dc_rev`. Thus, the `transposeXYZ()` implementation for any instruction can return a set of derivative insts for each relevant input differential value. + + 2. **Insts Used in Multiple Places (Derivative Accumulation):** If an inst is used in multiple places, and receives a reverse-mode derivative from several of those places, these results need to be **added up** to get the correct derivative. + + Consider this forward-mode example + + ```Rust + [OpDifferentialInstDecoration] + %db = OpAdd %da, %da : %float + + [OpDifferentialInstDecoration] + %dc = OpAdd %db, %da : %float + ``` + + It's reverse-mode derivative will look like this: + + ```Rust + %db_rev = %dc_rev // %db only has one differential since it only consumed in one place. + + // reverse-mode differential for %da from trnaposing the first instruction + [OpDifferentialInstDecoration] + %da_rev_1 = OpAdd %db_rev, %db_rev : %float + + // reverse-mode differential for %da from transposing the second instruction + [OpDifferentialInstDecoration] + %da_rev_2 = %dc_rev + + // add them together to get the final derivative for %da + [OpDifferentialInstDecoration] + %da_rev = OpAdd %da_rev_1 %da_rev_2 : %float + ``` + + Derivative accumulation is achieved through two ways: + + **Within** a block, we keep a list all the reverse derivative insts for each inst and only **materialize** the total derivative when it is required as an operand. This is the most efficient way to do this, because we can apply certain optimizations for composite types (derivative of an array element, vector element, struct field, etc..). + + **Across** blocks, we use an accumulator variable that is inserted into a top-level block in the function, and add to this variable whenever a transposition operation generates a new inst. This can sometimes produce sub-optimal code for aggregate/large data types, but at the moment, the accumulator method is necessary because insts can receive derivatives from conditionally executed blocks. + + While this example uses `OpAdd` to demonstrate accumulation, in practice, we use the derivative type system (See [Types](./types.md) for more) to look up the derivative addition function (`dadd`) to add two values of an arbitrary differential type. In practice, the `OpAdd` is replaced by `OpCall %float_dadd %da_rev1 %da_rev_2`. Similarly, for accumulator variables, we must initialize them to zero for the accumulation to work correctly, and we lookup the `dzero` interface method to initialize it in a type-specific way. + + 3. **Deferred Materialization for Derivatives of Composite Types:** + Non-primitive types, such as vectors, arrays, structs, etc. whose elements are used in several places in the forward-mode code, can result in sub-optimal reverse-mode code. Here is an example (in Slang source-style): + ```C + float f_fwd(DifferentialPair input) + { + float3 dinput = input.getDifferential(); + float a = dinput.x + dinput.y; + float b = a + dinput.z; + + return b; + } + + // Transposed code (naively, without deferred materialization) + void f_rev(inout DifferentialPair input, float d_output) + { + // transpose of (return b;) + float db_rev = d_output; + + // transpose of (float b = a + dinput.z) + float da_rev = db_rev; + float3 dinput_rev_1 = float3(0.f, 0.f, da_rev); + + // transpose of (float a = dinput.x + dinput.y) + float3 dinput_rev_2 = float3(0.f, da_rev, 0.f); + float3 dinput_rev_3 = float3(da_rev, 0.f, 0.f); + + // Accumulate [dinput_rev_1, dinput_rev_2, dinput_rev_3] + float3 dinput = dinput_rev_1 + dinput_rev_2 + dinput_rev_3 + + input = DifferentialPair( + input.getPrimal(), + dinput); + } + ``` + + Note that, this approach to inst-by-inst transposition can use a lot more stack space than is necessary (`dinput_rev_1`, `dinput_rev_2` and `dinput_rev_3` all only have a single non-0 entry). This is a known complexity issue with naive inst-by-inst transposition: hypothetically, an size-$N$ vector/array would end up allocating $O(N^2)$ memory even if only $N$ elements are non-0. + In our Slang implementation, we circumvent this (to an extent) by deferring materialization. Rather than create each component `dinput_rev_i` as soon as we see an inst use, we hold the derivative with a special flavor value for lookups (say `Swizzle` or `GetElement`). When the total value `dinput_rev` is necessary, we process components of each flavor type at once and create a single derivative from all the components. + + Here is the same example, with deferred materialization: + ```C + // Transposed code (naively, without deferred materialization) + void f_rev(inout DifferentialPair input, float d_output) + { + // transpose of (return b;) + float db_rev = d_output; + + // transpose of (float b = a + dinput.z), hold {flavor=Swizzle, component=.z, derivInst=db_rev} in list. + float da_rev = db_rev; + + // transpose of (float a = dinput.x + dinput.y), + // hold {flavor=Swizzle, component=.x, derivInst=da_rev} and {flavor=Swizzle, component=.y, derivInst=da_rev} in list. + + // Materialize when required (for constructing return pair) + float3 dinput = float3(db_rev, da_rev, da_rev); + + input = DifferentialPair( + input.getPrimal(), + dinput); + } + ``` + + Note that this only really works for accumulation *within* a single block/control-flow region. For across regions, we still have to materialize when we exit a region, so this memory problem can still manifest for control-flow heavy functions, where each region must allocate enough space for its contribution to the full derivative, even if only a small subset is non-0. + + + +```C +float a[10] = /*...*/; +for (int i = 0; i < 10; i++) +{ + a[i] = f(a[i]); +} +``` + +```C + +// Entry block +%t = OpBlock +{ + IRLoop %c %br %c 0 +} + +// Condition +%c = OpBlock +{ + %i = OpParam : %float + %a = OpParam : %Array(%float, 10) + + %2 = OpLesser(%i, 10) : %bool + + %OpIfElse(%2, %b, %br, %br) +} + +// Loop body. +%b = OpBlock +{ + %a_i = OpGetElement(%a, %i) : %float + %f_a_i = OpCall(f, %a_i) : %float + + %a_next = OpUpdateElement(%a, %i, %f_a_i) : %Array(%float, 10) + + %i_next = OpAdd(%i, 1) + + OpUnconditionalBranch(%c, %i_next, %a_next) +} + +// Break block +%br = OpBlock +{ + //... +} +``` + +After AD passes, this results in the following code: +```C + +//// Primal context pass. + +// Entry block +%t_rev = OpBlock +{ + // Context storage for all loop phi variables (n_iters + 1) + %ctx_a = IRVar : %array(%array(%float, 10), 11) // Catastrophically large amount of storage. + %ctx_i = IRVar : %array(%float, 11) + + OpLoop %c %br %c 0 +} + +// Condition +%c_rev = OpBlock +{ + %i = OpParam : %float + %a = OpParam : %array(%float, 10) + + // Context store operations. + %ctx_i_ptr = OpGetElementPtr(%ctx_i, %i) : %ptr(%int) + OpStore(%ctx_i_ptr, %i) + %ctx_a_ptr = OpGetElementPtr(%ctx_a, %i) : %ptr(%array(%float, 10)) + OpStore(%ctx_a_ptr, %a) + + %2 = OpLesser(%i, 10) : %bool + + %OpIfElse(%2, %b, %br, %br) +} + +// Loop body. +%b = OpBlock +{ /*...*/ } + +// Break block +%br = OpBlock +{ /*...*/ } + +//// Backprop pass + +// Entry block +%t_rev = OpBlock +{ + // Count down from the end + OpLoop %c_rev %br_rev %c_rev 9 + + // Variable to hold the derivative of %a + %var_da_rev = OpVar : %ptr(%array(%float, 10)) +} + +// Condition +%c_rev = OpBlock +{ + // rev-mode loop counter (runs backwards from limit to 0) + %dc = OpParam : %int + + %2 = OpLesser(%i, 10) : %bool + + OpIfElse %2 %b %br %br +} + +// Loop body. +%b_rev = OpBlock +{ + // Context load operations. + %ctx_i_ptr = OpGetElementPtr(%ctx_i, %dc) : %ptr(%int) + %i_saved = OpLoad(%ctx_i_ptr) : %int + + %ctx_a_ptr = OpGetElementPtr(%ctx_a, %dc) : %ptr(%array(%float, 10)) + %a_saved = OpLoad(%ctx_a_ptr) : %array(%float, 10) + + %a_i = OpGetElement(%a_saved, %i_saved) : %float + %a_pair_i = OpMakeDifferentialPair(%a_i, 0) : %diff_pair(%float) + + %da_rev_ptr = OpGetElementPtr(%var_da_rev, %i_saved) : %ptr(%float) + %df_output = OpLoad(%da_rev_ptr) : %float + + // Call rev-mode of f to propagate derivative of output of f to input of f. (Assume f has no context requirement) + %var_a_pair_i = OpVar : %ptr(%diff_pair(%float)) + OpStore(%var_a_pair_i, %a_pair_i) + OpCall(f_rev, %a_pair_i, %df_output) : %float + + // Load derivative for a_i + %a_pair_i_loaded = OpLoad(%var_a_pair_i, %a_pair_i) + %da_rev_i = OpDifferentialPairGetDifferential(%a_pair_i_loaded) : %float + + // Create derivative array for backpropagation (this happens during gradient materialization) + %da_rev_local_var = OpVar : %ptr(%array(%float, 10)) + %da_rev_init_zero = OpMakeArray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) : %array(%float, 10) + OpStore(%da_rev_local_var, %da_rev_init_zero) + + %da_rev_var_i = OpGetElementPtr(%da_rev_local_var, %dc) : %ptr(%float) + %curr_dval = OpLoad(%da_rev_var_i) : %float + %acc_dval = OpAdd(%curr_dval, %da_rev_i) : %float + OpStore(%da_rev_var_i, %acc_dval) + + // Add derivative array to the global var. + %curr_dval_a = OpLoad(%var_da_rev) : %array(%float, 10) + %new_dval_a = OpLoad(%da_rev_local_var) : %array(%float, 10) + %acc_dval_a = OpCall('array_dadd', %curr_dval_a, %new_dval_a) : %array(%float, 10) + OpStore(%var_da_rev, %acc_dval_a) + + %dc_next = OpAdd(%dc, -1) + + OpUnconditionalBranch(%c_rev, %dc_next) +} + +// Break block +%br_rev = OpBlock +{ /*...*/ } +``` + +4. Construct the reverse control-flow (`reveseCFGRegion()`) by going through the reference forward-mode blocks, and cloning the control-flow onto the reverse-mode blocks, but in reverse. This is achieved by running `reverseCFGRegion()` recursively on each sub-region, where a *region* is defined as a set of blocks with a single entry block and a single exit block. This definition of a region only works because we normalized the CFG into this form. + + The reversal logic follows these general rules: + 1. **Unconditional Branch**: For an unconditional branch from `A->B` we simply have to map the reverse version of B with that of A. i.e. `rev[B] -> rev[A]` + 2. **If-Else**: For an if-else of the form `A->[true = T->...->T_last->M, false = F->...->F_last->M]`, we construct `rev[M]->[true = rev[T_last]->...->rev[T_last]->rev[A], false = rev[F_last]->...->rev[F]->rev[A]]`. That is, we reverse each sub-region, and start from the merge block and end at the split block. + Note that we need to identify `T_last` and `F_last` i.e. the last two blocks in the true and false regions. We make the last block in the region an additional return value of `reverseCFGRegion()`, so that when reversing the true and false sub-regions, we also get the relevant last block as an additional output. Also note that additional empty blocks may be inserted to carry derivatives of the phi arguments, but this does not alter the control-flow. + 3. **Switch-case**: Proceeds in exactly the same way as `if-else` reversal, but with multiple cases instead of just 2. + 4. **Loop**: After normalization, all (non-trivial) loops are of the form: `A->C->[true = T->...->T_last->C, false=B->...->M]`. We reverse this loop into `rev[M]->...rev[B]->rev[C]->[true=rev[T_last]->...->rev[T]->rev[C], false=rev[A]]`. The actual reversal logic also handles some corner cases by inserting additional blank blocks to avoid situations where regions may share the same merge block. + + Finally, we process the first and last blocks (entry and return blocks) by inserting a void return (reverse-mode derivative functions are always of void result type) + +At this stage, the reverse-mode generation is almost complete. The control-flow and the derivative logic is present, but we still have to resolve out-of-scope accesses from the new differential blocks into the primal block. + +### 5. Checkpointing/Recomputation (also called 'primal-hoisting') +This step legalizes the out-of-scope accesses of primal insts from within differential blocks. This is to prepare us for the next step (i.e. [extraction](#6-extraction)) that splits the function into two by moving the primal blocks into a separate primal-context-generator function, and the differential blocks into the backward-propagation function. + +Before we can perform this extraction, we must find any primal values being used in differential blocks and handle them in one of two ways: +**Store** (put the values in a static struct) or **Recompute** (clone the necessary instructions to recompute when necessary). We first _classify_ all necessary instructions into one of the two buckets before processing each use accordingly. + +1. **Classify uses into each set:** Note that rather than proceeding on an inst-by-inst basis, we classify **uses** of insts. The same inst can be used in several places, and we may decide to store one use and recompute another (in some cases, this could be the optimal result). +The classification process uses a work-list approach that roughly looks like the following: + 1. Add all uses of **primal** insts in an inst within a **differential** block to the work list. This is our initial set of uses that require classification. + 2. Query the active policy object (which for now is hardcoded) to obtain the classification based on heuristics & user decorations (Specifically `[PreferRecompute]` and `[PreferCheckpoint]` decorations influence the classification policy) + 3. For uses that should be **recomputed**, we have to now make the same decision one their **operands**, in order to make them available for the recomputation insts. Thus, their operands are added to the work list. + 4. For uses that should be **stored**, there is no need to consider their operands, since the computed value will be explicitly stored and loaded later. + 5. Once the worklist is empty, go over all the **uses** and their classifications, and convert them into a list of **insts** that should be stored or recomputed. Note that if an inst has uses with both classifications, then it can appear in both lists. + +2. **Process 'Store' (i.e. checkpoint) insts:** Store them into a single variable (of a struct type that is synthesized as necessary), and then loaded from in the differential blocks. This allows us to simply turn this variable into an output parameter from the context function and an input parameter for the backprop function. +When storing values this way, we must consider that instructions within loops can have different values each iteration. Thus, we must use an array to store each value, and this array's size must be statically known since we wish to synthesize a static struct type to hold all the stored values. Thus, we enforce the requirement of a `[MaxIters(N)]` decoration and attempt to infer a loop iteration limit if one is not provided. + + Here's an example of a case where we decide to checkpoint _all_ relevant uses: + + ```C + // Example function without loops post-transposition step (BEFORE hoisting) + void f_rev(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + p = t2 * t2 + x; + } + + // + // Reversed differential blocks start here (will be extracted into a separate function in Step 6: Extraction) + // + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = t2 * dp_rev; // access of a primal value 't2' from a differential block. + dx_rev += dp_rev; + dp_rev = 0.f; // dp_rev's value gets reset to 0 after use. + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = t1 * dp_rev; // access of a primal value 't1' from a differential block. + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + + dpx = DifferentialPair(x, dx_rev); + } + + // The same function after the primal hoisting's checkpointing step. In this example, we + // assume all relevant uses are being checkpointed. + // + void f_rev_hoisted(DifferentialPair dpx, float d_out) + { + // Insert vars for checkpointed insts at the top-level + float t1_storage; + float t2_storage; + + // + // Primal blocks + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + t1_storage = t1; // Cache values immediately after they are created. + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + t2_storage = t2; // Cache values immediately after they are created. + p = t2 * t2 + x; + } + + // + // Reversed differential blocks + // + + float x = dpx.getPrimal(); + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = t2_storage * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = t1_storage * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + + dpx = DifferentialPair(x, dx_rev); + } + ``` + Another example with a function `g` that does contain loops: + + ```C + // Example function with a loop, post-transposition step (BEFORE hoisting) + void g_rev(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = 0; + + for (uint i = 0; i < 10; i++) + { + p = x * p; + } + + // + // Reversed differential blocks + // + + float dx_rev = 0.f; + float dp_rev = d_out; + for (uint i = 9; i > 0; i--) + { + dx_rev += p * dp_rev; // primal value 'p' accessed from differential blocks + dp_rev = x * dp_rev; + } + + return DifferentialPair(x, dx_rev); + } + + // After hoisting, note that we checkpoint 'p' in this case by using an array. + void g_rev_hoisted(DifferentialPair dpx, float d_out) + { + // Insert array to hold states of 'p' + float p_storage[11]; + + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = 0; + + // Insert storage for all states of p, including the initial value upon loop entry + p_storage[0] = p; + for (uint i = 0; i < 10; i++) + { + p = x * p; + // Use the loop induction variable 'i' to figure out which index to store p in. + p_storage[i+1] = p; + } + + // + // Reversed differential blocks + // + + float dx_rev = 0.f; + float dp_rev = d_out; + for (uint i = 9; i >= 0; i--) + { + // Load appropriate value of p from storage + float p = p_storage[i]; + dx_rev += p * dp_rev; + dp_rev = x * dp_rev; + } + + return DifferentialPair(x, dx_rev); + } + ``` + + **Indexed Region Processing:** In order to be able to allocate the right array and use the right indices, we need information about which blocks are part of which loop (and loops can be nested, so blocks can be part of multiple loops). To do this, we run a pre-processing step that maps all blocks to all relevant loop regions, the corresponding index variables and the inferred iteration limits (maximum times a loop can run). Note that if an instruction appears in a nested block, we create a multi-dimensional array and use multiple indices. + + **Loop State Variables:** Certain variables cannot be classified as recompute. Major examples are loop state variables which are defined as variables that are read from and written to within the loop. In practice, they appear as phi-variables on the first loop block after SSA simplification. Their uses _must_ be classified as 'store', because recomputing them requires duplicating the primal loop within the differential loop. This is because the differential loop runs backwards so the state of a primal variable at loop index $N$ cannot be recomputed when the loop is running backwards ($N+1 \to N \to N-1$), and involves running the primal loop up to $N$ times within the current iteration of the differential loop. In terms of complexity, this turns an $O(N)$ loop into an $O(N^2)$ loop, and so we disallow this. + It is possible that the resulting $O(N^2)$ loop may end up being faster in practice due to reduced memory requirements, but we currently lack the infrastructure to robustly allow such loop duplication while keeping the user informed of the potentially drastic complexity issues. + +3. **Process 'Recompute' insts:** Insert a copy of the primal instruction into a corresponding 'recomputation' block that is inserted into the differential control-flow so that it dominates the use-site. + + **Insertion of Recompute Blocks:** In order to accommodate recomputation, we first preprocess the function, by going through each **breakable (i.e. loop) region** in the differential blocks, looking up the corresponding **primal region** and cloning all the primal blocks into the beginning of the differential region. Note that this cloning process does not actually clone the instructions within each block, only the control-flow (i.e. terminator) insts. This way, there is a 1:1 mapping between the primal blocks and the newly created **recompute blocks**, This way, if we decide to 'recompute' an instruction, we can simply clone it into the corresponding recompute block, and we have a guarantee that the definition and use-site are within the same loop scope, and that the definition comes before the use. + + **Legalizing Accesses from Branches:** Our per-loop-region recompute blocks ensure that the recomputed inst is always within the same region as its uses, but it can still be out-of-scope if it is defined within a branch (i.e. if-else). We therefore still run a light-weight hoisting pass that detects these uses, inserts an `IRVar` at the immediate dominator of the def and use, and inserts loads and stores accordingly. Since they occur within the same loop region, there is no need to worry about arrays/indices (unlike the 'store' case). + + **Marking Recompute Blocks:** These blocks are marked with `OpRecomputeBlockDecoration` to identify them as containing primal instructions, even though they are within differential regions. This helps us remove any unused blocks if none of the instructions end up being recomputed. + + Here is an example of recomputation demonstrated in Slang source-style (although this takes place in IR-form) + ```C + // Example function without loops post-transposition step. + void f_rev(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + p = t2 * t2 + x; + } + + // + // Reversed differential blocks start here (will be extracted into a separate function in Step 6: Extraction) + // + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = t2 * dp_rev; // access of a primal value 't2' from a differential block. + dx_rev += dp_rev; + dp_rev = 0.f; // dp_rev's value gets reset to 0 after use. + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = t1 * dp_rev; // access of a primal value 't1' from a differential block. + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + + dpx = DifferentialPair(x, dx_rev); + } + + // The same function after the primal hoisting step. Note that the primal control flow has been cloned into the start of + // the top-level differential region. + // + void f_rev_hoisted(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + p = t2 * t2 + x; + } + + // + // Reversed differential blocks start here (will be extracted into a separate function in Step 6: Extraction) + // + + // Recompute blocks are inserted at the beginning of each differential region. + float x_recompute = dpx.getPrimal(); + if (x_recompute < 0.5) + { + // Only the t1 instruction is cloned in since it is used by the differential blocks. + float t1_recompute = x_recompute * x_recompute; + } + + if (x_recompute > 10.f) + { + // Only the t2 instruction is cloned in since it is used by the differential blocks. + float t2_recompute = x_recompute * x_recompute * x_recompute; + } + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x_recompute > 10.f) + { + float dt2_rev = t2_recompute * dp_rev; // invalid access of 't2_recompute' (it's inside a branch) + dx_rev += dp_rev; + + dx_rev += x_recompute * x_recompute * dt2_rev; + dx_rev += x_recompute * dt2_rev * x_recompute; + dx_rev += dt2_rev * x_recompute * x_recompute; + } + + if (x < 0.5) + { + float dt1_rev = t1 * dp_rev; // invalid access of 't1_recompute' (it's inside a branch) + dx_rev += dp_rev; + + dx_rev += x_recompute * dt1_rev; + dx_rev += dt1_rev * x_recompute; + } + + dpx = DifferentialPair(x, dx_rev); + } + + // Same function after branch-access-legalization (run after the primal-hoisting step): + void f_rev_hoisted_and_legalized(DifferentialPair dpx, float d_out) + { + // + // Primal blocks: + // + + float x = dpx.getPrimal(); + float p = 0; + + float t1; // Var inserted/moved to immediate dominator block (branch-access-legalization) + if (x < 0.5) + { + t1 = x * x; + p = t1 * t1 + x; + } + + float t2; // Var inserted/moved to immediate dominator block (branch-access-legalization) + if (x > 10.f) + { + t2 = x * x * x; + p = t2 * t2 + x; + } + + // + // Reversed differential blocks: + // + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = t2 * dp_rev; + dx_rev += dp_rev; + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = t1 * dp_rev; + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + } + ``` + + For completeness, here is another example of a function `g` which contains a loop to demonstrate how recomputation works when there are + multiple loop regions. + + ```C + // Example function with a loop, post-transposition step (BEFORE hoisting) + void g_rev(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = x; + + if (x < 0.5) + { + float k = 2.f * x; + p = p * k; + } + + for (uint i = 0; i < 10; i++) + { + if (x > 0.5) + { + float t = 2.f * i; + p = p + x * t; + } + } + + // + // Reversed differential blocks + // + + float dt_rev = 0.f; + float dp_rev = 0.f; + for (uint i = 9; i >= 0; i++) + { + if (x > 0.5) + { + dx_rev += t * dp_rev; // Use of primal value 't' in differential blocks. + } + } + + if (x < 0.5) + { + dp_rev = dp_rev * k; // Use of primal value 'k' in differential blocks. + float dk_rev = p * dp_rev; // Use of primal value 'p' in differential blocks. + dx_rev += dk_rev * 2.f; + } + + dx_rev += dp_rev; + + return DifferentialPair(x, dx_rev); + } + + // The same function after hoisting and branch-access-legalization. + // Notice that recompute blocks are inserted into the top-level + // as well as each loop region in the differential blocks. + // + void g_rev_hoisted_and_legalized(DifferentialPair dpx, float d_out) + { + // + // Primal blocks (will be extracted into a separate function in Step 6: Extraction) + // + + float x = dpx.getPrimal(); + float p = x; + + if (x < 0.5) + { + float k = 2.f * x; + p = p * k; + } + + for (uint i = 0; i < 10; i++) + { + if (x > 0.5) + { + float t = 2.f * i; + p = p + x * t; + } + } + + // + // Reversed differential blocks + // + + // ----- Recompute blocks inserted for top-level + float p_recompute = x; // Inst recomputed. + float k_recompute; + if (x < 0.5) + { + k_recompute = 2.f * x; // Inst recomputed. + } + // ----- + + float dt_rev = 0.f; + float dp_rev = 0.f; + for (uint i = 9; i >= 0; i++) + { + // ---- Recompute blocks inserted for loop region. + float t_recompute; + if (x > 0.5) + { + t_recompute = 2.f * i; // Inst recomputed. + } + // ---- + + if (x > 0.5) + { + dx_rev += t_recompute * dp_rev; + } + } + + if (x < 0.5) + { + dp_rev = dp_rev * k_recompute; + float dk_rev = p_recompute * dp_rev; + dx_rev += dk_rev * 2.f; + } + + dx_rev += dp_rev; + + return DifferentialPair(x, dx_rev); + } + ``` + +### 6. Extraction +The final step involves _splitting_ the function immediately after the primal block to create two functions: a **primal context function** that computes the primal value normally, but also outputs a context object with relevant intermediate values, and a **backward propagation function** that computes the backward derivative and consumes this context object for the required intermediate values. + +The first 5 steps have set us up for this final step, so it is not particularly complex. We follow this high-level logic: + +1. Create an empty function for the primal context function. The type of this function is the same as the primal function, but with an additional `out` parameter for the intermediate context, whose type is undecided at this stage. We use a temporary function-specific type called `OpBackwardDerivativeIntermediateContextType(func)` as a placeholder. +2. Move primal blocks to the primal context function. Re-create the return inst (the return value is temporarily remembered using a decoration during the rest of the AD process). Also, the first block (reserved for function parameters) is also duplicated and processed to have primal parameters in the primal function and pair parameters in the differential function. +3. Lower all `OpBackwardDerivativeIntermediateContextType` types into concrete struct types by creating a field for each 'stored' inst from Step 5. This lowering process happens **at the end of the current AD pass after all relevant methods have completed Step 5**. We need Step 5 (hoisting) to be complete for all relevant methods because the context struct for a given function can include context structs of other functions that are called from it. Our context-type lowering therefore proceeds recursively by lowering the context for inner functions as necessary. The lowering process also removes the temporary vars that were created to hold the store insts, and replaces them with a stores and loads from the context struct. + + **Recursive Functions are Disallowed:** Since we lower all intermediate types into a static struct type, recursive calls cannot currently be supported from differentiable functions. The context struct for a method may include itself, creating an impossible scenario. + +Here is one of the examples above (`g`) after checkpointing: + +```C +// Example function before the extraction step. +void f_rev_hoisted(DifferentialPair dpx, float d_out) +{ + // Insert vars for checkpointed insts at the top-level + float t1_storage; + float t2_storage; + + // + // Primal blocks + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + t1_storage = t1; // Cache values immediately after they are created. + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + t2_storage = t2; // Cache values immediately after they are created. + p = t2 * t2 + x; + } + + // + // Reversed differential blocks + // + + float x = dpx.getPrimal(); + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = t2_storage * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = t1_storage * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + + dpx = DifferentialPair(x, dx_rev); +} + +// After extraction: lowered intermediate context for f +struct f_Intermediates +{ + float t1; + float t2; +}; + + +// After extraction: primal context function +float s_primal_ctx_f(float x, out f_Intermediates ctx) +{ + // + // Primal blocks + // + + float x = dpx.getPrimal(); + float p = 0; + + if (x < 0.5) + { + float t1 = x * x; + ctx.t1 = t1; // Cache values immediately after they are created. + p = t1 * t1 + x; + } + + if (x > 10.f) + { + float t2 = x * x * x; + ctx.t2 = t2; // Cache values immediately after they are created. + p = t2 * t2 + x; + } + + return p; +} + +// After extraction: backward propagation function. +void s_bwd_f(DifferentialPair dpx, float d_out, f_Intermediates ctx) +{ + float x = dpx.getPrimal(); + + float dp_rev = d_out; + float dx_rev = 0.f; // accumulator var for 'x.d' + if (x > 10.f) + { + float dt2_rev = ctx.t2 * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * x * dt2_rev; + dx_rev += x * dt2_rev * x; + dx_rev += dt2_rev * x * x; + } + + if (x < 0.5) + { + float dt1_rev = ctx.t1 * dp_rev; // Use stored value. + dx_rev += dp_rev; + + dx_rev += x * dt1_rev; + dx_rev += dt1_rev * x; + } + + dpx = DifferentialPair(x, dx_rev); +} +``` + +Having separate methods for the primal and backward passes is necessary when reverse-mode differentiating a method that calls out to other differentiable functions. +Here is an example of differentiating a method that calls out to multiple methods, to get an idea for why we need the primal context method to be separate + +```C +float outer(float x) +{ + float y = f(x); + float z = g(y); + float w = h(z); + + return w; +} + +// It's complete reverse mode derivative looks like the following: +void outer_rev(DifferentialPair dpx, float d_output) +{ + // Compute the primal values in the forward direction, while producing relevant context. + f_Intermediates f_ctx; + g_Intermediates g_ctx; + h_Intermediates h_ctx; + + float y = s_primal_ctx_f(x, f_ctx); + float z = s_primal_ctx_g(y, g_ctx); + float w = s_primal_ctx_h(z, h_ctx); + + // Note that at this point, we are holding intermediate context variables for f, g and h. + + // Consume the context while evaluating the propagating the derivatives backwards. + DifferentialPair dpz = {z, 0.f}; + s_bwd_h(dpz, d_output, h_ctx); + + DifferentialPair dpy = {y, 0.f}; + s_bwd_g(dpy, dpz.getDifferential(), g_ctx); + + DifferentialPair _dpx = {x, 0.f}; + s_bwd_f(dpx, dpy.getDifferential(), f_ctx); + + dpx = _dpx; +} +``` diff --git a/lib/All/slang/share/doc/slang/design/autodiff/types.md b/lib/All/slang/share/doc/slang/design/autodiff/types.md new file mode 100644 index 0000000..3860f0d --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/autodiff/types.md @@ -0,0 +1,290 @@ + +This documentation is intended for Slang contributors and is written from a compiler engineering point of view. For Slang users, see the user-guide at this link: [https://shader-slang.com/slang/user-guide/autodiff.html](https://shader-slang.com/slang/user-guide/autodiff.html) + +Before diving into this document, please review the document on [Basics](./basics.md) for the fundamentals of automatic differentiation. + +# Components of the Type System +Here we detail the main components of the type system: the `IDifferentiable` interface to define differentiable types, the `DifferentialPair` type to carry a primal and corresponding differential in a single type. +We also detail how auto-diff operators are type-checked (the higher-order function checking system), how the `no_diff` decoration can be used to avoid differentiation through attributed types, and the derivative data flow analysis that warns the the user of unintentionally stopping derivatives. + +## `interface IDifferentiable` +Defined in core.meta.slang, `IDifferentiable` forms the basis for denoting differentiable types, both within the core module, and otherwise. +The definition of `IDifferentiable` is designed to encapsulate the following 4 items: +1. `Differential`: The type of the differential value of the conforming type. This allows custom data-structures to be defined to carry the differential values, which may be optimized for space instead of relying solely on compiler synthesis/ + +Since the computation of derivatives is inherently linear, we only need access to a few operations. These are: + +2. `dadd(Differential, Differential) -> Differential`: Addition of two values of the differential type. It's implementation must be associative and commutative, or the resulting derivative code may be incorrect. +3. `dzero() -> Differential`: Additive identity (i.e. the zero or empty value) that can be used to initialize variables during gradient aggregation +4. `dmul(S, Differential)`: Scalar multiplication of a real number with the differential type. It's implementation must be distributive over differential addition (`dadd`). + +Points 2, 3 & 4 are derived from the concept of vector spaces. The derivative values of any Slang function always form a vector space (https://en.wikipedia.org/wiki/Vector_space). + +### Derivative member associations +In certain scenarios, the compiler needs information on how the fields in the original type map to the differential type. Particularly, this is a problem when differentiate the implicit construction of a struct through braces (i.e. `{}`), represented by `kIROp_MakeStruct`. We provide the decorator `[DerivativeMember(DifferentialTypeName.fieldName)]` (ASTNode: DerivativeMemberAttribute, IR: kIROp_DerivativeMemberDecoration) to explicitly mark these associations. +Example +```C +struct MyType : IDifferentiable +{ + typealias Differential = MyDiffType; + float a; + + [DerivativeMember(MyDiffType.db)] + float b; + + /* ... */ +}; + +struct MyDiffType +{ + float db; +}; +``` + +### Automatic Synthesis of `IDifferentible` Conformances for Aggregate Types +It can be tedious to expect users to hand-write the associated `Differential` type, the corresponding mappings and interface methods for every user-defined `struct` type. For aggregate types, these are trivial to construct by analysing which of their components conform to `IDifferentiable`. +The synthesis proceeds in roughly the following fashion: +1. `IDifferentiable`'s components are tagged with special decorator `__builtin_requirement(unique_integer_id)` which carries an enum value from `BuiltinRequirementKind`. +2. When checking that types conform to their interfaces, if a user-provided definition does not satisfy a requirement with a built-in tag, we perform synthesis by dispatching to `trySynthesizeRequirementWitness`. +3. For _user-defined types_, Differential **types** are synthesized during conformance-checking through `trySynthesizeDifferentialAssociatedTypeRequirementWitness` by checking if each constituent type conforms to `IDifferentiable`, looking up the corresponding `Differential` type, and constructing a new aggregate type from these differential types. Note that since it is possible that a `Differential` type of a constituent member has not yet been synthesized, we have additional logic in the lookup system (`trySynthesizeRequirementWitness`) that synthesizes a temporary empty type with a `ToBeSynthesizedModifier`, so that the fields can be filled in later, when the member type undergoes conformance checking. +4. For _user-defined types_, Differential methods (`dadd`, `dzero` and `dmul`) are synthesized in `trySynthesizeDifferentialMethodRequirementWitness` by utilizing the `Differential` member and its `[DifferentialMember]` decorations to determine which fields need to be considered and the base type to use for each field. There are two synthesis patterns. The fully-inductive pattern is used for `dadd` and `dzero` which works by calling `dadd` and `dzero` respectively on the individual fields of the `Differential` type under consideration. +Example: +```C +// Synthesized from "struct T {FT1 field1; FT2 field2;}" +T.Differential dadd(T.Differential a, T.Differential b) +{ + return Differential( + FT1.dadd(a.field1, b.field1), + FT2.dadd(a.field2, b.field2), + ) +} +``` +On the other hand, `dmul` uses the fixed-first arg pattern since the first argument is a common scalar, and proceeds inductively on all the other args. +Example: +```C +// Synthesized from "struct T {FT1 field1; FT2 field2;}" +T.Differential dmul(S s, T.Differential a) +{ + return Differential( + FT1.dmul(s, a.field1), + FT2.dmul(s, a.field2), + ) +} +``` +5. During auto-diff, the compiler can sometimes synthesize new aggregate types. The most common case is the intermediate context type (`kIROp_BackwardDerivativeIntermediateContextType`), which is lowered into a standard struct once the auto-diff pass is complete. It is important to synthesize the `IDifferentiable` conformance for such types since they may be further differentiated (through higher-order differentiation). This implementation is contained in `fillDifferentialTypeImplementationForStruct(...)` and is roughly analogous to the AST-side synthesis. + +### Differentiable Type Dictionaries +During auto-diff, the IR passes frequently need to perform lookups to check if an `IRType` is differentiable, and retrieve references to the corresponding `IDifferentiable` methods. These lookups also need to work on generic parameters (that are defined inside generic containers), and existential types that are interface-typed parameters. + +To accommodate this range of different type systems, Slang uses a type dictionary system that associates a dictionary of relevant types with each function. This works in the following way: +1. When `CheckTerm()` is called on an expression within a function that is marked differentiable (`[Differentiable]`), we check if the resolved type conforms to `IDifferentiable`. If so, we add this type to the dictionary along with the witness to its differentiability. The dictionary is currently located on `DifferentiableAttribute` that corresponds to the `[Differentiable]` modifier. + +2. When lowering to IR, we create a `DifferentiableTypeDictionaryDecoration` which holds the IR versions of all the types in the dictionary as well as a reference to their `IDifferentiable` witness tables. + +3. When synthesizing the derivative code, all the transcriber passes use `DifferentiableTypeConformanceContext::setFunc()` to load the type dictionary. `DifferentiableTypeConformanceContext` then provides convenience functions to lookup differentiable types, appropriate `IDifferentiable` methods, and construct appropriate `DifferentialPair`s. + +### Looking up Differential Info on _Generic_ types +Generically defined types are also lowered into the differentiable type dictionary, but rather than having a concrete witness table, the witness table is itself a parameter. When auto-diff passes need to find the differential type or place a call to the IDifferentiable methods, this is turned into a lookup on the witness table parameter (i.e. `Lookup(, )`). Note that these lookups instructions are inserted into the generic parent container rather than the inner most function. +Example: +```C +T myFunc(T a) +{ + return a * a; +} + +// Reverse-mode differentiated version +void bwd_myFunc( + inout DifferentialPair dpa, + T.Differential dOut) // T.Differential is Lookup('Differential', T_Witness_Table) +{ + T.Differential da = T.dzero(); // T.dzero is Lookup('dzero', T_Witness_Table) + + da = T.dadd(dpa.p * dOut, da); // T.dadd is Lookup('dadd', T_Witness_Table) + da = T.dadd(dpa.p * dOut, da); + + dpa = diffPair(dpa.p, da); +} +``` + +### Looking up Differential Info on _Existential_ types +Existential types are interface-typed values, where there are multiple possible implementations at run-time. The existential type carries information about the concrete type at run-time and is effectively a 'tagged union' of all possible types. + +#### Differential type of an Existential +The differential type of an existential type is tricky to define since our type system's only restriction on the `.Differential` type is that it also conforms to `IDifferentiable`. The differential type of any interface `IInterface : IDifferentiable` is therefore the interface type `IDifferentiable`. This is problematic since Slang generally requires a static `anyValueSize` that must be a strict upper bound on the sizes of all conforming types (since this size is used to allocate space for the union). Since `IDifferentiable` is defined in the core module `core.meta.slang` and can be used by the user, it is impossible to define a reliable bound. +We instead provide a new **any-value-size inference** pass (`slang-ir-any-value-inference.h`/`slang-ir-any-value-inference.cpp`) that assembles a list of types that conform to each interface in the final linked IR and determines a relevant upper bound. This allows us to ignore types that conform to `IDifferentiable` but aren't used in the final IR, and generate a tighter upper bound. + +**Future work:** +This approach, while functional, creates a locality problem since the size of `IDifferentiable` is the max of _all_ types that conform to `IDifferentiable` in visible modules, even though we only care about the subset of types that appear as `T.Differential` for `T : IInterface`. The reason for this problem is that upon performing an associated type lookup, the Slang IR drops all information about the base interface that the lookup starts from and only considers the constraint interface (in this case `Differential : IDifferentiable`). +There are several ways to resolve this issue, including (i) a static analysis pass that determines the possible set of types at each use location and propagates them to determine a narrower set of types, or (ii) generic (or 'parameterized') interfaces, such as `IDifferentiable` where each version can have a different set of conforming types. + + + +Example: +```C +interface IInterface : IDifferentiable +{ + [Differentiable] + This foo(float val); + + [Differentiable] + float bar(); +}; + +float myFunc(IInterface obj, float a) +{ + IInterface k = obj.foo(a); + return k.bar(); +} + +// Reverse-mode differentiated version (in pseudo-code corresponding to IR, some of these will get lowered further) +void bwd_myFunc( + inout DifferentialPair dpobj, + inout DifferentialPair dpa, + float.Differential dOut) // T.Differential is Lookup('Differential', T_Witness_Table) +{ + // Primal pass.. + IInterface obj = dpobj.p; + IInterface k = obj.foo(a); + // ..... + + // Backward pass + DifferentialPair dpk = diffPair(k); + bwd_bar(dpk, dOut); + IDifferentiable dk = dpk.d; // Differential of `IInterface` is `IDifferentiable` + + DifferentialPair dp = diffPair(dpobj.p); + bwd_foo(dpobj, dpa, dk); +} + +``` + +#### Looking up `dadd()` and `dzero()` on Existential Types +There are two distinct cases for lookup on an existential type. The more common case is the closed-box existential type represented simply by an interface. Every value of this type contains a type identifier & a witness table identifier along with the value itself. The less common case is when the function calls are performed directly on the value after being cast to the concrete type. + +**`dzero()` for "closed" Existential type: The `NullDifferential` Type** +For concrete and even generic types, we can initialize a derivative accumulator variable by calling the appropriate `Type.dzero()` method. This is unfortunately not possible when initializing an existential differential (which is currently of type `IDifferentiable`), since we must also initialize the type-id of this existential to one of the implementations, but we do not know which one yet since that is a run-time value that only becomes known after the first differential value is generated. + +To get around this issue, we declare a special type called `NullDifferential` that acts as a "none type" for any `IDifferentiable` existential object. + +**`dadd()` for "closed" Existential types: `__existential_dadd`** +We cannot directly use `dadd()` on two existential differentials of type `IDifferentiable` because we must handle the case where one of them is of type `NullDifferential` and `dadd()` is only defined for differentials of the same type. +We handle this currently by synthesizing a special method called `__existential_dadd` (`getOrCreateExistentialDAddMethod` in `slang-ir-autodiff.cpp`) that performs a run-time type-id check to see if one of the operand is of type `NullDifferential` and returns the other operand if so. If both are non-null, we dispatch to the appropriate `dadd` for the concrete type. + +**`dadd()` and `dzero()` for "open" Existential types** +If we are dealing with values of the concrete type (i.e. the opened value obtained through `ExtractExistentialValue(ExistentialParam)`). Then we can perform lookups in the same way we do for generic type. All existential parameters come with a witness table. We insert instructions to extract this witness table and perform lookups accordingly. That is, for `dadd()`, we use `Lookup('dadd', ExtractExistentialWitnessTable(ExistentialParam))` and place a call to the result. + +## `struct DifferentialPair` +The second major component is `DifferentialPair` that represents a pair of a primal value and its corresponding differential value. +The differential pair is primarily used for passing & receiving derivatives from the synthesized derivative methods, as well as for block parameters on the IR-side. +Both `fwd_diff(fn)` and `bwd_diff(fn)` act as function-to-function transformations, and so the Slang front-end translates the type of `fn` to its derivative version so the arguments can be type checked. + +### Pair type lowering. +The differential pair type is a special type throughout the AST and IR passes (AST Node: `DifferentialPairType`, IR: `kIROp_DifferentialPairType`) because of its use in front-end semantic checking and when synthesizing the derivative code for the functions. Once the auto-diff passes are complete, the pair types are lowering into simple `struct`s so they can be easily emitted (`DiffPairLoweringPass` in `slang-ir-autodiff-pairs.cpp`). +We also define additional instructions for pair construction (`kIROp_MakeDifferentialPair`) and extraction (`kIROp_DifferentialPairGetDifferential` & `kIROp_DifferentialPairGetPrimal`) which are lowered into struct construction and field accessors, respectively. + +### "User-code" Differential Pairs +Just as we use special IR codes for differential pairs because they have special handling in the IR passes, sometimes differential pairs should be _treated as_ regular struct types during the auto-diff passes. +This happens primarily during higher-order differentiation when the user wishes to differentiate the same code multiple times. +Slang's auto-diff approaches this by rewriting all the relevant differential pairs into 'irrelevant' differential pairs (`kIROp_DifferentialPairUserCode`) and 'irrelevant' accessors (`kIROp_DifferentialPairGetDifferentialUserCode`, `kIROp_DifferentialPairGetPrimalUserCode`) at the end of **each auto-diff iteration** so that the next iteration treats these as regular differentiable types. +The user-code versions are also lowered into `struct`s in the same way. + +## Type Checking of Auto-Diff Calls (and other _higher-order_ functions) +Since `fwd_diff` and `bwd_diff` are represented as higher order functions that take a function as an input and return the derivative function, the front-end semantic checking needs some notion of higher-order functions to be able to check and lower the calls into appropriate IR. + +### Higher-order Invocation Base: `HigherOrderInvokeExpr` +All higher order transformations derive from `HigherOrderInvokeExpr`. For auto-diff there are two possible expression classes `ForwardDifferentiateExpr` and `BackwardDifferentiateExpr`, both of which derive from this parent expression. + +### Higher-order Function Call Checking: `HigherOrderInvokeExprCheckingActions` +Resolving the concrete method is not a trivial issue in Slang, given its support for overloading, type coercion and more. This becomes more complex with the presence of a function transformation in the chain. +For example, if we have `fwd_diff(f)(DiffPair(...), DiffPair(...))`, we would need to find the correct match for `f` based on its post-transform argument types. + +To facilitate this we use the following workflow: +1. The `HigherOrderInvokeExprCheckingActions` base class provides a mechanism for different higher-order expressions to implement their type translation (i.e. what is the type of the transformed function). +2. The checking mechanism passes all detected overloads for `f` through the type translation and assembles a new group out of the results (the new functions are 'temporary') +3. This new group is used by `ResolveInvoke` when performing overload resolution and type coercion using the user-provided argument list. +4. The resolved signature (if there is one) is then replaced with the corresponding function reference and wrapped in the appropriate higher-order invoke. + +**Example:** + +Let's say we have two functions with the same name `f`: (`int -> float`, `double, double -> float`) +and we want to resolve `fwd_diff(f)(DiffPair(1.0, 0.0), DiffPair(0.0, 1.0))`. + +The higher-order checking actions will synthesize the 'temporary' group of translated signatures (`int -> DiffPair`, `DiffPair, DiffPair -> DiffPair`). +Invoke resolution will then narrow this down to a single match (`DiffPair, DiffPair -> DiffPair`) by automatically casting the `float`s to `double`s. Once the resolution is complete, +we return `InvokeExpr(ForwardDifferentiateExpr(f : double, double -> float), casted_args)` by wrapping the corresponding function in the corresponding higher-order expr + +## Attributed Types (`no_diff` parameters) + +Often, it will be necessary to prevent gradients from propagating through certain parameters, for correctness reasons. For example, values representing random samples are often not differentiated since the result may be mathematically incorrect. + +Slang provides the `no_diff` operator to mark parameters as non-differentiable, even if they use a type that conforms to `IDifferentiable` + +```C +float myFunc(float a, no_diff float b) +{ + return a * b; +} + +// Resulting fwd-mode derivative: +DiffPair myFunc(DiffPair dpa, float b) +{ + return diffPair(dpa.p * b, dpa.d * b); +} +``` + +Slang uses _OpAttributedType_ to denote the IR type of such parameters. For example, the lowered type of `b` in the above example is `OpAttributedType(OpFloat, OpNoDiffAttr)`. In the front-end, this is represented through the `ModifiedType` AST node. + +Sometimes, this additional layer can get in the way of things like type equality checks and other mechanisms where the `no_diff` is irrelevant. Thus, we provide the `unwrapAttributedType` helper to remove attributed type layers for such cases. + +## Derivative Data-Flow Analysis +Slang has a derivative data-flow analysis pass that is performed on a per-function basis immediately after lowering to IR and before the linking step (`slang-ir-check-differentiability.h`/`slang-ir-check-differentiability.cpp`). + +The job of this pass is to enforce that instructions that are of a differentiable type will propagate a derivatives, unless explicitly dropped by the user through `detach()` or `no_diff`. The reason for this is that Slang requires functions to be decorated with `[Differentiable]` to allow it to propagate derivatives. Otherwise, the function is considered non-differentiable, and effectively produces a 0 derivative. This can lead to frustrating situations where a function may be dropping non-differentiable on purpose. Example: +```C +float nonDiffFunc(float x) +{ + /* ... */ +} + +float differentiableFunc(float x) // Forgot to annotate with [Differentiable] +{ + /* ... */ +} + +float main(float x) +{ + // User doesn't realise that the function that is supposed to be differentiable is not + // getting differentiated, because the types here are all 'float'. + // + return nonDiffFunc(x) * differentiableFunc(x); +} +``` + +The data-flow analysis step enforces that non-differentiable functions used in a differentiable context should get their derivative dropped explicitly. That way, it is clear to the user whether a call is getting differentiated or dropped. + +Same example with `no_diff` enforcement: +```C +float nonDiffFunc(float x) +{ + /* ... */ +} + +[Differentiable] +float differentiableFunc(float x) +{ + /* ... */ +} + +float main(float x) +{ + return no_diff(nonDiffFunc(x)) * differentiableFunc(x); +} +``` + +A `no_diff` can only be used directly on a function call, and turns into a `TreatAsDifferentiableDecoration` that indicates that the function will not produce a derivative. + +The derivative data-flow analysis pass works similar to a standard data-flow pass: +1. We start by assembling a set of instructions that 'produce' derivatives by starting with the parameters of differentiable types (and without an explicit `no_diff`), and propagating them through each instruction in the block. An inst carries a derivative if there one of its operands carries a derivative, and the result type is differentiable. +2. We then assemble a set of instructions that expect a derivative. These are differentiable operands of differentiable functions (unless they have been marked by `no_diff`). We then reverse-propagate this set by adding in all differentiable operands (and repeating this process). +3. During this reverse-propagation, if there is any `OpCall` in the 'expect' set that is not also in the 'produce' set, then we have a situation where the gradient hasn't been explicitly dropped, and we create a user diagnostic. diff --git a/lib/All/slang/share/doc/slang/design/backwards-compat-for-ir-modules.md b/lib/All/slang/share/doc/slang/design/backwards-compat-for-ir-modules.md new file mode 100644 index 0000000..4f859c6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/backwards-compat-for-ir-modules.md @@ -0,0 +1,199 @@ +# Design Document: Slang IR Module Backwards Compatibility + +## Overview + +This document describes the design and implementation of backwards compatibility support for serialized Slang IR modules. The feature enables Slang to load IR modules compiled with different versions of the compiler, providing version information and graceful handling of incompatible modules. + +## Motivation + +As Slang evolves, the intermediate representation (IR) may change with new instructions being added or existing ones being modified. Without backwards compatibility: + +- Users cannot load modules compiled with older versions of Slang +- There's no way to detect version mismatches between modules +- Module compatibility issues are opaque to users + +This feature addresses these issues by introducing versioning and stable instruction naming. + +## User-Facing Changes + +### New Command Line Options + +1. **`-get-module-info `** + + - Prints information about a serialized IR module without loading it + - Output includes: + - Module name + - Module version + - Compiler version that created the module + - Example usage: `slangc -get-module-info mymodule.slang-module` + +2. **`-get-supported-module-versions`** + - Prints the range of module versions this compiler supports + - Output includes minimum and maximum supported versions + - Example usage: `slangc -get-supported-module-versions` + +### API Changes + +New method in `ISession` interface: + +```cpp +SlangResult loadModuleInfoFromIRBlob( + slang::IBlob* source, + SlangInt& outModuleVersion, + const char*& outModuleCompilerVersion, + const char*& outModuleName); +``` + +This allows programmatic inspection of module metadata without full deserialization. + +## Technical Design + +### Stable Instruction Names + +The core mechanism for backwards compatibility is the introduction of stable names for IR instructions: + +1. **Stable Name Table** (`slang-ir-insts-stable-names.lua`) + + - Maps instruction names to unique integer IDs + - IDs are permanent once assigned + - New instructions get new IDs, never reusing old ones + +2. **Runtime Mapping** + - `getOpcodeStableName(IROp)`: Convert runtime opcode to stable ID + - `getStableNameOpcode(UInt)`: Convert stable ID back to runtime opcode + - Unknown stable IDs map to `kIROp_Unrecognized` + +### Module Versioning + +Two types of versions are tracked: + +1. **Module Version** (`IRModule::m_version`) + + - Semantic version of the IR instruction set + - Range: `k_minSupportedModuleVersion` to `k_maxSupportedModuleVersion` + - Stored in each serialized module + +2. **Serialization Version** (`IRModuleInfo::serializationVersion`) + - Version of the serialization format itself + - Currently version 0 + - Allows future changes to serialization structure + +### Compiler Version Tracking + +Each module stores the exact compiler version (`SLANG_TAG_VERSION`) that created it. This enables version-specific workarounds if needed in the future. + +### Validation System + +A GitHub Actions workflow (`check-ir-stable-names.yml`) ensures consistency: + +1. **Check Mode**: Validates that: + + - All IR instructions have stable names + - No duplicate stable IDs exist + - The stable name table is a bijection with current instructions + +2. **Update Mode**: Automatically assigns stable IDs to new instructions + +The validation is implemented in `check-ir-stable-names.lua` which: + +- Loads instruction definitions from `slang-ir-insts.lua` +- Compares against `slang-ir-insts-stable-names.lua` +- Reports missing entries or inconsistencies + +## Breaking Changes and Version Management + +### When to Update Module Version + +The module version must be updated when: + +1. **Adding Instructions** (Minor Version Bump) + + - Increment `k_maxSupportedModuleVersion` + - Older compilers can still load modules that don't use new instructions + +2. **Removing Instructions** (Major Version Bump) + + - Increment `k_maxSupportedModuleVersion` + - Update `k_minSupportedModuleVersion` to exclude versions with removed instructions + - This breaks compatibility with older modules using removed instructions + +3. **Changing Instruction Semantics** + - Even if the instruction name remains the same + - Requires version bump to prevent incorrect behavior + - To avoid bumping the minimum supported version, one may instead introduce + a new instruction and just bump `k_maxSupportedModuleVersion` + +### Serialization Format Changes + +Changes to how data is serialized (not what data) require updating `serializationVersion`: + +- Changes to the RIFF container structure +- Different encoding for instruction payloads +- Reordering of serialized data + +## Implementation Details + +### Module Loading Flow + +1. **Version Check** + + ```cpp + if (fossilizedModuleInfo->serializationVersion != IRModuleInfo::kSupportedSerializationVersion) + return SLANG_FAIL; + ``` + +2. **Instruction Deserialization** + + - Stable IDs are converted to runtime opcodes + - Unknown IDs become `kIROp_Unrecognized` + +3. **Validation Pass** + - After deserialization, check for any `kIROp_Unrecognized` instructions + - Fail loading if any are found + +### Error Handling + +- Incompatible serialization versions: Immediate failure +- Unknown instructions: Mark as unrecognized, fail after full deserialization + (this should be caught by the next check) +- Module version out of range: Fail after deserialization + +## Future Considerations + +### Potential Enhancements + +1. **Graceful Degradation** + + - Skip unrecognized instructions if they're not critical + - Provide compatibility shims for removed instructions + +2. **Module Migration Tools** + + - Utility to upgrade old modules to new formats + - Batch processing for large codebases + +### Maintenance Guidelines + +1. **Regular CI Validation** + + - The GitHub Action ensures stable names stay synchronized + - Catches missing entries before merge + +2. **Version Documentation** + + - Maintain changelog of what changed in each module version + - Document any version-specific workarounds + +3. **Testing** + - Test loading of modules from previous versions + - Verify error messages for incompatible modules + +## Conclusion + +This backwards compatibility system provides a robust foundation for Slang IR evolution while maintaining compatibility where possible. The combination of stable instruction naming, comprehensive versioning, and automated validation ensures that: + +- Users can reliably use modules across Slang versions +- Developers can evolve the IR with clear compatibility boundaries +- Version mismatches are detected and reported clearly + +The system is designed to be maintainable and extensible, with clear guidelines for when and how to make breaking changes. diff --git a/lib/All/slang/share/doc/slang/design/capabilities.md b/lib/All/slang/share/doc/slang/design/capabilities.md new file mode 100644 index 0000000..b4bd4c0 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/capabilities.md @@ -0,0 +1,271 @@ +Capabilities (Out of Date) +============ + +Slang aims to be a portable language for shader programming, which introduces two complementary problems: + +1. We need a way to indicate that certain constructs (types, functions, etc.) are only allowed on certain targets, so that a user gets a meaningful error if they try to do something that won't work on one or more of the APIs or platforms they want to target. Similarly, the user expects to get an error if they call a fragment-shader-specific function inside of, say, compute shader code, or vice versa. + +2. If the same feature can be implemented across multiple platforms, but the best (or only) implementation path differs across platforms, then we need a way to express the platform specific code and pick the right implementation per-target. + +Item (2) is traditionally handled with preprocessor techniques (e.g., `#ifdef`ing the body of a function based on target platform), but that of course requires that the user invoke the Slang front end once for each target platform, and target-specific coding in a library will then "infect" code that uses that library, forcing them to invoke the front-end once per target as well. + +We are especially sensitive to this problem in the compiler itself, because we have to author and maintain the Slang standard modules, which needs to (1) expose the capabilities of many platforms and (2) work across all those platforms. It would be very unfortunate if we had to build different copies of our standard modules per-target. + +The intention in Slang is to solve both of these problems with a system of *capabilities*. + +What is a capability? +--------------------- + +For our purposes a capability is a discrete feature that a compilation target either does or does not support. +We could imagine defining a capability for the presence of texture sampling operations with implicit gradients; this capability would be supported when generating fragment shader kernel code, but not when generating code for other stages. + +Let's imagine a language syntax that the standard modules could use to define some *atomic* capabilities: + +``` +capability implicit_gradient_texture_fetches; +``` +We can then imagine using attributes to indicate that a function requires a certain capability: + +``` +struct Texture2D +{ + ... + + // Implicit-gradient sampling operation. + [availableFor(implicit_gradient_texture_fetches)] + float4 Sample(SamplerState s, float2 uv); +} +``` + +(Note that the `[availableFor(...)]` syntax is just a straw-man to write up examples, and a better name would be desirable if/when we implement this stuff.) + +Given those declarations, we could then check when compiling code if the user is trying to call `Texture2D.Sample` in code compiled for a target that *doesn't* support implicit-gradient texture fetches, and issue an appropriate error. +The details on how to sequence this all in the compiler will be covered later. + +Derived Capabilities +-------------------- + +Once we can define atomic capabilities, the next step is to be able to define *derived* capabilities. +Let's imagine that we extend our `capability` syntax so that we can define a new capability that automatically implies one or more other capabilities: + +``` +capability fragment : implicit_gradient_texture_fetches; +``` + +Here we've said that whenever the `fragment` capability is available, we can safely assume that the `implicit_gradient_texture_fetches` capability is available (but not vice versa). + +Given even a rudimentary tool like that, we can start to build up capabilities that relate closely to the "profiles" in things like D3D: + +``` +capability d3d; +capability sm_5_0 : d3d; +capability sm_5_1 : sm_5_0; +capability sm_6_0 : sm_5_1; +... + +capability d3d11 : d3d, sm_5_0; +capability d3d12 : d3d, sm_6_0; + +capability khronos; +capability glsl_400 : khronos; +capability glsl_410 : glsl_400; +... + +capability vulkan : khronos, glsl_450; +capability opengl : khronos; +``` + +Here we are saying that `sm_5_1` supports everything `sm_5_0` supports, and potentially more. We are saying that `d3d12` supports `sm_6_0` but maybe not, e.g., `sm_6_3`. +We are expressing that fact that having a `glsl_*` capability means you are on some Khronos API target, but that it doesn't specify which one. +(The exact details of these declarations obviously aren't the point; getting a good hierarchy of capabilities will take time.) + +Capability Composition +---------------------- + +Sometimes we'll want to give a distinct name to a specific combination of capabilities, but not say that it supports anything new: + +``` +capability ps_5_1 = sm_5_1 & fragment; +``` + +Here we are saying that the `ps_5_1` capability is *equivalent* to the combination of `sm_5_1` and `fragment` (that is, if you support both `sm_5_1` and `fragment` then you support `ps_5_1` and vice versa). + +Compositions should be allowed in `[availableFor(...)]` attributes (e.g., `[availableFor(vulkan & glsl_450)]`), but pre-defined compositions should be favored when possible. + +When composing things with `&` it is safe for the compiler to filter out redundancies based on what it knows so that, e.g., `ps_5_0 & fragment` resolves to just `ps_5_0`. + +Once we have an `&` operator for capabilities, it is easy to see that "derived" capabilities are really syntax sugar, so that a derived capability like: + +``` +capability A : B, C +``` + +could have been written instead as : + +``` +capability A_atomic +capability A = A_atomic & B & C +``` + +Where the `A_atomic` capability guarantees that `A` implies `B` and `C` but not vice versa. + +It is also useful to think of an `|` operator on capabilities. +In particular if a function has multiple `[availableFor(...)]` attributes: + +``` +[availableFor(vulkan & fragment)] +[availableFor(d3d12 & fragment)] +void myFunc(); +``` + +This function should be equivalent to one with just a single `[availableFor((vulkan & fragment) | (d3d12 & fragment))]` which is equivalent to `[availableFor((vulkan | d3d12) & fragment)]`. +Simplification should generally push toward "disjunctive normal form," though, rather than pursue simplifications like that. +Note that we do *not* include negation, so that capabilities are not general Boolean expressions. + +Validation +---------- + +For a given function definition `F`, the front end will scan its body and see what it calls, and compose the capabilities required by the called functions using `&` (simplifying along the way). Call the resulting capability (in disjunctive normal form) `R`. + +If `F` doesn't have an `[availableFor(...)]` attribute, then we can derive its *effective* `[availableFor(...)]` capability as `R` (this probably needs to be expressed as an iterative dataflow problem over the call graph, to handle cycles). + +If `F` *does* have one or more `[availableFor(...)]` clauses that amount to a declared capability `C` (again in disjunctive normal form), then we can check that `C` implies `R` and error out if it is not the case. +A reasonable implementation would track which calls introduced which requirements, and be able to explain *why* `C` does not capture the stated requirements. + +For a shader entry point, we should check it as if it had an `[availableFor(...)]` that is the OR of all the specified target profiles (e.g., `sm_5_0 | glsl_450 | ...`) ANDed with the specified stage (e.g., `fragment`). +Any error here should be reported to the user. +If an entry point has an explicit `[availableFor(...)]` then we should AND that onto the profile computed above, so that the user can restrict certain entry points to certain profiles. + +In order to support separate compilation, the functions that are exported from a module should probably either have explicit availability attributes, or else they will be compiled against a kind of "default capability" used for the whole module. +Downstream code that consumes such a module would see declarations with explicit capabilities only. +Picking an appropriate "default capability" to use when compiling modules is an important challenge; it would in practice define the "min spec" to use when compiling. + +Capability Overriding +--------------------- + +It should be possible to define multiple versions of a function, having different `[availableFor(...)]` attributes: + +``` +[availableFor(vulkan)] void myFunc() { ... } + +[availableFor(d3d12)] void myFunc() { ... } +``` + +For front-end checking, these should be treated as if they were a single definition of `myFunc` with an ORed capability (e.g., `vulkan | d3d12`). +Overload resolution will pick the "best" candidate at a call site based *only* on the signatures of the function (note that this differs greatly from how profile-specific function overloading works in Cg). + +The front-end will then generate initial IR code for each definition of `myFunc`. +Each of the IR functions will have the *same* mangled name, but different bodies, and each will have appropriate IR decorations to indicate the capabilities it requires. + +The choice of which definition to use is then put off until IR linking for a particular target. +At that point we can look at all the IR functions matching a given mangled name, filter them according to the capabilities of the target, and then select the "best" one. + +In general a definition `A` of an IR symbol is better than another definition `B` if the capabilities on `A` imply those on `B` but not versa. +(In practice this probably needs to be "the capabilities on `A` intersected with those of the target," and similarly for `B`) + +This approach allows us to defer profile-based choices of functions to very late in the process. The one big "gotcha" to be aware of is when functions are overloaded based on pipeline stage, where we would then have to be careful when generating DXIL or SPIR-V modules with multiple entry points (as a single function `f` might need to be specialized twice if it calls a stage-overloaded function `g`). + +Capabilities in Other Places +---------------------------- + +So far I've talked about capabilities on functions, but they should also be allowed on other declarations including: + +- Types, to indicate that code using that type needs the given capability +- Interface conformances, to indicate that a type only conforms to the interface when the capabilities are available +- Struct fields, to indicate that the field is only present in the type when the capabilities are present +- Extension declarations, to indicate that everything in them requires the specified capabilities + +We should also provide a way to specify that a `register` or other layout modifier is only applicable for specific targets/stages. Such a capability nominally exists in HLSL today, but it would be much more useful if it could be applied to specify target-API-specific bindings. + +Only functions should support overloading based on capability. In all other cases there can only be one definition of an entity, and capabilities just decide when it is available. + +API Extensions as Capabilities +------------------------------ + +One clear use case for capabilities is to represent optional extensions, including cases where a feature is "built-in" in D3D but requires an extension in Vulkan: + +``` +capability KHR_secret_sauce : vulkan; + +[available_for(sm_7_0)] // always available for D3D Shader Model 7.0 +[available_for(KHR_secret_sauce)] // Need the "secret sauce" extension for Vulkan +void improveShadows(); +``` + +When generating code for Vulkan, we should be able to tell the user that the `improveShadows()` function requires the given extension. The user should be able to express compositions of capabilities in their `-profile` option (and similarly for the API): + +``` +slangc code.slang -profile vulkan+KHR_secret_sauce +``` +(Note that for the command line, it is beneficial to use `+` instead of `&` to avoid conflicts with shell interpreters) + +An important question is whether the compiler should automatically infer required extensions without them being specified, so that it produces SPIR-V that requires extensions the user didn't ask for. +The argument against such inference is that users should opt in to non-standard capabilities they are using, but it would be unfortunate if this in turn requires verbose command lines when invoking the compiler. +It should be possible to indicate the capabilities that a module or entry point should be compiled to use without command-line complications. + +(A related challenge is when a capability can be provided by two different extensions: how should the compiler select the "right" one to use?) + +Disjoint Capabilities +--------------------- + +Certain compositions of capabilities make no sense. If a user declared a function as needing `vulkan & d3d12` they should probably get an error message. + +Knowing that certain capabilities are disjoint can also help improve the overall user experience. +If a function requires `(vulkan & extensionA) | (d3d12 & featureb)` and we know we are compiling for `vulkan` we should be able to give the user a pointed error message saying they need to ask for `extensionA`, because adding `featureB` isn't going to do any good. + +As a first-pass model we could have a notion of `abstract` capabilities that are used to model the root of hierarchies of disjoint capabilities: + +``` +abstract capability api; + +abstract capability d3d : api; +capability d3d11 : d3d; +capability d3d12 : d3d; + +abstract capability khronos : api; +capability vulkan : khronos; +capability opengl : khronos; +``` + +As a straw man: we could have a rule that to decide if non-abstract capabilities `A` and `B` are disjoint, we look for their common ancestor in the tree of capabilities. +If the common ancestor is abstract, they are disjoint, and if not they not disjoint. +We'd also know that if the user tries to compile for a profile that includes an abstract capability but *not* some concrete capability derived from it, then that is an error (we can't generate code for just `d3d`). + +The above is an over-simplification because we don't have a *tree* of capabilities, but a full *graph*, so we'd need an approach that works for the full case. + +Interaction with Generics/Interfaces +------------------------------------ + +It should be possible for an interface requirement to have a capability requirement attached to it. +This would mean that users of the interface can only use the method/type/whatever when the capability is present (just like for any other function): + +``` +interface ITexture +{ + float4 sampleLevel(float2 uv, float lod); + + [availableFor(fragment)] + float4 sample(float2 uv); // can only call this from fragment code +} +``` +When implementing an interface, any capability constraints we put on a member that satisfies an interface requirement would need to guarantee that either: + +- the capabilities on our method are implied by those on the requirement (we don't require more), or + +- the capabilities on the method are implied by those on the type itself, or its conformance to the interface (you can't use the conformance without the capabilities), or + +- the capabilities are already implied by those the whole module is being compiled for + +In each case, you need to be sure that `YourType` can't be passed as a generic argument to some function that uses just the `ITexture` interface above and have them call a method on your type from a profile that doesn't have the required capabilities. + +Interaction with Heterogeneity +------------------------------ + +If Slang eventually supports generating CPU code as well as shaders, it should use capabilities to handle the CPU/GPU split similar to how they can be used to separate out vertex- and fragment-shader functionality. +Something like a `cpu` profile that works as a catch-all for typical host CPU capabilities would be nice, and could be used as a convenient way to mark "host" functions in a file that is otherwise compiled for a "default profile" that assumes GPU capabilities. + +Conclusion +---------- + +Overall, the hope is that in many cases developers will be able to use capability-based partitioning and overloading of APIs to build code that only has to pass through the Slang front-end once, but that can then go through back-end code generation for each target. +In cases where this can't be achieved, the way that capability-based overloading is built into the Slang IR design means that we should be able to merge multiple target-specific definitions into one IR module, so that a module can employ target-specific specializations while still presenting a single API to consumers. diff --git a/lib/All/slang/share/doc/slang/design/casting.md b/lib/All/slang/share/doc/slang/design/casting.md new file mode 100644 index 0000000..6eafea1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/casting.md @@ -0,0 +1,150 @@ +Casting in the Slang Compiler +============================= + +The following discussion is about casting within the C++ implementation of the slang compiler. + +C++'s built in mechanisms for casting (principally dynamic_cast) is problematic within the slang compiler codebase. Code using 'dynamic_cast' requires RTTI information is available, and that a type that uses it must have a vtbl (have at least one virtual member). Some problems with this... + +* There are types which we want to 'dynamic_cast' that do not have, and we do not want to have a Vtbl (for example Slang::IRInst). +* There are types which a 'dynamic_cast' doesn't do quite what we want (for example casting on Type* derived types typically wants to work on their canonical type) +* We may want to replace use of dynamic_cast in the future for speed/space or other reasons +* It is common in the code base when using a 'smart pointer' type to cast it, but still return a smart pointer + +To deal with these issues we need casting within Slang to follow it's own methodology. In summary it is as follows... + +* Use 'as' free function to do a typical 'dynamic like' cast. + * 'as' doesn't guarantee the returned pointer points to the same object. + * For example with Type* it *actually* does the cast on the canonical type which is often a different object. +* If you want to *literally* do a dynamic cast use 'dynamicCast' free function. + * This guarantees the returned pointer points to the same object (like normal dynamic_cast) +* If you want to return a smart pointer from a cast from a smart pointer use the .as or .dynamicCast *methods* +* If you want to determine if an 'as' cast is possible on a smart pointer use the .is method + * Doing so will produce more efficient code because a new smart pointer does not need to be constructed + +These functions will also work with types that do not have Vtbl - like IRInst derived types. + +Both 'as' and 'dynamicCast' handle the case if the pointer is a nullptr, by returning a nullptr. If the cast succeeds the cast pointer is returned otherwise nullptr is returned. If a cast is performed with a free function it always returns a raw pointer. + +So why have 'as' and 'dynamicCast' - they seem sort of similar? The primary difference is dynamicCast *must* always return a pointer to the same object, whilst 'as' *can* return a pointer to a different object if that is the desired 'normal' casting behavior for the type. This is the case for Type* when using 'as' it may return a different object - the 'canonical type' for the Type*. For a concrete example take 'NamedExpressionType', its canonical type is the type the name relates to. If you use 'as' on it - it will produce a pointer to a different object, an object that will not be castable back into a NamedExpressionType. + +Also keep in mind that 'as' behavior is based on the pointer type being cast from. For any pointer to a type derived from Type it will cast the canonical type. **BUT** if the pointer is pointing to a Type derived *object*, but the pointer type is *not* derived from Type (like say RefObject*), then 'as' will behave like dynamicCast. + +All this being said 'as' in usage is seen as the 'default' way to do a 'dynamic like' cast with these special behaviour appropriate for the type when necessary. + +By having the free function and method versions of 'as' and 'dynamicCast', you can choose if you want a 'raw' or 'smart' pointer type returned from the cast. If you just want to test if something is a certain type, then using as/dynamicCast free functions is the faster way to do it. If you *know* that a raw pointer is ok, because the object will remain in scope, then again using the free function is better because it does less work. But as the examples following show, care is needed because if you get it wrong the object might go out of scope and leave the raw pointer pointing to a deleted object. When in doubt the safe choice is to typically use .as (or .dynamicCast if appropriate) methods. + +Following example shows the different types of casting... + +```C++ + +void someFunction(Decl* decl, Type* type) +{ + RefPtr declRefPtr(decl); + RefPtr typeRefPtr(type); + + // Use of as + { + // Casting with as on a free function returns a raw pointer + GenericDecl* genericDeclRaw0 = as(decl); + // Free function again returns a raw pointer + GenericDecl* genericDeclRaw1 = as(declRefPtr); + + // Using the as *method* returns a smart pointer holding the cast result + RefPtr genericDeclRefPtr0 = declRefPtr.as(); + + // Of course you can use auto with either + auto genericDeclRefPtr1 = declRefPtr.as(); + + auto genericDeclRaw2 = as(declRefPtr); + } + + // Currently using as on anything not cast *from* Type is the same as dynamicCast. + // But on Type* sometimes you may want to control the cast + { + // With a NamedExpressionType sometimes you don't want 'as' behaviour - if we want to see the information about the name (not the thing + // it relates to (the canonical type) + NamedExpressionType* namedExpressionRawPtr = dynamicCast(type); + + + // Returns the smart pointer + auto namedExpressionRefPtr = typeRefPtr.as(); + } + +``` + +It is important to be aware of what style of cast you use where. Take for example the following function ... +```C++ + RefPtr substitute(RefPtr expr) const + { + return DeclRefBase::Substitute(expr); + } +``` + +If you want to do a cast on it, you need to be careful especially about scope, for example... + +```C++ + RefPtr expr = ...; + + { + // Whoops! This is a problem. When using the free function, the cast is to a *raw* pointer, so obj + // receives a raw pointer. When the RefPtr returned from Substitute goes out of scope (when the statement is left) + // the ref will be removed and if the ref count was 1 destroyed. Now obj points to a freed object and so a crash is + // likely to follow in the future! + + auto obj = as(substitute(expr)); + } + // So how do we avoid this? Well it depends what the function is returning and the scope. If it's returning a smart pointer, + // you could use the .as method + { + // This can only compile if it is a smart pointer (raw pointers don't have an as method) + auto obj = substitute(expr).as(); + } + + // Another option is to put the created thing in a smart pointer so you know it's in scope + { + RefPtr sub = substitute(expr); + // Ok as long as sub is in scope + auto obj = as(sub); + + } + + // More awkwardly you could use free function, but assign to a smart pointer, thus maintaining scope + { + RefPtr obj = as(substitute(expr)); + } + +``` + +The following code shows the change in behavior of 'as' is based on the source *pointer* type **NOT** the *object* type.. + +```C++ + // Derives from Type + NamedExpressionType* exprType = ...; + + + // Will be the Type* of the *canonical* type, because the pointer is Type derived and we are using as! + Type* type0 = as(exprType); + // It' going to be pointing to a different object, because type0 is the cast of the *canonical* type, because exprType derives from Type + SLANG_ASSERT(type0 != exprType); + + // If I do a dynamicCast the result is either nullptr or a pointer that *must* point to the same object + Type* type1 = dynamicCast(exprType); + SLANG_ASSERT(type1 == exprType); + + + // Here, the pointer is pointing to a NamedExpressionType derived object. Which derives from Type. BUT our pointer here does *not* derive from type. + RefObject* refObj = exprType; + + // 'as' just looks at the from type, and it doesn't derive from Type (it's just RefObject), so it does regular as, which is dynamicCast + Type* type2 = as(refObject); + + SLANG_ASSERT(type2 == exprType); + + // Finally... + + // Is true even though exprType is a NamedExpression, because the cast is on the canonical type + SLANG_ASSERT(as(exprType) == nullptr); + + // dynamicCast is always the same object returned, so must match + SLANG_ASSERT(dynamicCast(exprType) == exprType); +``` diff --git a/lib/All/slang/share/doc/slang/design/coding-conventions.md b/lib/All/slang/share/doc/slang/design/coding-conventions.md new file mode 100644 index 0000000..bc54078 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/coding-conventions.md @@ -0,0 +1,282 @@ +Slang Project Coding Conventions +================================ + +Principles +---------- + +This document attempts to establish conventions to be used in the Slang codebase. +We have two goals for this convention. + +The first goal is to make the code look relatively consistent so that it is easy to navigate and understand for contributors. +Having varying styles across different modules, files, functions, or lines of code makes the overall design and intention of the codebase harder to follow. + +The second goal is to minimize the scope complexity of diffs when multiple maintainers work together on the codebase. +In the absence of an enforced style, developers tend to "clean up" code they encounter to match their personal preferences, and in so doing create additional diffs that increase the chances of merge conflicts and pain down the line. + +Because the Slang codebase has passed through many hands and evolved without a pre-existing convention, these two goals can come into conflict. +We encourage developers to err on the side of leaving well enough alone (favoring the second goal). +Don't rewrite or refactor code to match these conventions unless you were already going to have to touch all of those lines of code anyway. + +Note that external code that is incorporated into the project is excluded from all of these conventions. + +Languages +--------- + +### C++ + +Most code in the Slang project is implemented in C++. +We currently assume support for some C++11 idioms, but have explicitly avoided adding dependencies on later versions. + +As a general rule, be skeptical of "modern C++" ideas unless they are clearly better to simpler alternatives. +We are not quite in the realm of "Orthodox C++", but some of the same guidelines apply: + +* Don't use exceptions for non-fatal errors (and even then support a build flag to opt out of exceptions) +* Don't use the built-in C++ RTTI system (home-grown is okay) +* Don't use the C++ variants of C headers (e.g., `` instead of ``) +* Don't use the STL containers +* Don't use iostreams + +The compiler implementation does not follow some of these guidelines at present; that should not be taken as an excuse to further the proliferation of stuff like `dynamic_cast`. +Do as we say, not as we do. + +Some relatively recent C++ features that are okay to use: + +* Rvalue references for "move semantics," but only if you are implementing performance-critical containers or other code where this really matters. + +* `auto` on local variables, if the expected type is clear in context + +* Lambdas are allowed, but think carefully about whether just declaring a subroutine would also work. + +* Using `>>` to close multiple levels of templates, instead of `> >` (but did you really need all those templates?) + +* `nullptr` + +* `enum class` + +* Range-based `for` loops + +* `override` + +* Default member initializers in `class`/`struct` bodies + +Templates are suitable in cases where they improve clarity and type safety. +As a general rule, it is best when templated code is kept minimal, and forwards to a non-templated function that does the real work, to avoid code bloat. + +Any use of template metaprogramming would need to prove itself exceptionally useful to pay for the increase in cognitive complexity. +We don't want to be in the business of maintaining "clever" code. + +As a general rule, `const` should be used sparingly and only with things that are logically "value types." +If you find yourself having to `const`-qualify a lot of member function in type that you expect to be used as a heap-allocated object, then something has probably gone wrong. + +As a general rule, default to making the implementation of a type `public`, and only encapsulate state or operations with `private` when you find that there are complex semantics or invariants that can't be provided without a heavier hand. + +### Slang + +The Slang project codebase also includes `.slang` files implementing the Slang core module, as well as various test cases and examples. +The conventions described here are thus the "official" recommendations for how users should format Slang code. + +To the extent possible, we will try to apply the same basic conventions to both C++ and Slang. +In places where we decide that the two languages merit different rules, we will point it out. + +Files and Includes +------------------ + +### File Names + +All files and directories that are added to codebase should have names that contain only ASCII lower-case letters, digits, dots (`.`) and dashes (`-`). +Operating systems still vary greatly in their handling of case sensitivity for file names, and non-ASCII code points are handled with even less consistency; sticking to a restricted subset of ASCII helps avoids some messy interactions between case-insensitive file systems and case-sensitive source-control systems like Git. +As with all these conventions, files from external projects are exempted from these restrictions. + +### Naming of Source and Header Files + +In general the C++ codebase should be organized around logical features/modules/subsystem, each of which has a single `.h` file and zero or more `.cpp` files to implement it. + +If there is a single `.cpp` file, its name should match the header: e.g., `parser.h` and `parser.cpp`. + +If there is more than one `.cpp` file, their names should start with the header name: e.g., `parser.h` and `parser-decls.cpp` and `parser-exprs.cpp`. +If there are declarations that need to be shared by the `.cpp` files, but shouldn't appear in the public interface, then can go in a `*-impl.h` header (e.g., `parser-impl.h`). + +Use best judgement when deciding what counts as a "feature." One class per file is almost always overkill, but the codebase currently leans too far in the other direction, with some oversized source files. + +### Headers + +Every header file should have an include guard. +Within the implementation we can use `#pragma once`, but exported API headers (`slang.h`) should use traditional `#ifdef` style guards (and they should be consumable as both C and C++). + +A header should include or forward-declare everything it needs in order to compile. +It is *not* up to the programmer who `#include`s a header to sort out the dependencies. + +Avoid umbrella or "catch-all" headers. + +### Source Files + +Every source file should start by including the header for its feature/module, before any other includes (this helps ensure that the header correctly includes its dependencies). + +Functions that are only needed within that one source file can be marked `static`, but we should avoid using the same name for functions in different files (in order to support lumped/unified builds). + +### Includes + +In general, includes should be grouped as follows: + +* First, the correspodning feature/module header, if we are in a source file +* Next, any `<>`-enlosed includes for system/OS headers +* Next, any `""`-enclosed includes for external/third-part code that is stored in the project repository +* Finally, any includes for other features in the project + +Within each group, includes should be sorted alphabetically. +If this breaks because of ordering issues for system/OS/third-party headers (e.g., `` must be included before ``), then ideally those includes should be mediated by a Slang-project-internal header that features can include. + +Namespaces +---------- + +Favor fewer namespaces when possible. +Small programs may not need any. + +All standard module code that a Slang user might link against should go in the `Slang` namespace for now, to avoid any possibility of clashes in a static linking scenario. +The public C API is obviously an exception to this. + + +Code Formatting +------------------------------ + +- For C++ files, please format using `clang-format`; `.clang-format` files in + the source tree define the style. +- For CMake files, please format using `gersemi` +- For shell scripts, please format using `shfmt` +- For YAML files, please use `prettier` + +The formatting for the codebase is overall specified by the +[`extras/formatting.sh`](./extras/formatting.sh) script. + +If you open a pull request and the formatting is incorrect, you can comment +`/format` and a bot will format your code for you. + +Naming +------ + +### Casing + +Types should in general use `UpperCamelCase`. This includes `struct`s, `class`es, `enum`s and `typedef`s. + +Values should in general use `lowerCamelCase`. This includes functions, methods, local variables, global variables, parameters, fields, etc. + +Macros should in general use `SCREAMING_SNAKE_CASE`. +It is important to prefix all macros (e.g., with `SLANG_`) to avoid collisions, since `namespace`s don't affect macros). + +In names using camel case, acronyms and initialisms should appear eniterly in either upper or lower case (e.g., `D3DThing d3dThing`) and not be capitalized as if they were ordinary words (e.g., `D3dThing d3dThing`). +Note that this also applies to uses of "ID" as an abbreviation for "identifier" (e.g., use `nodeID` instead of `nodeId`). + +### Prefixes + +Prefixes based on types (e.g., `p` for pointers) should never be used. + +Global variables should have a `g` prefix, e.g. `gCounter`. +Non-`const` `static` class members can have an `s` prefix if that suits your fancy. +Of course, both of these should be avoided, so this shouldn't come up often. + +Constant data (in the sense of `static const`) should have a `k` prefix. + +In contexts where "information hiding" is relevant/important, such as when a type has both `public` and `private` members, or just has certain operations/fields that are considered "implementation details" that most clients should not be using, an `m_` prefix on member variables and a `_` prefix on member functions is allowed (but not required). + +In function parameter lists, an `in`, `out`, or `io` prefix can be added to a parameter name to indicate whether a pointer/reference/buffer is intended to be used for input, output, or both input and output. +For example: + +```c++ +void copyData(void* outBuffer, void const* inBuffer, size_t size); + +Result lookupThing(Key k, Thing& outThing); + +void maybeAppendExtraNames(std::vector& ioNames); +``` + +Public C APIs will prefix all symbol names while following the casing convention (e.g. `SlangModule`, `slangLoadModule`, etc.). + +### Enums + +C-style `enum` should use the following convention: + +```c++ +enum Color +{ + kColor_Red, + kColor_Green, + kColor_Blue, + + kColorCount, +}; +``` + +When using `enum class`, drop the `k` and type name as prefix, but retain the `UpperCamelCase` tag names: + +```c++ +enum class Color +{ + Red, + Green, + Blue, + + Count, +}; +``` + +When defining a set of flags, separate the type definition from the `enum`: + +```c++ +typedef unsigned int Axes; +enum +{ + kAxes_None = 0, + + kAxis_X = 1 << 0, + kAxis_Y = 1 << 1, + kAxis_Z = 1 << 2, + + kAxes_All = kAxis_X | kAxis_Y | kAxis_Z, +}; +``` + +Note that the type name reflects the plural case, while the cases that represent individual bits are named with a singular prefix. + +In public APIs, all `enum`s should use the style of separating the type definition from the `enum`, and all cases should use `SCREAMING_SNAKE_CASE`: + +```c++ +typedef unsigned int SlangAxes; +enum +{ + SLANG_AXES_NONE = 0, + + SLANG_AXIS_X = 1 << 0, + SLANG_AXIS_Y = 1 << 1, + SLANG_AXIS_Z = 1 << 2, + + SLANG_AXES_ALL = SLANG_AXIS_X | SLANG_AXIS_Y | SLANG_AXIS_Z, +}; +``` + +### General + +Names should default to the English language and US spellings, to match the dominant conventions of contemporary open-source projects. + +Function names should either be named with action verbs (`get`, `set`, `create`, `emit`, `parse`, etc.) or read as questions (`isEnabled`, `shouldEmit`, etc.). + +Whenever possible, compiler concepts should be named using the most widely-understood term available: e.g., we use `Token` over `Lexeme`, and `Lexer` over `Scanner` simply because they appear to be the more common names. + +Avoid abbreviations and initialisms unless they are already widely established across the codebase; a longer name may be cumbersome to write in the moment, but the code will probably be read many more times than it is written, so clarity should be preferred. +An important exception to this is common compiler concepts or techniques which may have laboriously long names: e.g., Static Single Assignment (SSA), Sparse Conditional Copy Propagation (SCCP), etc. + +One gotcha particular to compiler front-ends is that almost every synonym for "type" has some kind of established technical meaning; most notably the term "kind" has a precise meaning that is relevant in our domain. +It is common practice in C and C++ to define tagged union types with a selector field called a "type" or "kind," which does not usually match this technical definition. +If a developer wants to avoid confusion, they are encouraged to use the term "flavor" instead of "type" or "kind" since this term (while a bit silly) is less commonly used in the literature. + +Comments and Documentation +-------------------------- + +You probably know the drill: comments are good, but an out-of-date comment can be worse than no comment at all. +Try to write comments that explain the "why" of your code more than the "what." +When implementing a textbook algorithm or technique, it may help to imagine giving the reviewer of your code a brief tutorial on the topic. + +In cases where comments would benefit from formatting, use Markdown syntax. +We do not currently have a setup for extracting documentation from comments, but if we add one we will ensure that it works with Markdown. + +When writing comments, please be aware that your words could be read by many people, from a variety of cultures and backgrounds. +Default to a plain-spoken and professional tone and avoid using slang, idiom, profanity, etc. diff --git a/lib/All/slang/share/doc/slang/design/decl-refs.md b/lib/All/slang/share/doc/slang/design/decl-refs.md new file mode 100644 index 0000000..5c19586 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/decl-refs.md @@ -0,0 +1,166 @@ +Understanding Declaration References (Out of Date) +==================================== + +This document is intended as a reference for developers working on the Slang compiler implementation. + +As you work on the code, you'll probably notice a lot of places where we use the `DeclRef` type: + +* Expressions like `VarExpr` and `MemberExpr` are subclasses of `DeclRefExpr`, which holds a `DeclRef`. + +* The most common subclass of `Type` is `DeclRefType`, which holds a `DeclRef` for the type declaration. + +* Named types (references to `typedef`s) hold a `DeclRef` + +* The name lookup process relies a lot on `DeclRef` + +So what in the world is a `DeclRef`? + +The short answer is that a `DeclRef` packages up two things: + +1. A pointer to a `Decl` in the parsed program AST + +2. A set of "substitutions" to be applied to that decl + +Why do we need `DeclRef`s? +-------------------------- + +In a compiler for a simple language, we might represent a reference to a declaration as simply a pointer to the AST node for the declaration, or some kind of handle/ID that references that AST node. +A representation like that will work in simple cases, for example: + +```hlsl +struct Cell { int value }; + +Cell a = { 3 }; +int b = a.value + 4; +``` + +In this case, the expression node for `a.value` can directly reference the declaration of the field `Cell::value`, and from that we can conclude that the type of the field (and hence the expression) is `int`. + +In contrast, things get more complicated as soon as we have a language with generics: + +```hlsl +struct Cell { T value; }; + +// ... + +Cell a = { 3 }; +int b = a.value + 4; +``` + +In this case, if we try to have the expression `a.value` only reference `Cell::value`, then the best we can do is conclude that the field has type `T`. + +In order to correctly type the `a.value` expression, we need enough additional context to know that it references `Cell::value`, and from that to be able to conclude that a reference to `T` in that context is equivalent to `int`. + +We can represent that information as a substitution which maps `T` to `int`: + +``` +[ Cell::T => int ] +``` + +Then we can encode a reference to `Cell::value` as a reference to the single declaration `Cell::value` with such a substitution applied: + +``` +Cell::value [Cell::T => int] +``` + +If we then want to query the type of this field, we can first look up the type stored on the AST (which will be a reference to `Cell::T`) and apply the substitutions from our field reference to get: + +``` +Cell::T [Cell::T => int] +``` + +Of course, we can then simplify the reference by applying the substitutions, to get: + +``` +int +``` + +How is this implemented? +------------------------ + +At the highest level, a `DeclRef` consists of a pointer to a declaration (a `Decl*`) plus a single-linked list of `Substution`s. +These substitutions fill in the missing information for any declarations on the ancestor chain for the declaration. + +Each ancestor of a declaration can introduce an expected substitution along the chain: + +* Most declarations don't introduce any substitutions: e.g., when referencing a non-generic `struct` we don't need any addition information. + +* A surrounding generic declaration requires a `GenericSubstitution` which specifies the type argument to be plugged in for each type parameter of the declaration. + +* A surrounding `interface` declaration usually requires a `ThisTypeSubstitution` that identifies the specific type on which an interface member has been looked up. + +All of the expected substitutions should be in place in the general case, even when we might not have additional information. E.g., within a generic declaration like this: + +```hlsl +struct Cell +{ + void a(); + void b() { a(); } +} +``` + +The reference to `a` in the body of `b` will be represented as a declaration reference to `Cell::a` with a substitution that maps `[Cell::T => Cell::T]`. This might seem superfluous, but it makes it clear that we are "applying" the generic to arguments (even if they are in some sense placeholder arguments), and not trying to refer to an unspecialized generic. + +There are a few places in the compiler where we might currently bend these rules, but experience has shown that failing to include appropriate substitutions is more often than not a source of bugs. + +What in the world is a "this type" substitution? +------------------------------------------------ + +When using interface-constrained generics, we need a way to invoke methods of the interface on instances of a generic parameter type. +For example, consider this code: + +```hlsl +interface IVehicle +{ + associatedtype Driver; + Driver getDriver(); +} + +void ticketDriver(V vehicle) +{ + V.Driver driver = vehicle.getDriver(); + sentTicketTo(driver); +} +``` + +In the expression `vehicle.getDriver`, we are referencing the declaration of `IVehicle::getDriver`, and so a naive reading tells us that the return type of the call is `IVehicle.Driver`, but that is an associated type and not a concrete type. It is clear in context that the expression `vehicle.getDriver()` should result in a `V.Driver`. + +The way the compiler encodes that is that we treat the expression `v.getDriver` as first "up-casting" the value `v` (of type `V`) to the interface `IVehicle`. We know this is valid because of the generic constraint `V : IVehicle`. The result of the up-cast operation is an expression with a type that references `IVehicle`, but with a substitution to track the fact that the underlying implementation type is `V`. This amounts to something like: + +``` +IVehicle [IVehicle.This => V] +``` + +where `IVehicle.This` is a way to refer to "the concrete type that is implementing `IVehicle`". + +Looking up the `getDriver` method on this up-cast expression yields a reference to: + +``` +IVehicle::getDriver [IVehicle.This => V] +``` + +And extracting the return type of that method gives us a reference to the type: + +``` +IVehicle::Driver [IVehicle.This => V] +``` + +which turns out to be exactly what the front end produces when it evaluates the type reference `V.Driver`. + +As this example shows, a "this type" substitution allows us to refer to interface members while retaining knowledge of the specific type on which those members were looked up, so that we can compute correct references to things like associated types. + +What does any of this mean for me? +---------------------------------- + +When working in the Slang compiler code, try to be aware of whether you should be working with a plain `Decl*` or a full `DeclRef`. +There are many queries like "what is the return type of this function?" that typically only make sense if you are applying them to a `DeclRef`. + +The `syntax.h` file defines helpers for most of the existing declaration AST nodes for querying properties that should represent substitutions (the type of a variable, the return type of a function, etc.). +If you are writing code that is working with a `DeclRef`, try to use these accessors and avoid being tempted to extract the bare declaration and start querying it. + +Some things like `Modifier`s aren't (currently) affected by substitutions, so it can make sense to query them on a bare declaration instead of a `DeclRef`. + +Conclusion +---------- + +Working with `DeclRef`s can be a bit obtuse at first, but they are the most elegant solution we've found to the problems that arise when dealing with generics and interfaces in the compiler front-end. Hopefully this document gives you enough context to see why they are important, and hints at how their representation in the compiler helps us implement some cases that would be tricky otherwise. diff --git a/lib/All/slang/share/doc/slang/design/existential-types.md b/lib/All/slang/share/doc/slang/design/existential-types.md new file mode 100644 index 0000000..0f34690 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/existential-types.md @@ -0,0 +1,252 @@ +Existential Types +================= + +This document attempts to provide some background on "existential types" as they pertain to the design and implementation of Slang. +The features described here are *not* reflected in the current implementation, so this is mostly a sketch of where we can go with the language and compiler. + +Background: Generics and Universal Quantification +------------------------------------------------- + +Currently Slang supports using interfaces as generic constraints. Let's use a contrived example: + +```hlsl +interface IImage { float4 getValue(float2 uv); } + +float4 offsetImage(T image, float2 uv) +{ + float2 offset = ...; + return image.getValue(uv + offset) +} +``` + +Generics like this are a form of "universal quantification" in the terminology of type theory. +This makes sense, because *for all* types `T` that satisfy the constraints, `offsetImage` provides an implementation of its functionality. + +When we think of translating `offsetImage` to code, we might at first only think about how we can specialize it once we have a particular type `T` in mind. +However, we can also imagine trying to generate one body of code that can implement `offsetImage` for *any* type `T`, given some kind of runtime representation of types. +For example, we might generate C++ code like: + +```c++ +struct IImageWitnessTable { float4 (*getValue)(void* obj, float2 uv); }; + +float4 offsetImage(Type* T, IImageWitnessTable* W, void* image, float2 uv) +{ + float2 offset = ...; + return W->getvalue(image, uv + offset); +} +``` + +This translation takes the generic parameters and turns them into ordinary runtime parameters: the type `T` becomes a pointer to a run-time type representation, while the constraint that `T : IImage` becomes a "witness table" of function pointers that, we assume, implements the `IImage` interface for `T`. So, the syntax of generics is *not* tied to static specialization, and can admit a purely runtime implementation as well. + +Readers who are familiar with how languages like C++ are implemented might see the "witness table" above and realize that it is kind of like a virtual function table, just being passed alongside the object, rather than stored in its first word. + +Using Interfaces Like Types +--------------------------- + +It is natural for a user to want to write code like the following: + +```hlsl +float4 modulateImage(IImage image, float2 uv) +{ + float4 factor = ...; + return factor * image.getValue(uv); +} +``` + +Unlike `offsetImage`, `modulateImage` is trying to use the `IImage` interface as a *type* and not just a constraint. + +This code appears to be asking for a dynamic implementation rather than specialization (we'll get back to that...) and so we should be able to implement it similarly to our translation of `offsetImage` to C++. +Something like the following makes a lot of sense: + +```c++ +struct IImage { Type* T; IImageWitnessTable* W; void* obj; }; + +float4 modulateImage(IImage image, float2 uv) +{ + float4 factor = ...; + return factor * image.W->getvalue(image.obj, uv); +} +``` + +Similar to the earlier example, there is a one-to-one mapping of the parameters of the Slang function the user wrote to the parameters of the generated C++ function. +To make this work, we had to bundle up the information that used to be separate parameters to the generic as a single value of type `IImage`. + +Existential Types +----------------- + +It turns out that when we use `IImage` as a type, it is what we'd call an *existential* type. +That is because if I give you a value `img` of type `IImage` in our C++ model, then you know that *there exists* some type `img.T`, a witness table `img.W` proving the type implements `IImage`, and a value `img.obj` of that type. + +Existential types are the bread and butter of object-oriented programming. +If I give you an `ID3D11Texture2D*` you don't know what its concrete type is, and you just trust me that some concrete type *exists* and that it implements the interface. +A C++ class or COM component can implement an existential type, with the constraint that the interfaces that a given type can support is limited by the way that virtual function tables are intrusively included inside the memory of the object, rather than externalized. +Many modern languages (e.g., Go) support adapting existing types to new interfaces, so that a "pointer" of interface type is actually a fat pointer: one for the object, and one for the interface dispatch table. +Our examples so far have assumed that the type `T` needs to be passed around separately from the witness table `W`, but that isn't strictly required in some implementations. + +In type theory, the most important operation you can do with an existential type is to "open" it, which means to have a limited scope in which you can refer to the constituent pieces of a "bundled up" value of a type like `IImage`. +We could imagine "opening" an existential as something like: + +``` +void doSomethingCool(T val); + +void myFunc(IImage img) +{ + open img as obj:T in + { + // In this scope we know that `T` is a type conforming to `IImage`, + // and `obj` is a value of type `T`. + // + doSomethingCool(obj); + } +} +``` + +Self-Conformance +---------------- + +The above code with `doSomethingCool` and `myFunc` invites a much simpler solution: + +``` +void doSomethingCool(T val); + +void myFunc(IImage img) +{ + doSomethingCool(img); +} +``` + +This seems like an appealing thing for a language to support, but there are some subtle reasons why this isn't possible to support in general. +If we think about what `doSomethingCool(img)` is asking for, it seems to be trying to invoke the function `doSomethingCool`. +That function only accepts type parameters that implement the `IImage` interface, so we have to ask ourselves: + +Does the (existential) type `IImage` implement the `IImage` interface? + +Knowing the implementation strategy outline above, we can re-phrase this question to: can we construct a witness table that implements the `IImage` interface for values of type `IImage`? + +For simple interfaces this is sometimes possible, but in the general case there are other desirable language features that get in the way: + +* When an interface has associated types, there is no type that can be chosen as the associated type for the interface's existential type. The "obvious" approach of using the constraints on the associated type can lead to unsound logic when interface methods take associated types as parameters. + +* When an interface uses the "this type" (e.g., an `IComparable` interface with a `compareTo(ThisType other)` method), it isn't correct to simplify the this type to the interface type (just because you have two `IComarable` values doesn't mean you can compare them - they have to be of the same concrete type!) + +* If we allow for `static` method on interfaces, then what implementation would we use for these methods on the interface's existential type? + +Encoding Existentials in the IR +------------------------------- + +Existentials are encoded in the Slang IR quite simply. We have an operation `makeExistential(T, obj, W)` that takes a type `T`, a value `obj` that must have type `T`, and a witness table `W` that shows how `T` conforms to some interface `I`. The result of the `makeExistential` operation is then a value of the type `I`. + +Rather than include an IR operation to "open" an existential, we can instead just provide accessors for the pieces of information in an existential: one to extract the type field, one to extract the value, and one to extract the witness table. These would idiomatically be used like: + +``` +let e : ISomeInterface = /* some existential */ +let T : Type = extractExistentialType(e); +let W : WitnessTbale = extractExistentialWitnessTable(e); +let obj : T = extractExistentialValue(e); +``` + +Note how the operation to extract `obj` gets its result type from the previously-executed extraction of the type. + +Simplifying Code Using Existentials +----------------------------------- + +It might seem like IR code generated using existentials can only be implemented using dynamic dispatch. +However, within a local scope it is clear that we can simplify expressions whenever `makeExistential` and `extractExistential*` operations are paired. +For example: + +``` +let e : ISomeInterface = makeExistential(A, a, X); +... +let B = extractExistentialType(e); +let b : B = extractExistentialValue(e); +let Y = extractExistentialWitnessTable(e); +``` + +It should be clear in context that we can replace `B` with `A`, `b` with `a`, and `Y` with `X`, after which all of the `extract*` operations and the `makeExistential` operation are dead and can be eliminated. + +This kind of simplification works within a single function, as long as there is no conditional logic involving existentials. +We require further transformation passes to allow specialization in more general cases: + +* Copy propagation, redundancy elimination and other dataflow optimizations are needed to simplify use of existentials within functions +* Type legalization passes, including some amount of scalarization, are needed to "expose" existential-type fields that are otherwise buried in a type +* Function specialization, is needed so that a function with existential parameters is specialized based on the actual types used at call sites + +Transformations just like these are already required when working with resource types (textures/samplers) on targets that don't support first-class computation on resources, so it is possible to share some of the same logic. +Similarly, any effort we put into validation (to ensure that code is written in a way that *can* be simplified) can hopefully be shared between existentials and resources. + +Compositions +------------ + +So far I've only talked about existential types based on a single interface, but if you look at the encoding as a tuple `(obj, T, W)` there is no real reason that can't be generalized to hold multiple witness tables: `(obj, T, W0, ... WN)`. Interface compositions could be expressed at the language level using the `&` operator on interface (or existential) types. + +The IR encoding doesn't need to change much to support compositions: we just need to allow multiple witness tables on `makeExistential` and have an index operand on `extractExistentialWitnessTable` to get at the right one. + +The hardest part of supporting composition of interfaces is actually in how to linearize the set of interfaces in a way that is stable, so that changing a function from using `IA & IB` to `IB & IA` doesn't change the order in which witness tables get packed into an existential value. + +Why are we passing along the type? +---------------------------------- + +I'm glossing over something pretty significant here, which is why anybody would pass around the type as part of the existential value, when none of our examples so far have made use of it. +This sort of thing isn't very important for languages where interface polymorphism is limited to heap-allocated "reference" types (or values that have been "boxed" into reference types), because the dynamic type of an object can almost always be read out of the object itself. + +When dealing with a value type, though, we have to deal with things like making *copies*: + +``` +interface IWritable { [mutating] void write(int val); } + +struct Cell : IWritable { int data; void write(int val) { data = val; } } + +T copyAndClobber(T obj) +{ + T copy = obj; + obj.write(9999); + return copy; +} + +void test() +{ + Cell cell = { 0 }; + Cell result = copyAndClobber(cell); + // what is in `result.data`? +} +``` + +If we call `copyAndClober` on a `Cell` value, then does the line `obj.write` overwrite the data in the explicit `copy` that was made? +It seems clear that a user would expect `copy` to be unaffected in the case where `T` is a value type. + +How does that get implemented in our runtime version of things? Let's imagine some C++ translation: + +``` +void copyAndClobber(Type* T, IWriteableWitnessTable* W, void* obj, void* _returnVal) +{ + void* copy = alloca(T->sizeInBytes); + T->copyConstruct(copy, obj); + + W->write(obj, 9999); + T->moveConstruct(_returnVal, copy); +} +``` + +Because this function returns a value of type `T` and we don't know how big that is, let's assume the caller is passing in a pointer to the storage where we should write the result. +Now, in order to have a local `copy` of the `obj` value that was passed in, we need to allocate some scratch storage, and only the type `T` can know how many bytes we need. +Furthermore, when copying `obj` into that storage, or subsequently copying the `copy` variable into the function result, we need the copy/move semantics of type `T` to be provided by somebody. + +This is the reason for passing through the type `T` as part of an existential value. + +If we only wanted to deal with reference types, this would all be greatly simplified, because the `sizeInBytes` and the copy/move semantics would be fixed: everything is a single pointer. + +All of the same issues arise if we're making copies of existential values: + +``` +IWritable copyAndClobberExistential(IWritable obj) +{ + IWritable copy = obj; + obj.write(9999); + return copy; +} +``` + +If we want to stay consistent and say that `copy` is an actual copy of `obj` when the underlying type is a value rather than a reference type, then we need the copy/move operations for `IWritable` to handle invoking the copy/move operations of the underlying encapsulated type. + +Aside: it should be clear from these examples that implementing generics and existential types with dynamic dispatch has a lot of complexity when we have to deal with value types (because copying requires memory allocation). +It is likely that a first implementation of dynamic dispatch support for Slang would restrict it to reference types (and would thus add a `class` keyword for defining reference types). diff --git a/lib/All/slang/share/doc/slang/design/experimental.md b/lib/All/slang/share/doc/slang/design/experimental.md new file mode 100644 index 0000000..c9a84ac --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/experimental.md @@ -0,0 +1,74 @@ +Deploying Experimental API Additions +==================================== + +This page intends to provide guidance to Slang developers when extending the Slang API, particularly when working on experimental features. +It applies to the "COM-lite" Slang API, rather than the deprecated C Slang API (sp* functions). + +* Note: This guidance relates to Slang API changes, not to language changes. That is, what Slang does with shader source code across releases is not discussed here. + +The goal is to maintain binary compatibility as much as possible between Slang releases, and to aid applications in dealing with changes to Slang. + +Slang is distributed as a dynamic library, and there is an expectation from Slang API users that upgrading by installing an updated slang-compiler.dll or slang-compiler.so will not break their application unnecessarily. + +ABI compatibility within the Slang API can be preserved between releases if some rules are followed by developers. + +Slang API uses a "COM-lite" structure wherein functionality is exposed through interfaces on objects. If the interfaces never change, ABI compatibility is preserved, but changes happen. When adding or changing interfaces, please observe the following: + +1. It is preferred to create *new* COM interfaces when adding new functionality. +* This maintains ABI compatibility. +* Applications must acquire access to the new functionality using QueryInterface(), which will gracefully fail if the slang-compiler.dll/libslang-compiler.so does not implement the functionality. + +2. Changes to existing virtual methods in COM interfaces should be avoided, as that is an ABI breakage. +* If a change is required though, change the interface's UUID. + +3. New virtual methods _may_ be added (only) to the end of existing COM interface structs. +* This does not disturb the ABI compatibility of the associated vtable. Old apps can remain unaware of the new function pointers appended to the end of the vtable. +* A UUID change is not necessary. +* Note that in the event that a Slang application which uses the added feature is run with an old slang-compiler.dll/libslang-compiler.so, the experience for the user is not as clean as if the added method belongs to a new interface. + +Adding Experimental Interfaces +============================== + +When the above recommendations cannot be followed, as with features that are expected to be iterated on or are regarded as temporary, there are additional recommendations. + +Interfaces that are expected to change must be marked `_Experimental` in their class name and in their UUID name. + +For example, + + +```csharp +/* Experimental interface for doing something cool. This interface is susceptible to ABI breakage. */ +struct ICoolNewFeature_Experimental : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0x8e12e8e3, 0x5fcd, 0x433e, { 0xaf, 0xcb, 0x13, 0xa0, 0x88, 0xbc, 0x5e, 0xe5 }) + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL coolMethod() = 0; +}; + +#define SLANG_UUID_ICoolNewFeature_Experimental ICoolNewFeature_Experimental::getTypeGuid() +``` + +Note: Use uuidgen to generate IIDs new interfaces. + +Removing Experimental Interfaces +================================ + +By the nature of being marked "Experimental", users have been warned that the interfaces are not officially supported and may be removed. You may simply delete the class and UUID, e.g. "ICoolNewFeature_Experimental" struct may be deleted from slang.h along with the definition of SLANG_UUID_ICoolNewFeature_Experimental. + +This will show up in applications as QueryInterface failures. + +It is nice, but not required, to retain the interface declarations for some time after removing internal support before deleting them from slang.h, so that applications have time to remove their dependence on the unsupported feature while still being able to compile in the interim. + +Changing Experimental Interfaces +================================ + +Backwards incompatible changes to Slang COM interfaces should be accompanied with a UUID change. + +In the event that an old application runs with a new slang library, applications are more capable of gracefully handling an unavailable interface than a changed one. The former may be still be functional, or include a helpful error message, whereas the latter is most likely a crash of some sort. + +Promoting Experimental Interfaces +================================= + +The class name and the UUID name should be changed in slang.h and in the slang source code, e.g. Rename "ICoolNewFeature_Experimental" to just "ICoolFeature". + +The SLANG_UUID for the interface should be renamed to omit "EXPERIMENTAL" but its value should remain the same. This is because, if there are no backwards incompatible changes that accompany the promotion from experimental to permanent, applications written against the experimental version can continue working against Slang libraries where the interface was promoted to permanent. diff --git a/lib/All/slang/share/doc/slang/design/interfaces.md b/lib/All/slang/share/doc/slang/design/interfaces.md new file mode 100644 index 0000000..4ce042c --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/interfaces.md @@ -0,0 +1,486 @@ +Interfaces Design +================= + +This document intends to lay out the proposed design for a few inter-related features in Slang: + +- Interfaces +- Associated Types +- Generics + +Introduction +------------ + +The basic problem here is not unique to shader programming: you want to write code that accomplished one task, while abstracting over how to accomplish another task. +As an example, we might want to write code to integrate incident radiance over a list of lights, while not concerning ourself with how to evaluate a reflectance function at each of those lights. + +If we were doing this task on a CPU, and performance wasn't critical, we could probably handle this with higher-order functions or an equivalent mechanism like function pointers: + + float4 integrateLighting( + Light[] lights, + float4 (*brdf)(float3 wi, float3 wi, void* userData), + void const* brdfUserData) + { + float4 result = 0; + for(/* ... */) { + // ... + result += brdf(wi, wo, brdfUserDat); + } + return result; + } + +Depending on the scenario, we might be able to generate statically specialized code by using templates instead: + + template + float4 integrateLighting(Light[] lights, BRDF const& brdf) + { + // ... + result += brdf(wi, wo); + // ... + } + +Current shading languages support neither higher-order functions nor templates/generics, so neither of these options is viable. +Instead practitioners typically use preprocessor techniques to either stich together the final code, or to substitute in different function/type definitions to make a definition like `integrateLighting` reusable. + +These ad hoc approaches actually work well in practice; we aren't proposing to replace them *just* to make code abstractly "cleaner." +Rather, we've found that the ad hoc approaches end up interacting poorly with the resource binding model in modern APIs, so that *something* less ad hoc is required to achieve our performance goals. +At that point, we might as well ensure that the mechanism we introduce is also a good fit for the problem. + +Overview +-------- + +The basic idea for our approach is as follows: + +- Start with the general *semantics* of a generic-based ("template") approach + +- Use the accumulated experience of the programming language community to ensure that our generics are humane (in other words: not like C++) + +- Expore the possibility of syntax sugar to let people use more traditional OOP-style syntax when it can reduce verbosity without harming understanding + +In general, our conceptual model is being ripped off wholesale from Rust and Swift. +The basic design principle is "when in doubt, do what Swift does." + +Interfaces +---------- + +An **interface** in Slang is akin to a `protocol` in Swift or a `trait` in Rust. +The choice of the `interface` keyword is to highlight the overlap with the conceptually similar construct that appeared in Cg, and then later in HLSL. + +### Declaring an interface + +An interface is a named collection of **requirements**; any type that **implements** the interface must provide definitions that satisfy those requirements. + +Here is a simple interface, with one requirement: + + interface Light + { + float3 illuminate(float3 P_world); + } + +The `Light` interface requires a (member) function called `illuminate` with the given signature. + +### Declaring that a type implementats an interface + +A user-defined `struct` type can declare that it implements an interface, by using conventional "inheritance" syntax: + + struct PointLight : Light + { + float3 P_light; + + float3 illuminate(float3 P_world) + { + float distance = length(P_light - P_world); + // ... + } + } + +It is a static error if a type declares that it implements an interface, but it does not provide all of the requirements: + + struct BadLight : Light + { + // ERROR: type 'BadLight' cannot implement 'Light' + // because it does not provide the required 'illuminate' function + } + +### Interface Inheritance + +While this document does not propose general notions of inheritance be added to Slang, it does make sense to allow an interface to inherit from zero or more other interfaces: + + interface InfinitessimalLight : Light + { + float3 getDirection(float3 P_world); + } + +In this case the `InfinitessimalLight` interface inherits from `Light`, and declares one new requirement. +In order to check that a type implements `InfinitessimalLight`, the compiler will need to check both that it implements `Light` and that it provides the new "direct" requirements in `InfinitessimalLight`. + +Declaring that a type implements an interface also implicitly declares that it implements all the interfaces that interface transitively inherits from: + + struct DirectionalLight : InfinitessimalLight + { + float3 L; + float3 dir; + + float3 getDirection(float3 P_world) { return dir; } + + float3 illuminate(float3 P_world) + { + // Okay, this is the point where I recognize + // that this function definition is not + // actually reasonable for a light... + } + + + +### Interfaces and Extensions + +It probably needs its own design document, but Slang currently has very basic support for `extension` declarations that can add members to an existing type. +These blocks correspond to `extension` blocks in Swift, or `impl` blocks in Rust. +This can be used to declare that a type implements an interface retroactively: + + extension PointLight : InfinitessimalLight + { + float3 getDirection(float3 P_world) + { + return normalize(P_light - P_world); + } + } + +In this case we've used an extension to declare the `PointLight` also implements `InfinitessimalLight`. For the extension to type-check we need to provide the new required function (the compiler must recognize that the implementation of `Light` was already provided by the original type definition). + +There are some subtleties around using extensions to add interface implementations: + +- If the type already provides a method that matches a requireemnt, can the extension "see" it to satisfying new requirements? + +- When can one extension "see" members (or interface implementations) added by another? + +A first implementation can probably ignore the issue of interface implementations added by extensions, and only support them directly on type definitions. + +Generics +-------- + +All of the above discussion around interfaces neglected to show how to actually *use* the fact that, e.g., `PointLight` implements the `Light` interface. +That is intentional, because at the most basic level, interfaces are designed to be used in the context of **generics**. + +### Generic Declarations + +The Slang compiler currently has some ad hoc support for generic declarations that it uses to implement the HLSL standard module (which has a few generic types). +The syntax for those is currently very bad, and it makes sense to converge on the style for generic declarations used by C# and Swift: + + float myGenericFunc(T someValue); + +Types can also be generic: + + struct MyStruct { float a; T b; } + +Ideally we should also allow interfaces and interface requirements to be generic, but there will probably be some limits due to implementation complexity. + +### Type Constraints + +Unlike C++, Slang needs to be able to type-check the body of a generic function ahead of time, so it can't rely on `T` having particular members: + + // This generic is okay, because it doesn't assume anything about `T` + // (other than the fact that it can be passed as input/output) + T okayGeneric(T a) { return a; } + + // This generic is not okay, because it assumes that `T` supports + // certain operators, and we have no way of knowing it this is true: + T notOkayGeneric(T a) { return a + a; } + +In order to rely on non-trivial operations in a generic parameter type like `T`, the user must **constrain** the type parameter using an interface: + + float3 mySurfaceShader(L aLight) + { + return aLight.illuminate(...); + } + +In this example, we have constrained the type parameter `L` so that it must implement the interface `Light`. +As a result, in the body of the function, the compiler can recognize that `aLight`, which is of type `L`, must implement `Light` and thus have a member `illuminate`. + +When calling a function with a constrained type parameter, the compiler must check that the actual type argument (whether provided explicitly or inferred) implements the interface given in the constraint: + + mySurfaceShader(myPointLight); // OK + mySurfaceShader(myPointLight); // equivalent to previous + mySurfaceShader(3.0f); // ERROR: `float` does not implement `Light` + +Note that in the erroneous case, the error is reported at the call site, rather than in the body of the callee (as it would be for C++ templates). + +For cases where we must constrain a type parameter to implement multiple interfaces, we can join the interface types with `&`: + + interface Foo { void foo(); } + interface Bar { void bar(); } + + void myFunc(T val) + { + val.foo(); + val.bar(); + } + +If we end up with very complicated type constraints, then it makes sense to support a "`where` clause" that allows requirements to be stated outside of the generic parameter list: + + void myFunc(T val) + where T : Foo, + T : Bar + {} + +Bot the use of `&` and `where` are advanced features that we might cut due to implementation complexity. + +### Value Parameters + +Because HLSL has generics like `vector` that already take non-type parameters, the language will need *some* degree of support for generic parameters that aren't types (at least integers need to be supported). +We need syntax for this that doesn't bloat the common case. + +In this case, I think that what I've used in the current Slang implementation is reasonable, where a value parameter needs a `let` prefix: + + void someFunc< + T, // type parameter + T : X, // type parameter with constraint + T = Y, // type parameter with default + T : X = Y, // type parameter with constraint and default + let N : int, // value parameter (type must be explicit) + let N : int = 3> // value parameter with default + () + { ... } + +We should also extend the `where` clauses to support inequality constraints on (integer) value parameters to enforce rules about what ranges of integers are valid. +The front-end should issue error messages if it can statically determine these constraints are violated, but it should probably defer full checking until the IR (maybe... we need to think about how much of a dependent type system we are willing to have). + +Associated Types +---------------- + +While the syntax is a bit different, the above mechanisms have approximately the same capabilities as Cg interfaces. +What the above approach can't handle (and neither can Cg) is a reusable definition of a surface material "pattern" that might blend multiple material layers to derive parameters for a specific BRDF. + +That is, suppose we have two BRDFs: one with two parameters, and one with six. +Different surface patterns may want to target different BRDFs. +So if we write a `Material` interface like: + + interface Material + { + BRDFParams evaluatePattern(float2 uv); + } + +Then what should `BRDFParams` be? The two-parameter or six-parameter case? + +An **associated type** is a concept that solves exactly this problem. +We don't care *what* the concrete type of `BRDFParams` is, so long as *every* implementation of `Material` has one. +The exact `BRDFParams` type can be different for each implementation of `Material`; the type is *associated* with a particular implementation. + +We will crib our syntax for this entirely from Swift, where it is verbose but explicit: + + interface Material + { + associatedtype BRDFParams; + + BRDFParams evaluatePattern(float2 uv); + + float3 evaluateBRDF(BRDFParams param, float3 wi, float3 wo); + } + +In this example we've added an associated type requirement so that every implementation of `Material` must supply a type named `BRDFParams` as a member. +We've also added a requirement that is a function to evaluate the BRDF given its parameters and incoming/outgoing directions. + +Using this declaration one can now define a generic function that works on any material: + + float3 evaluateSurface( + M material, + L[] lights, + float3 P_world, + float2 uv) + { + M.BRDFParams brdfParams = material.evaluatePattern(uv); + for(...) + { + L light = lights[i]; + // ... + float3 reflectance = material.evaluateBRDF(brdfParams, ...); + } + } + +Some quick notes: + +- The use of `associatedtype` (for associated types) and `typealias` (for `typedef`-like definitions) as distinct keywords in Swift was well motivated by their experience (they used to use `typealias` for both). I would avoid having the two cases be syntactically identical. + +- Swift has a pretty involved inference system where a type doesn't actually need to explicitly provide a type member with the chosen name. Instead, if you have a required method that takes or returns the associated type, then the compiler can infer what the type is by looking at the signature of the methods that meet other requirements. This is a complex and magical feature, and we shouldn't try to duplicate it. + +- Both Rust and Swift call this an "associated type." They are related to "virtual types" in things like Scala (which are in turn related to virtual classes in beta/gbeta). There are similar ideas that arise in Haskell-like languages with type classes (IIRC, the term "functional dependencies" is relevant). + +### Alternatives + +I want to point out a few alternatives to the `Material` design above, just to show that associated types seem to be an elegant solution compared to the alternatives. + +First, note that we could break `Material` into two interfaces, so long as we are allowed to place type constraints on associated types: + + interface BRDF + { + float3 evaluate(float3 wi, float3 wo); + } + + interface Material + { + associatedtype B : BRDF; + + B evaluatePattern(float2 uv); + } + +This refactoring might be cleaner if we imagine that a shader library would have family of reflectance functions (implementing `BRDF`) and then a large library of material patterns (implementing `Material`) - we wouldn't want each and every material to have to implement a dummy `evaluateBRDF` that just forwards to a BRDF instance nested in it. + +Looking at that type `B` there, we might start to wonder if we could just replace this with a generic type parameter on the interface: + + interface Material< B : BRDF > + { + B evaluatePattern(float2 uv); + } + +This would change any type that implements `Material`: + + // old: + struct MyMaterial : Material + { + typealias B = GGX; + + GGX evaluatePattern(...) { ... } + } + + // new: + struct MyMaterial : Material + { + GGX evaluatePattern(...) { ... } + } + +That doesn't seem so bad, but it ignores the complexity that arises at any use sites, e.g.: + + float3 evaluateSurface, L : Light>( + M material, + L[] lights, + float3 P_world, + float2 uv) + { ... } + +The type `B` which is logically an implementation detail of `M` now surfaces to the generic parameter list of any function that wants to traffic in materials. +This reduces the signal/noise ratio for anybody reading the code, and also means that any top-level code that is supposed to be specializing this function (suppose this was a fragment entry point) now needs to understand how to pick apart the `Material` it has on the host side to get the right type parameters. + +This kind of issue has existed in the PL community at least as far back as the ML module system (it is tough to name search, but the concepts of "parameterization" vs. "fibration" is relevant here), and the Scala researchers made a clear argument (I think it was in the paper on "un-types") that there is a categorical distinction between the types that are logicall the *inputs* to an abstraction, and the types that are logically the *outputs*. Generic type parameters and associated types handle these two distinct roles. + +Returning an Interface +---------------------- + +The revised `Material` definition: + + interface BRDF + { + float3 evaluate(float3 wi, float3 wo); + } + + interface Material + { + associatedtype B : BRDF; + + B evaluatePattern(float2 uv); + } + +has a function `evaluatePattern` that returns a type that implements an interface. +In the case where the return type is concrete, this isn't a problem (and the nature of associated types means that `B` will be concrete in any actual concrete implementation of `Material`). + +There is an open question of whether it is ever necessary (or even helpful) to have a function that returns a value of *some* type known to implement an interface, without having to state that type in the function signature. +This is a point that has [come up](https://github.com/rust-lang/rfcs/blob/master/text/1951-expand-impl-trait.md) in the Rust world, where they have discussed using a keyword like `some` to indicate the existential nature of the result type: + + // A function that returns *some* implementation of `Light` + func foo() -> some Light; + +The Rust proposal linked above has them trying to work toward `impl` as the keyword, and allowing it in both argument and result positions (to cover both universal and existential quantification). + +In general, such a feature would need to have many constraints: + +- The concrete return type must be fixed (even if clients of the function should be insulated from the choice), given the actual generic arguments provided. + +- If the existential is really going to be sealed, then the caller shouldn't be allowed to assume anything *except* that two calls to the same function with identical generic arguments should yield results of identical type. + +Under those constraints, it is pretty easy to see that an existential-returning method like: + + interface Foo + { + func foo() -> some Bar; + } + +can in principle be desugared into: + + interface Foo + { + associatedtype B : Bar; + + func foo() -> B; + } + +with particular loss in what can be expressed. +The same desugaring approach should apply to global-scope functions that want to return an existential type (just with a global `typealias` instead of an `associatedtype`). + + +It might be inconvenient for the user to have to explicitly write the type-level expression that yields the result type (consider cases where C++ template metaprogrammers would use `auto` as a result type), but there is really no added power. + + +Object-Oriented Sugar +--------------------- + +Having to explicitly write out generic parameter lists is tedious, especially in the (common) case where we will have exactly one parameter corresponding to each generic type parameter: + + // Why am I repeating myself?! + // + void fooserializationVersion != IRModuleInfo::kSupportedSerializationVersion) + return SLANG_FAIL; + +// Later, after loading instructions: +if (hasUnrecognizedInsts) + return SLANG_FAIL; +``` + +## Serialization Details + +### The Flat Representation + +For efficiency, IR modules are serialized as a "flat" representation: + +```cpp +struct FlatInstTable +{ + List instAllocInfo; // Op + operand count + List childCounts; // Children per instruction + List sourceLocs; // Source locations + List operandIndices; // Flattened operand references + List stringLengths; // For string/blob constants + List stringChars; // Concatenated string data + List literals; // Integer/float constant values +}; +``` + +This representation: + +- Minimizes pointer chasing during deserialization +- Groups similar data together for better cache performance +- Enables efficient bulk operations + +### Traversal Order + +Instructions are serialized in a specific order for performance: + +```cpp +traverseInstsInSerializationOrder(moduleInst, [&](IRInst* inst) { + // Process instruction +}); +``` + +The traversal: + +1. Visits instructions in preorder (parent before children) +2. Optionally reorders module-level instructions to group constants together +3. Maintains deterministic ordering for reproducible builds + +## Debugging and Validation + +### Available Tools + +1. **Module Info Inspection**: + + ```bash + slangc -get-module-info module.slang-module + ``` + + Shows module name, version, and compiler version. + +2. **Version Query**: + + ```bash + slangc -get-supported-module-versions + ``` + + Reports the supported version range. + +3. **IR Dumping**: + ```bash + slangc -dump-ir module.slang + ``` + Shows the IR in human-readable form. + +### Common Issues + +**"Unrecognized instruction" errors**: The module contains instructions unknown to this compiler version. Update Slang or recompile the module. + +**Stable name validation failures**: Run the update script and commit the changes: + +**Note**: Skip make command if lua is already built. +```bash +make -C external/lua MYCFLAGS="-DLUA_USE_POSIX" MYLIBS="" +./external/lua/lua extras/check-ir-stable-names.lua update +``` + +**Version mismatch**: The module was compiled with an incompatible Slang version. Check the version ranges and recompile if necessary. + +## Best Practices + +1. **Always update stable names**: After adding instructions, run the validation script before committing. + +2. **Document version changes**: When bumping module versions, add a comment explaining what changed. + +3. **Prefer addition over modification**: When possible, add new instructions rather than changing existing ones. + +4. **Group related changes**: If making multiple breaking changes, do them together in a single version bump. diff --git a/lib/All/slang/share/doc/slang/design/ir.md b/lib/All/slang/share/doc/slang/design/ir.md new file mode 100644 index 0000000..ba156c2 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/ir.md @@ -0,0 +1,275 @@ +The Design of Slang's Intermediate Representation (IR) +====================================================== + +This document details some of the important design choices for Slang's IR. + +Goals and Non-Goals +------------------- + +The IR needs to balance many goals which can sometimes come into conflict. +We will start by enumerating these goals (and related non-goals) explicitly so that we can better motivate specific design choices. + +* Obviously it must be simple to lower any source code in Slang code to the IR. It is however a non-goal for the lowering process to be lossless; we do not need to recover source-level program structure from the IR. + +* The IR must be amenable to standard dataflow analyses and optimizations. It should be possible to read a paper on a compiler algorithm or technique and apply it to our IR in a straightforward manner, and with the expected asymptotic efficiency. + +* As a particular case of analysis and optimization, it should be possible to validate flow-dependent properties of an input function/program (e.g., whether an `[unroll]` loop is actually unrollable) using the IR, and emit meaningful error messages that reference the AST-level names/locations of constructs involved in an error. + +* It should be possible to compile modules to the IR separately and then "link" them in a way that depends only on IR-level (not AST-level) constructs. We want to allow changing implementation details of a module without forcing a re-compile of IR code using that module (what counts as "implementation details") is negotiable. + +* There should be a way to serialize IR modules in a round-trip fashion preserving all of the structure. As a long-term goal, the serialized format should provide stability across compiler versions (working more as an IL than an IR) + +* The IR must be able to encode "generic" (type-parameterized) constructs explicitly, and to express transformations from generic to specialized (or dynamic-dispatch) code in the IR. In particular, it must be possible for a module to make use of generic defined in another (separately-compiled) module, with validation performed before linking, and specialization performed after. + +* The IR must be able to express code that is close to the level of abstraction of shader intermediate languages (ILs) like SPIR-V and DXIL, so that we can minimize the amount of work required (and the number of issues that can arise) when translating the IR to these targets. This can involve lowering and legalization passes to match the constraints of those ILs, but it should not require too much work to be done outside of the IR. + +* It should be possible to translate code in the IR back into high-level-language code, including things like structured control-flow constructs. + +* Whenever possible, invariants required by the IR should be built into its structure so that they are easier to maintain. + +* We should strive to make the IR encoding, both in memory and when serialized, as compact as is practically possible. + +Inspirations +------------ + +The IR design we currently use takes inspiration from three main sources: + +* The LLVM project provides the basic inspiration for the approach to SSA, such as using a typed IR, the decision to use the same object to represent an instruction and the SSA value it produces, and the push to have an extremely simple `replaceAllUsesWith` primitive. It is easy to forget that it is possible to design a compiler with different design decisions; the LLVM ones just happen to both be well-motivated and well-known. + +* The Swift IL (SIL) provides the inspiration for our approach for encoding SSA "phi nodes" (blocks with arguments), and also informs some of how we have approached encoding generics and related features like existential types. + +* The SPIR-V IL provides the inspiration for the choice to uniformly represent types as instructions, for how to encode "join points" for structured control flow, and for the concept of "decorations" for encoding additional metadata on instructions. + + +Key Design Decisions +-------------------- + +### Everything is an Instruction + +The Slang IR strives for an extremely high degree of uniformity, so almost every concept in the IR is ultimately just an instruction: + +* Ordinary add/sub/mul/etc. operations are instructions, as are function calls, branches, function parameters, etc. + +* Basic blocks in functions, as well as functions themselves are "parent instructions" that can have other instructions as children + +* Constant values (e.g., even `true` and `false`) are instructions + +* Types are instructions too, and can have operands (e.g., a vector type is the `VectorType` instruction applied to operands for the element type and count) + +* Generics are encoded entirely using ordinary instructions: a generic is encoded like a function that just happens to do computation at the type level + +* It isn't true right now, but eventually decorations will also be instructions, so that they can have operands like any other instruction + +* An overall IR module is itself an instruction so that there is a single tree that owns everything + +This uniformity greatly simplifies the task of supporting generics, and also means that operations that need to work over all instructions, such as cloning and serialization, can work with a single uniform representation and avoid special-casing particular opcodes. + +The decision to use an extremely uniform design, even going as far to treat types as "ordinary" instructions, is similar to SPIR-V, although we do not enforce many of the constraints SPIR-V does on how type and value instructions can be mixed. + +### Instructions Have a Uniform Structure + +Every instruction has: + +* An opcode +* A type (the top-level module is the only place where this can be null) +* Zero or more operands +* Zero or more decorations +* Zero or more children + +Instructions are not allowed to have any semantically-relevant information that is not in the above list. +The only exception to this rule is instructions that represent literal constants, which store additional data to represent their value. + +The in-memory encoding places a few more restrictions on top of this so that, e.g., currently an instruction can either have operands of children, but not both. + +Because everything that could be used as an operand is also an instruction, the operands of an instruction are stored in a highly uniform way as a contiguous array of `IRUse` values (even the type is contiguous with this array, so that it can be treated as an additional operand when required). +The `IRUse` type maintains explicit links for use-def information, currently in a slightly bloated fashion (there are well-known techniques for reducing the size of this information). + +### A Class Hierarchy Mirrored in Opcodes + +There is a logical "class hierarchy" for instructions, and we support (but do not mandate) declaring a C++ `struct` type to expose an instruction or group of instructions. +These `struct` types can be helpful to encode the fact that the program knows an instruction must/should have a particular type (e.g., having a function parameter of type `IRFunction*` prevents users from accidentally passing in an arbitrary `IRInst*` without checking that it is a function first), and can also provide convenience accessors for operands/children. + +Do make "dynamic cast" operations on this class hierarchy efficient, we arrange for the instruction opcodes for the in-memory IR to guarantee that all the descendents of a particular "base class" will occupy a contiguous range of opcodes. Checking that an instruction is in that range is then a constant-time operation that only looks at its opcode field. + +There are some subtleties to how the opcodes are ordered to deal with the fact that some opcodes have a kind of "multiple inheritance" thing going on, but that is a design wart that we should probably remove over time, rather than something we are proud of. + +### A Simpler Encoding of SSA + +The traditional encoding of SSA form involves placing "phi" instructions at the start of blocks that represent control-flow join points where a variable will take on different values depending on the incoming edge that is taken. +There are of course benefits to sticking with tradition, but phi instructions also have a few downsides: + +- The operands to phi instructions are the one case where the "def dominates use" constraint of SSA appears to be violated. I say "appears" because officially the action of a phi occurs on the incoming edge (not in the target block) and that edge will of course be dominated by the predecessor block. It still creates a special case that programmers need to be careful about. This also complicates serialization in that there is no order in which the blocks/instructions of a function can be emitted that guarantees that every instruction always precedes all of its uses in the stream. + +- All of the phi instructions at the start of the block must effectively operate in parallel, so that they all "read" from the correct operand before "writing" to the target variable. Like the above special case, this is only a problem for a phi related to a loop back-edge. It is of course possible to always remember the special interpretation of phi instructions (that they don't actually execute sequentially like every other instruction in a block), but its another special case. + +- The order of operands to a phi instruction needs to be related back to the predecessor blocks, so that one can determine which value is to be used for which incoming edge. Any transformation that modifies the CFG of a function needs to be careful to rewrite phi instructions to match the order in which predecessors are listed, or else the compiler must maintain a side data structure that remembers the mapping (and update it instead). + +- Directly interpreting/executing code in an SSA IR with phi instructions is made more difficult because when branching to a block we need to immediately execute any phi instructions based on the block from which we just came. The above issues around phis needing to be executed in parallel, and needing to track how phi operands relate to predecessor blocks also add complexity to an interpreter. + +Slang ditches traditional phi functions in favor of an alternative that matches the Swift IL (SIL). +The idea doesn't really start in Swift, but rather in the existing observation that SSA form IR and a continuation-passing style (CPS) IR are semantically equivalent; one can encode SSA blocks as continuation functions, where the arguments of the continuation stand in for the phi instructions, and a branch to the block becomes just a call. + +Like Swift, we do not use an explicit CPS representation, but instead find a middle ground of a traditional SSA IR where instead of phi instructions basic blocks have parameters. +The first N instructions in a Slang basic block are its parameters, each of which is an `IRParam` instruction. + +A block that would have had N phi instructions now has N parameters, but the parameters do not have operands. +Instead, a branch instruction that targets that block will have N *arguments* to match the parameters, representing the values to be assigned to the parameters when this control-flow edge is taken. + +This encoding is equivalent in what it represents to traditional phi instructions, but nicely solves the problems outlined above: + +- The phi operands in the successor block are now arguments in the *predecessor* block, so that the "def dominates use" property can be enforced without any special cases. + +- The "assignment" of the argument values to parameters is now encoded with a single instruction, so that the simultaneity of all the assignments is more clear. We still need to be careful when leaving SSA form to obey those semantics, but there are no tricky issues when looking at the IR itself. + +- There is no special work required to track which phi operands come from which predecessor block, since the operands are attached to the terminator instruction of the predecessor block itself. There is no need to update phi instructions after a CFG change that might affect the predecessor list of a block. The trade-off is that any change in the *number* of parameters of a block now requires changes to the terminator of each predecessor, but that is a less common change (isolated to passes that can introduce or eliminate block parameters/phis). + +- It it much more clear how to give an operational semantics to a "branch with arguments" instead of phi instructions: compute the target block, copy the arguments to temporary storage (because of the simultaneity requirement), and then copy the temporaries over the parameters of the target block. + +The main caveat of this representation is that it requires branch instructions to have room for arguments to the target block. For an ordinary unconditional branch this is pretty easy: we just put a variable number of arguments after the operand for the target block. For branch instructions like a two-way conditional, we might need to encode two argument lists - one for each target block - and an N-way `switch` branch only gets more complicated. + +The Slang IR avoids the problem of needing to store arguments on every branch instruction by banning *critical edges* in IR functions that are using SSA phis/parameters. A critical edge is any edge from a block with multiple successors (meaning it ends in a conditional branch) to one with multiple predecessors (meaning it is a "join point" in the CFG). +Phi instructions/parameters are only ever needed at join points, and so block arguments are only needed on branches to a join point. +By ruling out conditional branches that target join points, we avoid the need to encode arguments on conditional branch instructions. + +This constraint could be lifted at some point, but it is important to note that there are no programs that cannot be represented as a CFG without critical edges. + +### A Simple Encoding of the CFG + +A traditional SSA IR represents a function as a bunch of basic blocks of instructions, where each block ends in a *terminator* instruction. +Terminators are instructions that can branch to another block, and are only allowed at the end of a block. +The potential targets of a terminator determine the *successors* of the block where it appears, and contribute to the *predecessors* of any target block. +The successor-to-predecessor edges form a graph over the basic blocks called the control-flow graph (CFG). + +A simple representation of a function would store the CFG explicitly as a graph data structure, but in that case the data structure would need to be updated whenever a change is made to the terminator instruction of a branch in a way that might change the successor/predecessor relationship. + +The Slang IR avoids this maintenance problem by noting an important property. +If block `P`, with terminator `t`, is a predecessor of `S`, then `t` must have an operand that references `S`. +In turn, that means that the list of uses of `S` must include `t`. + +We can thus scan through the list of predecessors or successors of a block with a reasonably simple algorithm: + +* To find the successors of `P`, find its terminator `t`, identify the operands of `t` that represent successor blocks, and iterate over them. This is O(N) in the number of outgoing CFG edges. + +* To find the predecessors of `S`, scan through its uses and identify users that are terminator instructions. For each such user if this use is at an operand position that represents a successor, then include the block containing the terminator in the output. This is O(N) in the number of *uses* of a block, but we expect that to be on the same order as the number of predecessors in practice. + +Each of these actually iterates over the outgoing/incoming CFG *edges* of a block (which might contain duplicates if one block jumps to another in, e.g, multiple cases of a `switch`). +Sometimes you actually want the edges, or don't care about repeats, but in the case where you want to avoid duplicates the user needs to build a set to deduplicate the lists. + +The clear benefit of this approach is that the predecessor/successor lists arise naturally from the existing encoding of control-flow instructions. It creates a bit of subtle logic when walking the predecessor/successor lists, but that code only needs to be revisited if we make changes to the terminator instructions that have successors. + +### Explicit Encoding of Control-Flow Join Points + +In order to allow reconstruction of high-level-language source code from a lower-level CFG, we need to encode something about the expected "join point" for a structured branch. +This is the logical place where control flow is said to "reconverge" after a branch, e.g.: + +```hlsl +if(someCondition) // join point is "D" +{ + A; +} +else +{ + B; + if(C) return; +} +D; +``` + +Note that (unlike what some programming models would say) a join point is *not* necessarily a postdominator of the conditional branch. In the example above the block with `D` does not postdominate the block with `someCondition` nor the one with `B`. It is even possible to construct cases where the high-level join point of a control-flow construct is unreachable (e.g., the block after an infinite loop). + +The Slang IR encodes structured control flow by making the join point be an explicit operand of a structured conditional branch operation. Note that a join-point operand is *not* used when computing the successor list of a block, since it does not represent a control-flow edge. +This is slightly different from SPIR-V where join points ("merge points" in SPIR-V) are encoded using a metadata instruction that precedes a branch. Keeping the information on the instruction itself avoids cases where we move one but not the other of the instructions, or where we might accidentally insert code between the metadata instruction and the terminator it modifies. +In the future we might consider using a decoration to represent join points. + +When using a loop instruction, the join point is also the `break` label. The SPIR-V `OpLoopMerge` includes not only the join point (`break` target) but also a `continue` target. We do not currently represent structured information for `continue` blocks. +The reason for this is that while we could keep structured information about `continue` blocks, we might not be able to leverage it when generating high-level code, because the syntactic form of a `for` loop (the only construct in C-like languages where `continue` can go somewhere other than the top of the loop body) only allows an *expression* for the continue clause and not a general *statement*, but we cannot guarantee that after optimization the code in an IR-level "continue clause" would constitute a single expression. +The approach we use today means that the code in "continue clause" might end up being emitted more than once in final code; this is deemed acceptable because it is what `fxc` already does. + +When it comes time to re-form higher-level structured control flow from Slang IR, we use the structuring information in the IR to form single-entry "regions" of code that map to existing high-level control-flow constructs (things like `if` statements, loops, `break` or `continue` statements, etc.). +The current approach we use requires the structuring information to be maintained by all IR transformations, and also currently relies on some invariants about what optimizations are allowed to do (e.g., we had better not introduce multi-level `break`s into the IR). + +In the future, it would be good to investigate adapting the "Relooper" algorithm used in Emscripten so that we can recover valid structured control flow from an arbitrary CFG; for now we put off that work. +If we had a more powerful restructuring algorithm at hand, we could start to support things like multi-level `break`, and also ensure that `continue` clauses don't lead to code duplication any more. + +## IR Global and Hoistable Value Deduplication + +Types, constants and certain operations on constants are considered "global value" in the Slang IR. Some other insts like `Specialize()` and `Ptr(x)` are considered as "hoistable" insts, in that they will be defined at the outer most scope where their operands are available. For example, `Ptr(int)` will always be defined at global scope (as direct children of `IRModuleInst`) because its only operand, `int`, is defined at global scope. However if we have `Ptr(T)` where `T` is a generic parameter, then this `Ptr(T)` inst will be always be defined in the block of the generic. Global and hoistable values are always deduplicated and we can always assume two hoistable values with different pointer addresses are distinct values. + +The `IRBuilder` class is responsible for ensuring the uniqueness of global/hoistable values. If you call any `IRBuilder` methods that creates a new hoistable instruction, e.g. `IRBuilder::createIntrinsicInst`, `IRBuilder::emitXXX` or `IRBuilder::getType`, `IRBuilder` will check if an equivalent value already exists, and if so it returns the existing inst instead of creating a new one. + +The trickier part here is to always maintain the uniqueness when we modify the IR. When we update the operand of an inst from a non-hoistable-value to a hoistable-value, we may need to hoist `inst` itself as a result. For example, consider the following code: +``` +%1 = IntType +%p = Ptr(%1) +%2 = func { + %x = ...; + %3 = Ptr(%x); + %4 = ArrayType(%3); + %5 = Var (type: %4); + ... +} +``` + +Now consider the scenario where we need to replace the operand in `Ptr(x)` to `int` (where `x` is some non-constant value), we will get a `Ptr(int)` which is now a global value and should be deduplicated: +``` +%1 = IntType +%p = Ptr(%1) +%2 = func { + %x = ...; + //%3 now becomes %p. + %4 = ArrayType(%p); + %5 = Var (type: %4); + ... +} +``` +Note this code is now breaking the invariant that hoistable insts are always defined at the top-most scope, because `%4` becomes is no longer dependent on any local insts in the function, and should be hoisted to the global scope after replacing `%3` with `%p`. This means that we need to continue to perform hoisting of `%4`, to result this final code: +``` +%1 = IntType +%p = Ptr(%1) +%4 = ArrayType(%p); // hoisted to global scope +%2 = func { + %x = ...; + %5 = Var (type: %4); + ... +} +``` + +As illustrated above, because we need to maintain the invariants of global/hoistable values, replacing an operand of an inst can have wide-spread effect on the IR. + +To help ensure these invariants, we introduce the `IRBuilder.replaceOperand(inst, operandIndex, newOperand)` method to perform all the cascading modifications after replacing an operand. However the `IRInst.setOperand(idx, newOperand)` will not perform the cascading modifications, and using `setOperand` to modify the operand of a hoistable inst will trigger a runtime assertion error. + +Similarly, `inst->replaceUsesWith` will also perform any cascading modifications to ensure the uniqueness of hoistable values. Because of this, we need to be particularly careful when using a loop to iterate the IR linked list or def-use linked list and call `replaceUsesWith` or `replaceOperand` inside the loop. + +Consider the following code: + +``` +IRInst* nextInst = nullptr; +for (auto inst = func->getFirstChild(); inst; inst = nextInst) +{ + nextInst = inst->getNextInst(); // save a copy of nestInst + // ... + inst->replaceUsesWith(someNewInst); // Warning: this may be unsafe, because nextInst could been moved to parent->parent! +} +``` + +Now imagine this code is running on the `func` defined above, imagine we are now at `inst == %3` and we want to replace `inst` with `Ptr(int)`. Before calling `replaceUsesWith`, we have stored `inst->nextInst` to `nextInst`, so `nextInst` is now `%4`(the array type). Now after we call `replaceUsesWith`, `%4` is hoisted to global scope, so in the next iteration, we will start to process `%4` and follow its `next` pointer to `%2` and we will be processing `func` instead of continue walking the child list! + +Because of this, we should never be calling `replaceOperand` or `replaceUsesWith` when we are walking the IR linked list. If we want to do so, we must create a temporary workList and add all the insts to the work list before we make any modifications. The `IRInst::getModifiableChildren` utility function will return a temporary work list for safe iteration on the children. The same can be said to the def-use linked list. There is `traverseUses` and `traverseUsers` utility functions defined in `slang-ir.h` to help with walking the def-use list safely. + +Another detail to keep in mind is that any local references to an inst may become out-of-date after a call to `replaceOperand` or `replaceUsesWith`. Consider the following code: +``` +IRBuilder builder; +auto x = builder.emitXXX(); // x is some non-hoistable value. +auto ptr = builder.getPtrType(x); // create ptr(x). +x->replaceUsesWith(intType); // this renders `ptr` obsolete!! +auto var = builder.emitVar(ptr); // use the obsolete inst to create another inst. +``` +In this example, calling `replaceUsesWith` will cause `ptr` to represent `Ptr(int)`, which may already exist in the global scope. After this call, all uses of `ptr` should be replaced with the global `Ptr(int)` inst instead. `IRBuilder` has provided the mechanism to track all the insts that are removed due to deduplication, and map those removed but not yet deleted insts to the existing inst. When using `ptr` to create a new inst, `IRBuilder` will first check if `ptr` should map to some existing hoistable inst in the global deduplication map and replace it if possible. This means that after the call to `builder.emitVar`, `var->type` is not equal to to `ptr`. + +### Best Practices + +In summary, the best practices when modifying the IR is: +- Never call `replaceUsesWith` or `replaceOperand` when walking raw linked lists in the IR. Always create a work list and iterate on the work list instead. Use `IRInst::getModifiableChildren` and `traverseUses` when you need to modify the IR while iterating. +- Never assume any local references to an `inst` is up-to-date after a call to `replaceUsesWith` or `replaceOperand`. It is OK to continue using them as operands/types to create a new inst, but do not assume the created inst will reference the same inst passed in as argument. + + diff --git a/lib/All/slang/share/doc/slang/design/overview.md b/lib/All/slang/share/doc/slang/design/overview.md new file mode 100644 index 0000000..e1790bb --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/overview.md @@ -0,0 +1,265 @@ +An overview of the Slang Compiler +================================= + +This document will attempt to walk through the overall flow of the Slang compiler, as an aid to developers who are trying to get familiar with the codebase and its design. +More emphasis will be given to places where the compiler design is nontraditional, or might surprise newcomers; things that are straightforward won't get much detail. + +High-Level Concepts +------------------- + +Compilation is always performed in the context of a *compile request*, which bundles together the options, input files, and request for code generation. +Inside the code, there is a type `CompileRequest` to represent this. + +The user specifies some number of *translation units* (represented in the code as a `TranslationUnitRequest`) which comprise some number of *sources* (files or strings). +HLSL follows the traditional C model where a "translation unit" is more or less synonymous with a source file, so when compiling HLSL code the command-line `slangc` will treat each source file as its own translation unit. +For Slang code, the command-line tool will by default put all source files into a single translation unit (so that they represent a shared namespace0). + +The user can also specify some number of *entry points* in each translation unit (`EntryPointRequest`), which combines the name of a function to compile with the pipeline stage to compile for. + +In a single compile request, we can generate code for zero or more *targets* (represented with `TargetRequest`) a target defines both the format for output code (e.g., DXIL or SPIR-V) and a *profile* that specifies the capability level to assume (e.g., "Shader Model 5.1"). + +It might not be immediately clear why we have such fine-grained concepts as this, but it ends up being quite important to decide which pieces of the compiler are allowed to depend on which pieces of information (e.g., whether or not a phase of compilation gets to depend on the chosen target). + +The "Front End" +--------------- + +The job of the Slang front-end is to turn textual source code into a combination of code in our custom intermediate representation (IR) plus layout and binding information for shader parameters. + +### Lexing + +The first step in the compiler (after a source file has been loaded into memory) is to *lex* it. +The `Lexer` type is implement in `lexer.{h,cpp}` and produces `Token`s that represent the contents of the file on-demand as requested by the next phase of compilation. + +Each token stores a `TokenCode` that indicates the kind of token, the raw text of the token, and the location in the source code where it is located. +Source locations use a somewhat clever encoding to avoid being bloated (they are a single integer rather than separate file, line, and column fields). + +We don't make any attempt in the lexer to extract the actual value of integer and floating-point literals; we just store the raw text. +We also don't try to distinguish keywords from identifiers; keywords show up as ordinary identifier tokens. + +Much of the complexity (and inefficiency) in the current lexer is derived from the need to support C-isms like backspace line continuation, and special case rules like allowing `<>` to delimit a file name string after a `#include`. + +### Preprocessing + +The preprocessor (`Preprocessor`) in `preprocessor.{h,cpp}` deals with `#include` constructs, macro expansions, etc. +It pulls tokens from the lexer as needed (making sure to set flags to control the lexer behavior when required) and uses a limited lookahead to decide what to do with each token. + +The preprocessor maintains a stack of input streams, with the original source file at the bottom, and pushes entries for `#include`d files, macros to expand etc. + +Macro definitions store a sequence of already-lexed tokens, and expansion simply "replays" these tokens. +Expansion keeps a notion of an "environment" for looking up identifiers and mapping them to macro definitions. +Calling through to a function-style macro creates a fresh environment that maps the macro parameter names to pseudo-macros for the arguments. + +We still tokenize code in inactive preprocessor conditionals, but don't evaluate preprocessor directives inside inactive blocks (except those that may change the active/inactive state). +Preprocessor directives are each handled as a callback on the preprocessor state and are looked up by name; adding a new directive (if we ever had a reason to) is a fairly simple task. + +One important detail of the preprocessor is that it runs over a full source file at once and produces a flat array of `Token`s, so that there is no direct interaction between the parser and preprocessor. + +### Parsing + +The parser (`Parser` in `parser.{h,cpp}`) is mostly a straightforward recursive-descent parser. +Because the input is already tokenized before we start, we can use arbitrary lookahead, although we seldom look ahead more than one token. + +Traditionally, parsing of C-like languages requires context-sensitive parsing techniques to distinguish types from values, and deal with stuff like the C++ "most vexing parse." +Slang instead uses heuristic approaches: for example, when we encounter an `<` after an identifier, we first try parsing a generic argument list with a closing `>` and then look at the next token to determine if this looks like a generic application (in which case we continue from there) or not (in which case we backtrack). + +There are still some cases where we use lookup in the current environment to see if something is a type or a value, but officially we strive to support out-of-order declarations like most modern languages. +In order to achieve that goal we will eventually move to a model where we parse the bodies of declarations and functions in a later pass, after we have resolved names in the global scope. + +One important choice in the parser is that we strive to avoid hard-coding keywords as much as possible. +We already track an environment for C-like parsing, and we simply extend that so that we also look up declaration and statement keywords in the environment. +This means that most of the language "keywords" in Slang aren't keywords at all, and instead are just identifiers that happen to be bound to syntax in the default environment. +Syntax declarations are associated with a callback that is invoked to parse the construct they name. + +The design of treating syntax as ordinary declarations has a long-term motivation (we'd like to support a flexible macro system) but it also has short-term practical benefits. +It is easy for us to add new modifier keywords to the language without touching the lexer or parser (just adding them to the core module), and we also don't have to worry about any of Slang's extended construct (e.g., `import`) breaking existing HLSL code that just happens to use one of those new keywords as a local variable name. + +What the parser produces is an abstract syntax tree (AST). +The AST currently uses a strongly-typed C++ class hierarchy with a "visitor" API generated via some ugly macro magic. +Dynamic casting using C++ RTTI is used in many places to check the class of an AST node; we aren't happy with this but also haven't had time to implement a better/faster solution. + +In the parsed AST, both types and expressions use the same representation (because in an expression like `A(B)` it is possible that `A` will resolve to a type, or to a function, and we don't know which yet). + +One slightly odd design choice in the parser is that it attaching lexical scoping information to the syntax nodes for identifiers, and any other AST node that need access to the scope/environment where it was defined. This is a choice we will probably change at some point, but it is deeply ingrained right now. + +### Semantic Checking + +The semantic checking step (`check.{h,cpp}`) is, not surprisingly, the most complicated and messiest bit of the compiler today. +The basic premise is simple: recursively walk the entire AST and apply semantic checking to each construct. + +Semantic checking applies to one translation unit at a time. +It has access to the list of entry points for the translation unit (so it can validate them), but it *not* allowed to depend on the compilation target(s) the user might have selected. + +Semantic checking of an expression or type term can yield the same AST node, with type information added, or it can return newly constructed AST needs (e.g., when an implicit cast needs to be inserted). +Unchecked identifiers or member references are always resolved to have a pointer to the exact declaration node they are referencing. + +Types are represented with a distinct class hierarchy from AST nodes, which is also used for a general notion of compile-time values which can be used to instantiate generic types/functions/etc. +An expression that ends up referring to a type will have a `TypeType` as its type, which will hold the actual type that the expression represents. + +The most complicated thing about semantic checking is that we strive to support out-of-order declarations, which means we may need to check a function declaration later in the file before checking a function body early in the file. +In turn, that function declaration might depend on a reference to a nested type declared somewhere else, etc. +We currently solve this issue by doing some amount of on-demand checking; when we have a reference to a function declaration and we need to know its type, we will first check if the function has been through semantic checking yet, and if not we will go ahead and recursively type check that function before we proceed. + +This kind of unfounded recursion can lead to real problems (especially when the user might write code with circular dependencies), so we have made some attempts to more strictly "phase" the semantic checking, but those efforts have not yet been done systematically. + +When code involved generics and/or interfaces, the semantic checking phase is responsible for ensuring that when a type claims to implement an interface it provides all of the requirements of that interface, and it records the mapping from requirements to their implementations for later use. Similarly, the body of a generic is checked to make sure it uses type parameters in ways that are consistent with their constraints, and the AST is amended to make it explicit when an interface requirement is being employed. + +### Lowering and Mandatory Optimizations + +The lowering step (`lower-to-ir.{h,cpp}`) is responsible for converting semantically valid ASTs into an intermediate representation that is more suitable for specialization, optimization, and code generation. +The main thing that happens at this step is that a lot of the "sugar" in a high-level language gets baked out. For example: + +- A "member function" in a type will turn into an ordinary function that takes an initial `this` parameter +- A `struct` type nested in another `struct` will turn into an ordinary top-level `struct` +- Compound expressions will turn into sequences of instructions that bake the order of evaluation +- High-level control-flow statements will get resolved to a control-flow graph (CFG) of basic blocks + +The lowering step is done once for each translation unit, and like semantic checking it does *not* depend on any particular compilation target. +During this step we attach "mangled" names to any imported or exported symbols, so that each function overload, etc. has a unique name. + +After IR code has been generated for a translation unit (now called a "module") we next perform a set of "mandatory" optimizations, including SSA promotion and simple copy propagation and elimination of dead control-flow paths. +These optimizations are not primarily motivated by a desire to speed up code, but rather to ensure that certain "obvious" simplifications have been performed before the next step of validation. + +After the IR has been "optimized" we perform certain validation/checking tasks that would have been difficult or impossible to perform on the AST. +For example, we can validate that control flow never reached the end of a non-`void` function, and issue an error otherwise. +There are other validation tasks that can/should be performed at this step, although not all of them are currently implemented: + +- We should check that any `[unroll]` loops can actually be unrolled, by ensuring that their termination conditions can be resolved to a compile-time constant (even if we don't know the constant yet) + +- We should check that any resource types are being used in ways that can be statically resolved (e.g., that the code never conditionally computes a resource to reference), since this is a requirement for all our current targets + +- We should check that the operands to any operation that requires a compile-time constant (e.g., the texel offset argument to certain `Sample()` calls) are passed values that end up being compile-time constants + +The goal is to eliminate any possible sources of failure in low-level code generation, without needing to have a global view of all the code in a program. +Any error conditions we have to push off until later starts to limit the value of our separate compilation support. + +### Parameter Binding and Type Layout + +The next phase of parameter binding (`parameter-binding.{h,cpp}`) is independent of IR generation, and proceeds based on the AST that came out of semantic checking. +Parameter binding is the task of figuring out what locations/bindings/offsets should be given to all shader parameters referenced by the user's code. + +Parameter binding is done once for each target (because, e.g., Vulkan may bind parameters differently than D3D12), and it is done for the whole compile request (all translation units) rather than one at a time. +This is because when users compile something like HLSL vertex and fragment shaders in distinct translation units, they will often share the "same" parameter via a header, and we need to ensure that it gets just one location. + +At a high level, parameter binding starts by computing the *type layout* of each shader parameter. +A type layout describes the amount of registers/bindings/bytes/etc. that a type consumes, and also encodes the information needed to compute offsets/registers for individual `struct` fields or array elements. + +Once we know how much space each parameter consumes, we then inspect an explicit binding information (e.g., `register` modifiers) that are relevant for the target, and build a data structure to record what binding ranges are already consumed. +Finally, we go through any parameters without explicit binding information and assign them the next available range of the appropriate size (in a first-fit fashion). + +The parameter binding/layout information is what the Slang reflection API exposes. It is layered directly over the Slang AST so that it accurately reflects the program as the user wrote it, and not the result of lowering that program to our IR. + +This document describes parameter binding as a "front end" activity, but in practice it is something that could be done in the front-end, the back-end or both. +When shader code involves generic type parameters, complete layout information cannot be generated until the values of these parameters are fully known, and in practice that might not happen until the back end. + +### Serialization + +It is not yet fully implemented, but our intention is that the last thing the front-end does is to serialize the following information: + +- A stripped-down version of the checked AST for each translation unit including declarations/types, but not function bodies + +- The IR code for each translation unit + +- The binding/layout information for each target + +The above information is enough to type-check a subsequent module that `import`s code compile in the front-end, to link against its IR code, or to load and reflect type and binding information. + + +The "Back End" +-------------- + +The Slang back end logically starts with the user specifying: + +- An IR module, plus any necessary modules to link in and provide its dependencies + +- An entry point in that module, plus arguments for any generic parameters that entry point needs + +- A compilation target (e.g., SPIR-V for Vulkan) + +- Parameter binding/layout information for that module and entry point, computed for the chosen target + +We eventually want to support compiling multiple entry points in one pass of the back end, but for now it assumes a single entry point at a time + +### Linking and Target Specialization + +The first step we perform is to copy the chosen entry point and anything it depends on, recursively into a "fresh" IR module. +We make a copy of things so that any optimization/transformation passes we do for one target don't alter the code the front-end produced in ways that affect other targets. + +While copying IR code into the fresh module, we have cases where there might be multiple definitions of the same function or other entity. +In those cases, we apply "target specialization" to pick the definition that is the best for the chosen target. +This step is where we can select between, say, a built-in definition of the `saturate` function for D3D targets, vs. a hand-written one in a Slang standard module to use for GLSL-based targets. + +### API Legalization + +If we are targeting a GLSL-based platform, we need to translate "varying" shader entry point parameters into global variables used for cross-stage data passing. +We also need to translate any "system value" semantics into uses of the special built-in `gl_*` variables. + +We currently handle this kind of API-specific legalization quite early in the process, performing it right after linking. + +### Generic Specialization + +Once the concrete values for generic parameters are know we can set about specializing code to the known types. +We do this by cloning a function/type/whatever and substituting in the concrete arguments for the parameters. +This process can be continued as specializing one function may reveal opportunities to specialize others. + +During this step we also specialize away lookup of interface requirements through their witness tables, once generic witness-table parameters have been replaced with concrete witness tables. + +At the end of specialization, we should have code that makes no use of user-defined generics or interfaces. + +### Type Legalization + +While HLSL and Slang allow a single `struct` type to contain both "ordinary" data like a `float3` and "resources" like a `Texture2D`, the rules for GLSL and SPIR-V are more restrictive. +There are some additional wrinkles that arise for such "mixed" types, so we prefer to always "legalize" the types in the users code by replacing an aggregate type like: + +```hlsl +struct Material { float4 baseColor; Texture2D detailMap; }; +Material gMaterial; +``` + +with separate declarations for ordinary and resource fields: + +```hlsl +struct Material { float4 baseColor; } + +Material gMaterial; +Texture2D gMaterial_detailMap; +``` + +Changing the "shape" of a type like this (so that a single variable becomes more than one) needs to be done consistently across all declarations/functions in the program (hence why we do it after specialization, so that all concrete types are known). + +### Other Optimizations + +We dont' currently apply many other optimizations on the IR code in the back-end, under the assumption that the lower-level compilers below Slang will do some of the "heavy lifting." + +That said, there are certain optimizations that Slang must do eventually, for semantic completeness. One of the most important examples of these is implementing the semantics of the `[unroll]` attribute, since we can't always rely on downstream compilers to have a capable unrolling implementation. + +We expect that over time it will be valuable for Slang to support a wider array of optimization passes, as long as they are ones that are considered "safe" to do above the driver interface, because they won't interfere with downstream optimization opportunities. + +### Emission + +Once we have transformed the IR code into something that should be legal for the chosen target, we emit code in the appropriate format for the target. This can be high-level source code (such as HLSL, GLSL, Metal, WGSL, C++, or CUDA) or binary formats (such as SPIR-V, DXIL, PTX, or MetalLib) depending on the compilation target. + +The emit logic is mostly just a scan over the IR code to emit a high-level declaration for each item: an IR structure type becomes a `struct` declaration, and IR function becomes a function definition, etc. + +In order to make the generated code a bit more readable, the Slang compiler currently does *not* emit declarations using their mangled names and instead tries to emit everything using a name based on how it was originally declared. + +To improve the readability of function bodies, the emit logic tries to find consecutive sequences of IR instructions that it can emit as a single high-level language expression. This reduces the number of temporaries in the output code, but we need to be careful about inserting parentheses to respect operator precedence, and also to not accidentally change the order of evaluation of code. + +When emitting a function body, we need to get from the low-level control flow graph (CFG) to high-level structured control-flow statements like `if`s and loops. We currently do this on a per-function basis during code emission, using an ad hoc algorithm based on control-flow structured information we stored in the IR. +A future version of the compiler might implement something more complete like the "Relooper" algorithm used by Emscripten. + +### Downstream Compiler Execution + +For certain targets and compilation paths, we invoke downstream compilers to generate binary code (and optionally to disassemble that code for console output). For example: +- DXIL and DXBC targets use dxc and fxc respectively +- SPIR-V, although generated directly from the Slang IR by default, can instead use glslang if the `-emit-spirv-via-glsl` option is specified for `slangc`. If that option is used, GLSL is emitted from the Slang IR to pass to glslang for SPIR-V generation +- PTX generation uses NVRTC +- MetalLib and MetalLibAssembly targets use the Metal compiler (MetalC) + +Targets that have output emitted directly from the Slang IR without the use of downstream compilers include high-level source formats like HLSL, GLSL, Metal, WGSL, C++, and CUDA source, as well as the default SPIR-V binary generation path. + +The Slang compiler also supports a "pass through" mode where it skips most of the steps outlined so far and just passes text along to downstream compilers directly. This is primarily intended as a debugging aid for developers working on Slang, since it lets you use the same command-line arguments to invoke both Slang compilation and compilation with these other compilers. + +Conclusion +---------- + +Hopefully this whirlwind introduction to the flow of the Slang compiler gives some idea of how the project fits together, and makes it easier to dive into the code and start being productive. diff --git a/lib/All/slang/share/doc/slang/design/parsing.md b/lib/All/slang/share/doc/slang/design/parsing.md new file mode 100644 index 0000000..9027e06 --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/parsing.md @@ -0,0 +1,68 @@ +# Resolving Ambiguity in Slang's Parser + +A typical text-book style compiler front-end usually features explicit stages: tokenization, parsing, and semantic checking. Slang's original design follows this pattern, but the design has a drawback that it cannot effectively disambiguate the syntax due to lack of semantic info during parsing. + +For example, without knowing what `X` is, it is impossible to tell whether `X(5)` means calling a generic function `X` with argument `5`, or computing the logical `AND` between condition `X < a` and `b > 5`. + +Slang initially addresses this problem with a heursitic: if the compiler sees `IDENTIFIER` followed by `<`, it will try to parse the expression as a generic specialization first, and if that succeeds, it checks the token after the closing `>` to see if the following token is one of the possible "generic specialization followers". In this example, the next token is `(`, which is a "generic specialization follower", so the compiler determines that the expression being parsed is very likely a generic function call, and it will parse the expression as such. For reference, the full set of "generic specialization followers" are: `::`, `.`, `(`, `)`, `[`, `]`, `:`, `,`, `?`, `;`, `==`, `!=`, `>` and `>>`. + +This simplistic heuristic is originated from the C# compiler, which works well there since C# doesn't allow generic value arguments, therefore things like `X...` or `X...` can never be valid generic specializations. This isn't the case for Slang, where generic arguments can be int or boolean values, so `a&&b` and `a`) is encoded as a pointer to a `T`. +If the pointer is null, the optional has no value; otherwise the value is stored at the offset being pointed to. + +Note that when encoding a pointer to an optional (`std::optional *`) or an optional pointer (`std::optional`), there will be two indirections. + +#### Records + +Things that are conceptually like a `struct` or tuple are encoded as *records*, which are simply a sequence of *fields*. + +The alignment of a record is the maximum alignment of its fields. + +Fields in a record are laid out sequentially, where each field gets the next suitably-aligned offset after the preceding field. +No effort is made to fill in "gaps" left by preceding fields. + +Note: currently the size of a record is *not* rounded up to be a multiple of its alignment, so it is possible for one field to be laid out in the "tail padding" of the field before it. +This behavior should probably be changed, so that the fossilized layout better matches what C/C++ compilers tend to do. + +### Variable-Size Types + +Types where different instances may consume a different number of bytes may be encoded either *inline* or *indirectly*. + +If a variable-size type `V` is being referred to by a pointer or optional (e.g., `V*` or `std::optional`), then it will be encoded inline as the target address of that pointer/optional. + +In all other contexts, including when a `V` is used as a field or a record, it will be encoded indirectly (conceptually, as if the field was actually a `V*`). +When a variable-size type is encoded indirectly, a null pointer should be interpreted as an empty instance of the type `V`. + +#### Arrays + +An array of `T` is encoded as a sequence of `T` values, separated by the *stride* of `T` (the size of `T` rounded up to the alignment of `T`). +The offset of the array is the offset of its first element. + +The number of elements in the array is encoded as a 4-byte unsigned integer stored immediately *before* the offset of the array itself. + +#### Strings + +A string is encoded in the same way that an array of 8-bit bytes would be (including the count stored before the first element). +The only additional detail is that the serialized data *must* include an additional nul byte after the last element of the string. + +The data of a string is assumed to be in UTF-8 encoding, but there is nothing about the format that validates or enforces this. + +#### Dictionaries + +A dictionary with keys of type `K` and values of type `V` is encoded in the same way as an array of `P`, where `P` is a two-element tuple of a `K` and a `V`. + +There is currently no provision made for efficient lookup of elements of a fossilized dictionary. + +#### Variants + +A *variant* is a fossilized value that can describe its own layout. + +The content of variant holding a value of type `T` is encoded exactly as a record with one field of type `T` would be, starting at the offset of the variant itself. + +The four bytes immediately preceding a variant store a relative pointer to the fossilized layout for the type `T` of the content. + +### Layouts + +Every layout starts with a 4-byte unsigned integer that holds a tag representing the kind of layout (see `Slang::FossilizedValKind`). +The value of the tag determines what, if any, information appears after the tag. + +In any place where a relative pointer to a layout is expected, a null pointer may be used to indicate that the relevant layout information is either unknown, or was elided from the fossilized data. + +#### Pointer-Like Types + +For pointers (`T*`) and optionals (`Optional`), the tag is followed by a relative pointer to a layout for `T`. + +#### Container Types + +For arrays and dictionaries, the tag is followed by: + +* A relative pointer to a layout for the element type + +* A 4-byte unsigned integer holding the stride between elements + +#### Record Types + +For records, the tag is followed by: + +* A 4-byte unsigned integer holding the number of fields, `N` + +* `N` 8-byte values representing the fields, each comprising: + + * A relative pointer to the type of the field + + * A 4-byte unsigned integer holding the offset of that field within the record + +The RIFF Support Code +===================== + +There is code in `source/core/slang-riff.{h,cpp}` that implements abastractions for reading and writing RIFF-structured files. + +The current RIFF implementation is trying to be "correct" for the RIFF format as used elsewhere (e.g., for `.wav` files), but it is unclear if this choice is actually helping us rather than hurting us. +It is likely that we will want to customize the format if we keep using (e.g., at the very least increase the minimum alignment of chunks). + +RIFF is a simple chunk-based file format that is used by things like WAV files, and has inspired many similar container formats used in media/games. + +The RIFF structures are currently being used for a few things: + +* The top-level structure of serialized files for slang modules, "module libraries". This design choice is being utilized so that the compiler can navigate the relevant structures and extract the parts it needs (e.g., just the digest of a module, but not the AST or IR). + +* Repro files are using a top-level RIFF container, but it is just to encapsulate a single blob of raw data (with internal offset-based pointers) + +* The structure of the IR and `SourceLoc` serialization formats uses RIFF chunks for their top-level structure, but doesn't really make use of the ability to navigate them in memory or perform random access. + +* The actual serialized AST format is currently a deep hierarchy of RIFF chunks. + +* There is also code for a RIFF-based hierarchical virtual file-system format, and that format is being used for the serialized core module (seemingly just because it includes support for LZ4; the actual "file system" that gets serialized seems to only have a single file in it). + +General-Purpose Hierarchical Data Serialization +=============================================== + +The code in `source/slang/slang-serialize.{h,cpp}` implements a framework for serialization that is intended to be lightweight for users to adopt, while also scaling to more complicated cases like our AST serialization. + +In the simplest cases, all a programmer needs to know is that if they have declared a type like: + + struct MyThing + { + float f; + List others; + SomeObject* obj; + }; + +then they can add serialization support for their type by writing a function like: + + void serialize(Serializer const& serializer, MyThing& value) + { + SLANG_SCOPED_SERIALIZER_STRUCT(serializer); + serialize(serializer, value.f); + serialize(serializer, value.others); + serialize(serializer, value.obj); + } + +If the `OtherThing` and `SomeObject` types were already set up with their own serialization support, then that should be all that's needed. +Of course there's a lot more to it in once you get into the details and the difficult cases. +For now, looking at `source/slang/slang-serialize.h` is probably the best way to learn more about the approach. + +One key goal of this serialization system is that it allows the serialized format to be swapped in and out without affecting the per-type `serialize` functions. +Currently there are only a small number of implementations. + +RIFF Serialization +------------------ + +The files `slang-serialize-riff.{h,cpp}` provide an implementation of the general-purpose serialization framework that reads/writes RIFF files with a particular kind of structure, based on what had previously been hard-coded for use in serializing the AST to RIFF. + +In practice this representation is kind of like an encoding of JSON as RIFF chunks, with leaf/data chunks for what would be leaf values in JSON, and container chunks for arrays and dictionaries (plus other aggregates that would translate into arrays or dictionaries in JSON). + +Fossil Serialization +-------------------- + +The files `slang-serialize-fossil.{h,cpp}` provide an implementation of the generla-purpose serialization framwork that reads/writes the "fossil" format, which is described earlier in this document. + +AST Serialization +================= + +AST serialization is implementation as an application of the general-purpose framework described above. +There is an `ASTSerializer` type that expands on `Serializer` to include the additional context that is needed for handling AST-related types like `SourceLoc`, `Name`, and the `NodeBase` hierarchy. + +The Old Serialization System +============================ + +The old serialization system has largely been removed, but some vestiges of it are still noticeable. + +There was an older serialization system in place that made use of an extensive RTTI system that types had to be registered with, plus a set of boilerplate macros for interfacing with that system that were generated from the C++ declarations of the AST node types. +That system was also predicated on the idea that to serialize a user C++ type `Foo`, one would also hand-author a matching C++ type `SerialFooData`, and then write code to translate a `Foo` to/from a `SerialFooData` plus code to read/write a `SerialFooData` from the actual serialized data format. + +The IR and `SourceLoc` serialization approaches are currently still heavily influenced by the old serialization system, and there are still vestigates of the RTTI infrastructure that was introduced to support it. +The hope is that as more subsystems are ported to use newer approaches to serialization, this code can all be eliminated. + +The following sections are older text that describes some of the formats that have not yet been revisited. + +IR Serialization +---------------- + +This mechanism is *much* simpler than generali serialization, because by design the IR types are very homogeneous in style. There are a few special cases, but in general an instruction consists of + +* Its type +* A SourceLoc +* 0 or more operands. +* 0 or more children. + +Within the IR instructions are pointers to IRInst derived types. As previously discussed serializing pointers directly is generally not a good idea. To work around this the pointers are turned into 32 bit indices. Additionally we know that an instruction can belong to at most one other instruction. + +When serializing out special handling is made for child instructions - their indices are made to be a contiguous range of indices for all instructions that belong to each parent. The indices are ordered into the same order as the children are held in the parent. By using this mechanism it is not necessary to directly save off the indices that belong to a parent, only the range of indices. + +The actual serialization mechanism is similar to the generalized mechanism - referenced objects are saved off in order of their indices. What is different is that the encoding fixes the size of the Inst to `IRSerialData`. That this can hold up to two operands, if the instruction has more than two operands then one of the UInt32 is the operand count and the other is an offset to a list of operands. It probably makes sense to alter this in the future to stream the instructions payload directly. + +IR serialization allows a simple compression mechanism, that works because much of the IR serialized data is UInt32 data, that can use a variable byte encoding. + +SourceLoc Serialization +----------------------- + +SourceLoc serialization presents several problems. Firstly we have two distinct serialization mechanisms that need to use it - IR serialization and generalized serialization. That being the case it cannot be saved directly in either, even though it may be referenced by either. + +To keep things simple for now we build up SourceLoc information for both IR and general serialization via their writers adding their information into a SerialSourceLocWriter. Then we can save this information into a RIFF section, that can be loaded before either general or IR deserialization is used. + +When reading the SourceLoc information has to be located and deserialized before any AST or IR deserialization. The SourceLoc data can then be turned into a SerialSourceLocReader, which is then either set on the `SerialReaders` `SerialExtraObjects`. Or passed to the `IRSerialReader`. diff --git a/lib/All/slang/share/doc/slang/design/stdlib-intrinsics.md b/lib/All/slang/share/doc/slang/design/stdlib-intrinsics.md new file mode 100644 index 0000000..2ea50cd --- /dev/null +++ b/lib/All/slang/share/doc/slang/design/stdlib-intrinsics.md @@ -0,0 +1,254 @@ +Core Module Intrinsics +====================== + +The following document aims to cover a variety of systems used to add target specific features. They are most extensively used in the slang core module. + +**NOTE!** These features should *not* be considered stable! They can be used in regular slang code to add features, but they risk breaking with any Slang version change. Additionally the features implementation can be very particular to what is required for a specific feature set, so might not work as expected in all scenarios. + +As these features are in flux, it is quite possible this document is behind the current features available within the Slang code base. + +If you want to add support for a feature for a target to Slang, implementing it as a part of the Slang standard modules is typically a good way to progress. Depending on the extension/feature it may not be possible to add support exclusively via changes to the standard module alone. That said most support for target specific extensions and features involve at least some changes to the slang standard modules including the core module, and typically using the mechanisms described here. + +## Core Module + +The main place these features are used are within the slang core module. This is implemented with a set of slang files within the slang project + +* core.meta.slang +* hlsl.meta.slang +* diff.meta.slang + +Looking at these files will demonstrate the features in use. + +Most of the intrinsics and attributes have names that indicate that they are not for normal use. This is typically via a `__` prefix. + +The `.meta.slang` files look largely like Slang source files, but their contents can also be generated programmatically with C++ code. A section of code can drop into `C++` code if it is proceeded by `${{{{`. The C++ section is closed with a closing `}}}}`. This mechanism is typically used to generate different versions of a similar code sequence. Values from the C++ code can be accessed via the `$()`, where the contents of the brackets specifies something that can be calculated from within the C++ code. + +As an example, to produce an an array with values 0 to 9 we could write... + +```slang + +// Slang code +${{{{ +// C++ code, calling out to a C++ function getTime, the result is held in variable time +int cppTime = getTime(); +}}}} + +// Back to Slang code, can access the C++ variable previously defined as cppTime. Due to $(). +// The code inside the $() is executed on the C++ side, so can do calculations. In practice it would be easier +// to just use call $(getTime() + 1), but this demonstrates variables are accessible. +int slangTime = $(cppTime + 1); +``` + +# Attributes + +## [__readNone] + +A `[__readNone]` indicates a function that computes its results strictly based on argument values, without reading or writing through any pointer arguments, or any other state that could be observed by a caller. + +## [__NoSideEffect] + +Specifies a function declaration has no observable side effects. + +## [__unsafeForceInlineEarly] + +Inlines the contained code, but does so very early stage. Being earlier allows allows some kinds of inlining transformations to work, that wouldn't work with regular inlining. It also means it must be used with *care*, because it may produce unexpected results for more complex scenarios. + +## [__NonCopyableType] + +Marks a type to be non-copyable, causing SSA pass to skip turning variables of the the type into SSA values. + +## [__AlwaysFoldIntoUseSiteAttribute] + +A call to the decorated function should always be folded into its use site. + +## [KnownBuiltin("name")] + +A `[KnownBuiltin("name")]` attribute allows the compiler to identify this declaration during compilation, despite obfuscation or linkage removing optimizations + +# Intrinsics + + +## __target_intrinsic(target, expansion) + +This is a widely used and somewhat complicated intrinsic. Placed on a declaration it describes how the declaration should be emitted for a target. The complexity is that `expansion` is applied via a variety of rules. `target` is a "target capability", commonly it's just the emit target for the intrinsic, so one of... + +* hlsl +* glsl +* cuda - CUDA +* cpp - C++ output (used for exe, shared-library or host-callable) + +* spirv - Used for slangs SPIR-V direct mechanism + +A function definition can have a `target_intrinsic` *and* a body. In that case, the body will be used for targets where the `target_intrinsic` isn't defined. + +If the intrinsic can be emitted as is, the expansion need not be specified. If only the *name* needs to changed (params can be passed as is), only the name to be expanded to needs to be specified *without* `()`. In this scenario it is not necessary to specify as a string in quotes, and just the identifier name can be used. + +Currently `HLSL` has a special handling in that it is *assumed* if a declaration exists that it can be emitted verbatim to HLSL. + +The target can also be a capability atom. The atoms are listed in "slang-capability-defs.h". + +What is perhaps of importance here is that for some features for a specific target can have multiple ways of achieving the same effect - for example "GL_NV_ray_tracing" and "GL_EXT_ray_tracing" are two different ray tracing extensions available for Vulkan through GLSL. The `-profile` option can disambiguate which extension is actually desired, and the capability with that name on the `target_intrinsic` specifies how to implement that feature for that specific extension. + +The expansion mechanism is implemented in "slang-intrinsic-expand.cpp" which will be most up to date. + +The `expansion` value can be a string or an identifier. If it is an identifier, it will just be emitted as is replacing the name of the declaration the intrinsics is associated with. + +Sections of the `expansion` string that are to be replaced are prefixed by the `$` sigil. + +* $0-9 - Indicates the parameter at that index. For a method call $0 is `this`. +* $T0-9 - The type for the param at the index. If the type is a texture resource derived type, returns the *element* type. +* $TR - The return type +* $G0-9 - Replaced by the type/value at that index of specialization +* $S0-9 - The scalar type of the generic at the index. +* $p - Used on texturing operations. Produces the combined texture sampler arguments as needed for GLSL. +* $C - The $C intrinsic is a mechanism to change the name of an invocation depending on if there is a format conversion required between the type associated by the resource and the backing ImageFormat. Currently this is only implemented on CUDA, where there are specialized versions of the RWTexture writes that will do a format conversion. +* $E - Sometimes accesses need to be scaled. For example in CUDA the x coordinate for surface access is byte addressed. $E will return the byte size of the *backing element*. +* $c - When doing texture access in GLSL the result may need to be cast. In particular if the underlying texture is 'half' based, GLSL only accesses (read/write) as float. So we need to cast to a half type on output. When storing into a texture it is still the case the value written must be half - but we don't need to do any casting there as half is coerced to float without a problem. +* $z - If we are calling a D3D texturing operation in the form t.Foo(s, ...), where `t` is a Texture<T>, then this is the step where we try to properly swizzle the output of the equivalent GLSL call into the right shape. +* $N0-9 - Extract the element count from a vector argument so that we can use it in the constructed expression. +* $V0-9 - Take an argument of some scalar/vector type and pad it out to a 4-vector with the same element type (this is the inverse of `$z`). +* $a - We have an operation that needs to lower to either `atomic*` or `imageAtomic*` for GLSL, depending on whether its first operand is a subscript into an array. This `$a` is the first `a` in `atomic`, so we will replace it accordingly. +* $A - We have an operand that represents the destination of an atomic operation in GLSL, and it should be lowered based on whether it is an ordinary l-value, or an image subscript. In the image subscript case this operand will turn into multiple arguments to the `imageAtomic*` function. +* $XP - Ray tracing ray payload +* $XC - Ray tracing callable payload +* $XH - Ray tracing hit object attribute +* $P - Type-based prefix as used for CUDA and C++ targets (I8 for int8_t, F32 - float etc) + +## __attributeTarget(astClassName) + +For an attribute, specifies the AST class (and derived class) the attribute can be applied to. + +## __builtin + +Identifies the declaration is being "builtin". + +## __builtin_requirement(requirementKind) + +A modifier that indicates a built-in associated type requirement (e.g., `Differential`). The requirement is one of `BuiltinRequirementKind`. + +The requirement value can just be specified via the `$()` mechanism. + +## __builtin_type(tag) + +Specifies a builtin type - the integer value of one of the enumeration BaseType. + +## __magic_type(clsName, tag) + +Used before a type declaration. The clsName is the name of the class that is used to represent the type in the AST in Slang *C++* code. The tag is an optional integer value that is in addition and meaningful in the context of the class type. + +##__intrinsic_type(op) + +Used to specify the IR opcode associated with a type. The IR opcode is listed as something like `$(kIROp_HLSLByteAddressBufferType)`, which will expand to the integer value of the opcode (because the opcode value is an enum value that is visible from C++). It is possible to just write the opcode number, but that is generally inadvisable as the ids for ops are not stable. If a code change in Slang C++ adds or removes an opcode the number is likely to be incorrect. + +As an example from the core module + +```slang +__magic_type(HLSLByteAddressBufferType) +__intrinsic_type($(kIROp_HLSLByteAddressBufferType)) +struct ByteAddressBuffer +{ + // ... +}; +``` + +# General + +## __generic<> + +Is an alternate syntax for specifying a declaration that is generic. The more commonly used form is to list the generic parameters in `<>` after the name of the declaration. + +## attribute_syntax + +Attribute syntax provides a mechanism to introduce an attribute type in Slang. + +Right now the basic form is: + +``` +attribute_syntax [name(parmName: paramType, ...)] : syntaxClass; +``` + +There can be 0 or more params associated with the attribute, and if so the () are not needed. + +* `name` gives the name of the attribute to define. +* `paramName` is the name of param that are specified with attribute use +* `paramType` is the type of the value associated with the param +* `syntaxClass` is the name of an AST node class that we expect this attribute to create when checked. + +For example + +``` +__attributeTarget(FuncDecl) +attribute_syntax [CudaDeviceExport] : CudaDeviceExportAttribute; +``` + +Defines an attribute `CudaDeviceExport` which can only be applied to FuncDecl or derived AST types. Once semantically checked will be turned into a `CudaDeviceExportAttribute` attribute in the AST. + +With a parameter + +``` +__attributeTarget(InterfaceDecl) +attribute_syntax [anyValueSize(size:int)] : AnyValueSizeAttribute; +``` + +Defines an attribute `anyValueSize` that can be applied to `InterfaceDecl` and derived types. It takes a single parameter called `anyValueSize` of `int` type. + +## Ref + +Allows returning or passing a value "by reference". + +# GLSL/Vulkan specific + +## __glsl_version(version) + +Used to specify the GLSL version number that is required for the subsequent declaration. When Slang emits GLSL source, the version at the start of the file, will be the largest version seen that emitted code uses. + +For example + +```slang +__glsl_version(430) +``` + +## __glsl_extension + +Specifies the GLSL extension that is required for the declaration to work. A declaration that has the intrinsic, when output to GLSL will additionally add `#extension` to the the GLSL or SPIR-V output. + +Multiple extensions can be applied to a decoration if that is applicable, if there are multiple ways of implementing that can be emitted in the same manner (see the section around [target](#target-intrinsic)) for more details. + +## __spirv_version + +When declaration is used for SPIR-V target will take the highest value seen to be the SPIR-V version required. For compilation through GLSLANG, the value is passed down to to GLSLANG specifying this SPIR-V is being targeted. + +Example + +``` +__spirv_version(1.3) +``` + +## vk::spirv_instruction + +Provides a way to use a limited amount of `GL_EXT_spirv_intrinsics` the extension. + +``` +vk::spirv_instruction(op, set) +``` + +Op is the integer *value* for the op. The `set` is optional string which specifies the instruction set the op is associated with. +For example + +``` +__specialized_for_target(glsl) +[[vk::spirv_instruction(1, "NonSemantic.DebugBreak")]] +void debugBreak(); +``` + +# CUDA specific + +## __cuda_sm_version + +When declaration is used with this intrinsic for a CUDA target, the highest shader model seen will be passed down to the downstream CUDA compile (NVRTC). + +# NVAPI + +## [__requiresNVAPI] + +If declaration is reached during a compilation for an applicable target (D3D11/12), will indicate that [NVAPI support](../nvapi-support.md) is required for declaration to work. diff --git a/lib/All/slang/share/doc/slang/diagnostic-guidelines.md b/lib/All/slang/share/doc/slang/diagnostic-guidelines.md new file mode 100644 index 0000000..a90299a --- /dev/null +++ b/lib/All/slang/share/doc/slang/diagnostic-guidelines.md @@ -0,0 +1,590 @@ +# Slang Compiler Diagnostic Guidelines + +## Overview + +The Slang compiler aims to provide clear, actionable, and user-friendly diagnostics that help developers quickly understand and fix issues in their code. These guidelines draw from best practices established by Rust, Clang, and Swift compilers while adapting them for Slang's specific needs. + +## Diagnostic Structure + +A complete diagnostic in Slang consists of: + +``` +error[E0000]: main error message + --> file.slang:LL:CC + | +LL | + | ^^^^ primary label + | +LL | + | -------------- secondary label + | + = note: additional context without a span + = help: suggestion for fixing the issue +``` + +### Core Components + +- **Level**: `error`, `warning`, `lint`, `remark` (plus attached `note`, `help`) +- **Error Code**: Optional identifier (e.g., `E0308`) for detailed documentation lookup +- **Message**: Concise description of the problem +- **Source Location**: File path, line, and column information +- **Code Snippet**: The affected code with visual indicators +- **Labels**: Primary and secondary spans with explanatory text +- **Sub-diagnostics**: Additional notes and suggestions +- **Documentation Links**: References to relevant language guide chapters + +## Diagnostic Levels + +### Error + +Emitted when the compiler cannot proceed with compilation: + +- Syntax errors +- Type mismatches that prevent code generation +- Unresolved symbols +- Constraint violations +- Missing interface implementations + +### Warning + +Emitted for problematic but compilable code: + +- Deprecated feature usage +- Unused variables or imports +- Potentially incorrect but syntactically valid code +- Code that may behave unexpectedly +- Can be turned into errors with `-werror` + +### Lint + +Off-by-default style or clarity guidelines: + +- Extraneous parentheses +- Style violations +- Code clarity improvements + +### Note + +Provides additional context for errors and warnings: + +- Related code locations +- Explanations of why something failed +- References to relevant language rules + +### Help + +Offers actionable suggestions: + +- How to fix the problem +- Alternative approaches +- Links to documentation + +### Remark + +Off-by-default informational messages: + +- Optimization hints +- Compilation progress information +- Performance suggestions +- Code generation notes + +## Writing Style Guidelines + +### Message Content + +1. **Be concise and precise** + + - ❌ "The compiler failed to find a matching type" + - ✅ "type mismatch: expected `int`, found `string`" + +2. **Use plain language** + + - Avoid compiler jargon when possible + - Define technical terms when necessary + - Write for developers who may be new to the language + +3. **Include relevant context** + +``` +error[E0277]: interface `IAddable` is not implemented for type `String` + --> file.slang:7:22 + | +4 | interface IAddable { This add(This other); } + | ---------------------- required by this interface +5 | String s1 = "hello"; +6 | String s2 = "world"; +7 | String result = add(s1, s2); + | ^^^ `add` requires `IAddable` interface +``` + +### Grammar and Formatting + +1. **No ending punctuation** for single-sentence messages + + - ✅ ``cannot find type `Foo` in this scope`` + - ❌ ``cannot find type `Foo` in this scope.`` + +2. **Use backticks** for code elements + + - Types: `` `float4` ``, `` `Texture2D` `` + - Identifiers: `` `myVariable` `` + - Keywords: `` `interface` ``, `` `struct` `` + +3. **Lowercase start** for messages + + - ✅ `missing semicolon` + - ❌ `Missing semicolon` + +4. **Active voice** when describing problems + + - ✅ ``function `foo` takes 2 arguments but 3 were provided`` + - ❌ ``3 arguments were provided but function `foo` takes 2`` + +5. **Use Oxford comma** in lists + + - ✅ `` expected one of `int`, `float`, or `double` `` + - ❌ `` expected one of `int`, `float` or `double` `` + +6. **Use correct articles** (a vs. an) + - ✅ `an interface` + - ✅ `a struct` + - ✅ ``an `IFoo` implementation`` + - ❌ `a interface` + +### Type Aliases and Underlying Types + +When type aliases are involved, show the underlying type when it helps clarify the error: + +``` +error[E0308]: type mismatch + --> file.slang:10:23 + | +10 | ColorRGBA color = 0.5; + | ^^^ expected `ColorRGBA` (aka `float4`), found `float` +``` + +Display options for controlling type alias expansion: + +- `-show-type-aliases=always`: Always show "aka" annotations +- `-show-type-aliases=helpful`: Show only when it clarifies (default) +- `-show-type-aliases=never`: Never expand type aliases + +## Error Codes + +### Format + +- Use a letter prefix followed by 5 digits: `E00001`, `W00001` +- Group related errors in ranges: + - **TBD** + +### Documentation + +**Each error code needs:** + +- Brief description +- Links to documentation + +**Optionally:** + +- Common causes +- Example code that triggers the error +- Suggested fixes + +## Suggestions and Fix-its + +### Applicability Levels + +1. **MachineApplicable**: Can be automatically applied + +``` +help: add missing semicolon + | +5 | return value; + | + +``` + +2. **HasPlaceholders**: Requires user input + +``` +help: specify the type explicitly + | +5 | let color: = value; + | +++++++++ +``` + +3. **MaybeIncorrect**: Suggestion might not be appropriate + +``` +help: consider adding the `[shader("compute")]` attribute + | +5 | [shader("compute")] + | +++++++++++++++++++ +6 | void main() { +``` + +### Guidelines for Suggestions + +- Provide fix-its only when confidence is high +- Show the exact change needed +- Use placeholders (``, ``) when user input is required +- Prefer showing code transformations over textual descriptions + +## Span and Location Information + +### Primary Spans + +- Point to the exact location of the error +- Keep spans as small as possible while remaining meaningful +- For multi-token constructs, highlight the most relevant part + +### Secondary Spans + +- Show related code that contributes to the error +- Use different labels to distinguish multiple spans +- Order spans by relevance, not just by source location + +### Example + +``` +error[E0308]: type mismatch in function call + --> file.slang:10:11 + | +8 | void expectInt(int x) { } + | ----- expected `int` here +9 | +10 | expectInt("hello"); + | ^^^^^^^ found `string` +``` + +## Error Cascading Prevention + +We shouldn't be generating many dependent errors from a single mistake. + +We should at least be checking that there are no additional error messages in all our diagnostic tests. At the moment we generally only check for the presence of the tested diagnostic. + +To avoid overwhelming users with follow-on errors: + +1. **Stop type-checking** in a scope after critical type errors +2. **Mark symbols as poisoned** when their definition has errors +3. **Limit error propagation** from generic instantiation failures +4. **Track error origins** to suppress duplicate reports + +Example: + +``` +error[E0412]: the type `MyTexture` is not defined + --> file.slang:5:5 + | +5 | MyTexture tex; + | ^^^^^^^^^ type not found + | + = note: subsequent errors involving `tex` have been suppressed +``` + +## Diagnostic Priority and Limits + +### Priority System + +When multiple errors exist, show them in this order: + +TBD + +1. Syntax errors +2. Import/module errors +3. Type definition errors +4. Interface implementation errors +5. Type mismatch errors +6. Other semantic errors +7. Warnings +8. Remarks + +### Error Limits + +- Configurable via `-max-errors=N` +- Show message when limit reached: + +``` + error: aborting due to 20 previous errors; use `-max-errors=N` to see more +``` + +## Lint System + +Lints are a good opportunity to attach fix-its for a LSP or LLM. + +### Lint Naming + +- Use snake_case +- Name should make sense with "allow": `allow unused_variables` +- Be specific about what is being checked +- Group related lints with common prefixes + +### Lint Levels + +1. **allow**: Off by default +2. **warn**: On by default, produces warnings +3. **deny**: On by default, produces errors + +### Lint Groups + +Define logical groups: + +- **style**: Code formatting and naming conventions + - NON_CAMEL_CASE_NAMES + - NON_UPPER_CASE_CONSTANTS + - INCONSISTENT_SPACING +- **correctness**: Potential bugs or incorrect usage +- **performance**: Performance-related suggestions + +## Special Diagnostic Features + +### Generic Type Diffing + +When dealing with complex generic types, highlight differences: + +``` +error[E0308]: type mismatch + = note: expected `RWStructuredBuffer` + found `RWStructuredBuffer` + ^^^^^^ types differ here +``` + +### Macro Expansion Context + +Show the expansion chain for errors in macros: + +``` +error[E0369]: invalid operation + --> file.slang:20:5 + | +20 | MY_MACRO!(x + y); + | ^^^^^^^^^^^^^^^^^ in this macro invocation + | + ::: macros.slang:5:10 + | +5 | $left + $right + | ^ cannot add these types +``` + +### Similar Name Suggestions + +``` +error[E0425]: cannot find `printn` in scope + --> file.slang:5:5 + | +5 | printn("hello"); + | ^^^^^^ not found + | + = help: a similar function exists: `println` +help: did you mean `println`? + | +5 | println("hello"); + | ~~~~~~~ +``` + +## IDE Integration + +### LSP-Specific Formatting + +Optimize diagnostics for Language Server Protocol: + +- Include `DiagnosticRelatedInformation` for secondary spans +- Provide `CodeAction` items for fix-its +- Support incremental diagnostic updates +- Include diagnostic tags (deprecated, unnecessary) + +### Inline Error Markup + +Specifications for IDE display: + +```json +{ + "severity": "error", + "range": { + "start": { "line": 10, "character": 5 }, + "end": { "line": 10, "character": 10 } + }, + "message": "undefined variable `count`", + "code": "E00123", + "codeDescription": { "href": "https://docs.shader-slang.org/errors/E00123" } +} +``` + +### Quick-Fix Protocol + +Standardized fix communication: + +```json +{ + "title": "Add missing interface implementation", + "kind": "quickfix", + "diagnostics": ["E00987"], + "edit": { + "changes": { + "file.slang": [ + { + "range": { "start": { "line": 15, "character": 0 } }, + "newText": "interface MyStruct : IRenderable {\n // implementation\n}\n" + } + ] + } + } +} +``` + +### Diagnostic Severity Mappings + +Map compiler levels to IDE severity: + +- `error` → `DiagnosticSeverity.Error` (1) +- `warning` → `DiagnosticSeverity.Warning` (2) +- `remark` → `DiagnosticSeverity.Information` (3) +- `note` → `DiagnosticSeverity.Hint` (4) + +## Internationalization + +TBD (can we use LLMs here?) + +## Testing Diagnostics + +### Diagnostic Verification + +TBD Test file syntax to be parsed and checked against machine readable output + +Filecheck style test descriptions, but can be tested using the machine readable output. + +``` +void test() { + int x = "string"; + // ERROR: type mismatch + // ^^^^^^^^ expected `int`, found `string` + // HELP: change the type annotation +} +``` + +### Test Coverage Requirements + +- Each diagnostic should have at least one test +- Test both positive and negative cases +- Verify fix-its compile successfully +- Check error recovery after applying suggestions + +## Progressive Disclosure + +### Beginner-Friendly Defaults + +- Show simple, actionable messages by default +- Hide implementation details unless relevant +- Provide links to learn more + +## Performance Considerations + +1. Don't compute expensive diagnostics unless needed +2. Avoid reporting the same error multiple times +3. Cache diagnostic messages for repeated errors +4. Use error limits to prevent runaway diagnostics + +## Command-Line Interface + +### Display Options + +- `-error-format=json`: Machine-readable output +- `-color=auto|always|never`: Control color output +- `-show-error-codes`: Display error codes +- `-explain E00001`: Show detailed error explanation +- `-verbose-diagnostics`: Show additional diagnostic information +- `-max-errors=N`: Set maximum error count +- `-show-type-aliases=always|helpful|never`: Control type alias display + +### Verbose Mode + +With `-verbose-diagnostics`: + +- Show full type signatures including type aliases +- Include compiler passes information +- Show all possible fixes, not just the most likely +- Display internal compiler state when relevant + +### Example JSON Output + +```json +{ + "level": "error", + "code": "E0308", + "message": "type mismatch", + "spans": [ + { + "file": "main.slang", + "line": 10, + "column": 15, + "text": "float3 color = float4(1, 0, 0, 1);", + "label": "expected `float3`, found `float4`" + } + ], + "children": [ + { + "level": "help", + "message": "use `.xyz` to extract the first three components", + "spans": [ + { + "file": "main.slang", + "line": 10, + "column": 35, + "suggestion": ".xyz" + } + ] + } + ], + "documentation_url": "https://docs.shader-slang.org/errors/E00345" +} +``` + +## Best Practices Checklist + +Before adding a new diagnostic: + +- [ ] Is the message clear and actionable? +- [ ] Is the span as precise as possible? +- [ ] Would a fix-it help? +- [ ] Error code +- [ ] Is the severity level appropriate? +- [ ] Are related locations shown with notes? +- [ ] Is the message properly capitalized and punctuated, grammar etc. +- [ ] Will this message make sense in different contexts? +- [ ] Have we considered error cascading? +- [ ] Is there a relevant documentation link? +- [ ] Does the documentation have examples? +- [ ] Have we added tests for this diagnostic? + +## Examples of Good Diagnostics + +### Type Mismatch + +``` +error[E0308]: mismatched types + --> src/main.slang:5:16 + | +4 | float3 expectVec3(float3 v) { return v; } + | ------- expected due to this parameter type +5 | expectVec3(float4(1, 0, 0, 1)); + | ^^^^^^^^^^^^^^^^^^^ expected `float3`, found `float4` + | + = help: use `.xyz` to extract the first three components + = note: see https://docs.shader-slang.org/types/vectors for vector swizzling +``` + +### Missing Interface Implementation + +``` +error[E0277]: type `String` doesn't implement interface `IArithmetic` + --> src/main.slang:10:24 + | +10 | String result = s1 + s2; + | ^ operator `+` requires `IArithmetic` interface + | + = note: the interface `IArithmetic` is not implemented for `String` + = note: string concatenation requires explicit method calls + = help: use `s1.concat(s2)` instead + = note: see https://docs.shader-slang.org/interfaces/operators +``` + +These guidelines should be treated as living documentation that evolves with the Slang compiler's needs and user feedback. Regular reviews and updates ensure diagnostics remain helpful and relevant. diff --git a/lib/All/slang/share/doc/slang/doc-system.md b/lib/All/slang/share/doc/slang/doc-system.md new file mode 100644 index 0000000..d552bf1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/doc-system.md @@ -0,0 +1,114 @@ +Slang Doc System +================ + +Slang contains a rudimentary documentation generation system. The mechanism used to mark up source is similar to [doxygen](https://www.doxygen.nl/manual/docblocks.html). Namely + +``` +/** + ... text ... (JavaDoc style) + */ +void someFunctionA() {} + +/*! + .. text .. (QT style) + another line + */ +void someFunctionB() {} + +/// ... text ... (Multi line) +/// another line +void someFunctionC() {} + +//!... text ... (QT Multi line) +//! another line +void someFunctionD() {} + +``` + +All of the above examples will add the documentation for the declaration that appears after them. Also note that this slightly diverges from doxygen in that an empty line before and after in a multi line comment is *not* required. + +We can also document the parameters to a function similarly + +``` +/// My function +void myFunction( + /// The A parameter + int a, + /// The B parameter + int b); +``` + +If you just need a single line comment to describe something, you can place the documentation after the parameter as in + +``` + +/// My function +void myFunction( int a, //< The A parameter + int b) //< The B parameter +{} +``` + +This same mechanisms work for other kinds of common situations such as with enums + +``` +/// An enum +enum AnEnum +{ + Value, ///< A value + /// Another value + /// With a multi-line comment + AnotherValue, +}; +``` + +Like `doxygen` we can also have multi line comments after a declaration for example + +``` +/// An enum +enum AnEnum +{ + Value, ///< A value + ///< Some more information about `Value` + + /// Another value + /// With a multi-line comment + AnotherValue, +}; +``` + + + + +To actually get Slang to output documentation you can use the `-doc` option from the `slangc` command line, or pass it in as parameter to `spProcessCommandLineArguments` or `processCommandLineArguments`. The documentation is currently output by default to the same `ISlangWriter` stream as diagnostics. So for `slangc` this will generally mean the terminal/stderr. + +Currently the Slang doc system does not support any of the 'advanced' doxygen documentation features. If you add documentation to a declaration it is expected to be in [markdown](https://guides.github.com/features/mastering-markdown/). + +Currently the only documentation style supported is a single file 'markdown' output. Future versions will support splitting into multiple files and linking between them. Also future versions may also support other documentation formats/standards. + +It is possible to generate documentation for the slang core module. This can be achieved with `slangc` via + +``` +slangc -doc -compile-core-module +``` + +The documentation will be written to a file `stdlib-doc.md`. + +It should be noted that it is not necessary to add markup to a declaration for the documentation system to output documentation for it. Without the markup the documentation is going to be very limited, in essence saying the declaration exists and other aspects that are available from the source. This may not be very helpful. For this reason and other reasons there is a mechanism to control the visibility of items in your source. + +There are 3 visibility levels 'public', 'internal' and 'hidden'/'private'. There is a special comment that controls visibility for subsequent lines. The special comment starts with `//@` as shown below. + +``` +//@ public: + +void thisFunctionAppearsInDocs() {} + +//@ internal: + +void thisFunctionCouldAppearInInternalDocs() {} + +//@ hidden: + +void thisFunctionWillNotAppearInDocs() {} +``` + + diff --git a/lib/All/slang/share/doc/slang/faq.md b/lib/All/slang/share/doc/slang/faq.md new file mode 100644 index 0000000..824d996 --- /dev/null +++ b/lib/All/slang/share/doc/slang/faq.md @@ -0,0 +1,42 @@ +Frequently Asked Questions +========================== + +### How did this project start? + +The Slang project forked off from the ["Spire"](https://github.com/spire-lang/spire) shading language research project. +In particular, Slang aims to take the lessons learned in that research effort (about how to make more productive shader compilation languages and tools) and apply them to a stystem that is easier to adopt, and hopefully more amenable to production use. + +### Why should I use Slang instead of glslang, hlsl2glslfork, the Microsoft open-source HLSL compiler, etc.? + +If you are mostly just shopping around for a tool to get HLSL shaders working on other graphics APIs, then [this](http://aras-p.info/blog/2014/03/28/cross-platform-shaders-in-2014/) blog post is probably a good place to start. + +If one of those tools meets your requirements, then you should probably use it. +Slang is a small project, and early in development, so you might find that you hit fewer bumps in the road with one of the more established tools out there. + +The goal of the Slang project is not to make "yet another HLSL-to-GLSL translator," but rather to create a shading language and supporting toolchain that improves developer productivity (and happiness) over the existing HLSL language and toolchain, while providing a reasonable adoption path for developers who have an existing investment in HLSL shader code. +If you think that is something interesting and worth supporting, then please get involved! + +### What would make a shading language more productive? + +This is probably best answered by pointing to the most recent publication from the Spire research project: + +[Shader Components: Modular and High Performance Shader Development](http://graphics.cs.cmu.edu/projects/shadercomp/) + +Some other papers for those who would like to read up on our inspiration: + +[A System for Rapid Exploration of Shader Optimization Choices](http://graphics.cs.cmu.edu/projects/spire/) +[Spark: Modular, Composable Shaders for Graphics Hardware](https://graphics.stanford.edu/papers/spark/) + +### Who is using Slang? + +Right now the only user of Slang is the [Falcor](https://github.com/NVIDIA/Falcor) real-time rendering framework developed and used by NVIDIA Research. +The implementation of Slang has so far focused heavily on the needs of Falcor. + +### Won't we all just be using C/C++ for shaders soon? + +The great thing about both Vulkan and D3D12 moving to publicly-documented binary intermediate languages (SPIR-V and DXIL, respectively) is that there is plenty of room for language innovation on top of these interfaces. + +Having support for writing GPU shaders in a reasonably-complete C/C++ language would be great. +We are supportive of efforts in the "C++ for shaders" direction. + +The Slang effort is about trying to solve the challenges that are unique to the real-time graphics domain, and that won't magically get better by switching to C++. diff --git a/lib/All/slang/share/doc/slang/gpu-feature/derivatives-in-compute/derivatives-in-compute.md b/lib/All/slang/share/doc/slang/gpu-feature/derivatives-in-compute/derivatives-in-compute.md new file mode 100644 index 0000000..038ea14 --- /dev/null +++ b/lib/All/slang/share/doc/slang/gpu-feature/derivatives-in-compute/derivatives-in-compute.md @@ -0,0 +1,9 @@ +### Derivatives In Compute +An entry point may be decorated with `[DerivativeGroupQuad]` or `[DerivativeGroupLinear]` to specify how to use derivatives in compute shaders. + +GLSL syntax may also be used, but is not recommended (`derivative_group_quadsNV`/`derivative_group_linearNV`). + +Targets: +* **_SPIRV:_** Enables `DerivativeGroupQuadsNV` or `DerivativeGroupLinearNV`. +* **_GLSL:_** Enables `derivative_group_quadsNV` or `derivative_group_LinearNV`. +* **_HLSL:_** Does nothing. `sm_6_6` is required to use derivatives in compute shaders. HLSL uses an equivalent of `DerivativeGroupQuad`. diff --git a/lib/All/slang/share/doc/slang/gpu-feature/texture/footprint-queries.md b/lib/All/slang/share/doc/slang/gpu-feature/texture/footprint-queries.md new file mode 100644 index 0000000..6e76414 --- /dev/null +++ b/lib/All/slang/share/doc/slang/gpu-feature/texture/footprint-queries.md @@ -0,0 +1,205 @@ +Texture Footprint Queries +========================= + +Slang supports querying the *footprint* of a texture sampling operation: the texels that would be accessed when performing that operation. +This feature is supported on Vulkan via the `GL_NV_shader_texture_footprint` extension, and on D3D12 via the `NvFootprint*` functions exposed by NVAPI. + +# Background + +There are many GPU rendering techniques that involve generating a texture (e.g., by rendering to it) and then sampling from that texture in a 3D rendering pass, such that it is difficult to predict *a priori* which parts of the texture will be accessed, or not. +As one example, consider rendering a shadow map that will be accessed when shading a g-buffer. +Depending on the geometry that was rendered into the g-buffer, and the occlusion that might exist, some parts of the shadow map might not be needed at all. + +In principle, an application could use a compute pass on the g-buffer to compute, for each pixel, the part of the shadow-map texture that it will access - its footprint. +The application could then aggregate these footprints into a stencil mask or other data structure that could be used to optimize the rendering pass that generates the shadow map. + +Unfortunately, it is almost impossible for applications to accurately and reliably predict the texel data that particular sampling operations will require, once non-trivial texture filtering modes are considered. +Sampling operations support a wide variety of state that affects the lookup and filtering of texels. For example: + +* When bilinear filtering is enabled, a sampling operation typically accesses the four texels closest to the sampling location and blends them. + +* When trilinear filtering is enabled, a sampling operation may access texels at two different mip levels. + +* When anisotropic filtering is enabled, a sampling operation may take up to N *taps* (where N is the maximum supported degree of anisotropy), each of which may itself access a neighborhood of texels to produce a filtered value for that tap. + +* When sampling a cube map, a sampling operation may straddle the "seam" between two or even three cube faces. + +Texture footprint queries are intended to solve this problem by providing application developers with a primitive that can query the footprint of a texture sampling operation using the exact same sampler state and texture coordinates that will be used when sampling the texture later. + +# Slang Shader API + +Rather than exactly mirror the Vulkan GLSL extension or the NVAPI functions, the Slang core module provides a single common interface that can map to either of those implementations. + +## Basics + +A typical 2D texture sampling operation is performed using the `Sample()` method on `Texture2D`: + +```hlsl +Texture2D texture = ...; +SamplerState sampler = ...; +float2 coords = ...; + +// Sample a 2D texture +float4 color = texture.Sample( + sampler, coords); +``` + +To query the footprint that would be accessed by this operation, we can use an operation like: + +```hlsl +uint granularity = ...; +TextureFootprint2D footprint = texture.queryFootprintCoarse(granularity, + sampler, coords); +``` + +Note that the same arguments used to call `Sample` above are here passed to `queryFootprint` in the exact same order. +The returned `footprint` encodes a conservative footprint of the texels that would be accessed by the equivalent `Sample` operation above. + +Texture footprints are encoded in terms of blocks of texels, and the size of those blocks determined the *granularity* of the footprint. +The `granularity` argument to `queryFootprintCoarse` above indicates the granularity of blocks that the application requests. + +In cases where a filtering operation might access two mip levels - one coarse and one fine - a footprint query only returns information about one of the two levels. +The application selects between these options by calling either `queryFootprintCoarse` or `queryFootprintFine`. + +## Variations + +A wide range of footprint queries are provided, corresponding to various cases of texture sampling operations with different parameters. +For 2D textures, the following functions are supported: + +```hlsl +TextureFootprint2D Texture2D.queryFootprintCoarse( + uint granularity, SamplerState sampler, float2 coords); +TextureFootprint2D Texture2D.queryFootprintFine( + uint granularity, SamplerState sampler, float2 coords); +TextureFootprint2D Texture2D.queryFootprintCoarseBias( + uint granularity, SamplerState sampler, float2 coords, + float lodBias); +TextureFootprint2D Texture2D.queryFootprintFineBias( + uint granularity, SamplerState sampler, float2 coords, + float lodBias); +TextureFootprint2D Texture2D.queryFootprintCoarseLevel( + uint granularity, SamplerState sampler, float2 coords, + float lod); +TextureFootprint2D Texture2D.queryFootprintFineLevel( + uint granularity, SamplerState sampler, float2 coords, + float lod); +TextureFootprint2D Texture2D.queryFootprintCoarseGrad( + uint granularity, SamplerState sampler, float2 coords, + float2 dx, float2 dy); +TextureFootprint2D Texture2D.queryFootprintFineGrad( + uint granularity, SamplerState sampler, float2 coords, + float2 dx, float2 dy); + +// Vulkan-only: +TextureFootprint2D Texture2D.queryFootprintCoarseClamp( + uint granularity, SamplerState sampler, float2 coords, + float lodClamp); +TextureFootprint2D Texture2D.queryFootprintFineClamp( + uint granularity, SamplerState sampler, float2 coords, + float lodClamp); +TextureFootprint2D Texture2D.queryFootprintCoarseBiasClamp( + uint granularity, SamplerState sampler, float2 coords, + float lodBias, + float lodClamp); +TextureFootprint2D Texture2D.queryFootprintFineBiasClamp( + uint granularity, SamplerState sampler, float2 coords, + float lodBias, + float lodClamp); +TextureFootprint2D Texture2D.queryFootprintCoarseGradClamp( + uint granularity, SamplerState sampler, float2 coords, + float2 dx, float2 dy, + float lodClamp); +TextureFootprint2D Texture2D.queryFootprintFineGradClamp( + uint granularity, SamplerState sampler, float2 coords, + float2 dx, float2 dy, + float lodClamp); +``` + +For 3D textures, the following functions are supported: + +```hlsl +TextureFootprint3D Texture3D.queryFootprintCoarse( + uint granularity, SamplerState sampler, float3 coords); +TextureFootprint3D Texture3D.queryFootprintFine( + uint granularity, SamplerState sampler, float3 coords); +TextureFootprint3D Texture3D.queryFootprintCoarseBias( + uint granularity, SamplerState sampler, float3 coords, + float lodBias); +TextureFootprint3D Texture3D.queryFootprintFineBias( + uint granularity, SamplerState sampler, float3 coords, + float lodBias); +TextureFootprint3D Texture3D.queryFootprintCoarseLevel( + uint granularity, SamplerState sampler, float3 coords, + float lod); +TextureFootprint3D Texture3D.queryFootprintFineLevel( + uint granularity, SamplerState sampler, float3 coords, + float lod); + +// Vulkan-only: +TextureFootprint3D Texture3D.queryFootprintCoarseClamp( + uint granularity, SamplerState sampler, float3 coords, + float lodClamp); +TextureFootprint3D Texture3D.queryFootprintFineClamp( + uint granularity, SamplerState sampler, float3 coords, + float lodClamp); +TextureFootprint3D Texture3D.queryFootprintCoarseBiasClamp( + uint granularity, SamplerState sampler, float3 coords, + float lodBias, + float lodClamp); +TextureFootprint3D Texture3D.queryFootprintFineBiasClamp( + uint granularity, SamplerState sampler, float3 coords, + float lodBias, + float lodClamp); +``` + +## Footprint Types + +Footprint queries on 2D and 3D textures return values of type `TextureFootprint2D` and `TextureFootprint3D`, respectively, which are built-in `struct`s defined in the Slang core module: + +``` +struct TextureFootprint2D +{ + typealias Anchor = uint2; + typealias Offset = uint2; + typealias Mask = uint2; + typealias LOD = uint; + typealias Granularity = uint; + + property anchor : Anchor { get; } + property offset : Offset { get; } + property mask : Mask { get; } + property lod : LOD { get; } + property granularity : Granularity { get; } + property isSingleLevel : bool { get; } +} + +struct TextureFootprint3D +{ + typealias Anchor = uint3; + typealias Offset = uint3; + typealias Mask = uint2; + typealias LOD = uint; + typealias Granularity = uint; + + property anchor : Anchor { get; } + property offset : Offset { get; } + property mask : Mask { get; } + property lod : LOD { get; } + property granularity : Granularity { get; } + property isSingleLevel : bool { get; } +} +``` + +A footprint is encoded in terms of *texel groups*, where the `granularity` determines the size of those groups. +When possible, the returned footprint will match the granularity passed into the query operation, but a larger granularity may be selected in cases where the footprint is too large to encode at the requested granularity. + +The `anchor` property specifies an anchor point in the texture, in the vicinity of the footprint. Its components are in multiples of 8 texel groups. + +The `offset` property specifies how the bits in `mask` map to texel groups in the vicinity of the `anchor` point. + +The `mask` property is a 64-bit bitfield (encoded as a `uint2`), where each bit represents footprint coverage of one texel group, within a 8x8 (for 2D textures) or 4x4x4 neighborhood of texel groups. + +The `lod` property indicates the mipmap level that would be accessed by the sampling operation. + +The `isSingleLevel` property indicates if the sampling operation is known to access only a single mip level. +Note that this property will always be `false` when using the D3D/NVAPI path. diff --git a/lib/All/slang/share/doc/slang/language-guide.md b/lib/All/slang/share/doc/slang/language-guide.md new file mode 100644 index 0000000..e2cab90 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-guide.md @@ -0,0 +1,259 @@ +Slang Language Guide +==================== + +This document will try to describe the main characteristics of the Slang language that might make it different from other shading languages you have used. + +The Basics +---------- + +Slang is similar to HLSL, and it is expected that many HLSL programs can be used as Slang code with no modifications. +Big-picture stuff that is supported: + +* A C-style preprocessor +* Ordinary function, `struct`, `typedef`, etc. declarations +* The standard vector/matrix types like `float3` and `float4x4` +* The less-used explicit `vector` and `matrix` types +* `cbuffer` declarations for uniform parameters +* Global-scope declarations of texture/sampler parameters, including with `register` annotations +* Entry points with varying `in`/`out` parameters using semantics (including `SV_*` system-value semantics) +* The built-in templated resource types like `Texture2D` with their object-oriented syntax for sampling operations +* Attributes like `[unroll]` are parsed, and passed along for HLSL/DXBC output, but dropped for other targets +* `struct` types that contain textures/samplers as well as ordinary uniform data, both as function parameters and in constant buffers +* The built-in functions up through Shader Model 6.0 (as documented on MSDN) are supported + +New Features +------------ + +### Import Declarations + +In order to support better software modularity, and also to deal with the issue of how to integrate shader libraries written in Slang into other languages, Slang introduces an `import` declaration construct. + +The basic idea is that if you write a file `foo.slang` like this: + +```hlsl +// foo.slang + +float4 someFunc(float4 x) { return x; } +``` + +you can then import this code into another file in Slang, HLSL, or GLSL: + +```hlsl +// bar.slang + +import foo; + +float4 someOtherFunc(float4 y) { return someFunc(y); } +``` + +The simplest way to think of it is that the `import foo` declaration instructs the compiler to look for `foo.slang` (in the same search paths it uses for `#include` files), and give an error if it isn't found. +If `foo.slang` is found, then the compiler will go ahead and parse and type-check that file, and make any declarations there visible to the original file (`bar.slang` in this example). + +When it comes time to generate output code, Slang will output any declarations from `import`ed files that were actually used (it skips those that are never referenced), and it will cross-compile them as needed for the chosen target. + +A few other details worth knowing about `import` declarations: + +* The name you use on the `import` line gets translated into a file name with some very simple rules. An underscore (`_`) in the name turns into a dash (`-`) in the file name, and dot separators (`.`) turn into directory separators (`/`). After these substitutions, `.slang` is added to the end of the name. + +* If there are multiple `import` declarations naming the same file, it will only be imported once. This is also true for nested imports. + +* Currently importing does not imply any kind of namespacing; all global declarations still occupy a single namespace, and collisions between different imported files (or between a file and the code it imports) are possible. This is a bug. + +* If file `A.slang` imports `B.slang`, and then some other file does `import A;`, then only the names from `A.slang` are brought into scope, not those from `B.slang`. This behavior can be controlled by having `A.slang` use `__exported import B;` to also re-export the declarations it imports from `B`. + +* An import is *not* like a `#include`, and so the file that does the `import` can't see preprocessor macros defined in the imported file (and vice versa). Think of `import foo;` as closer to `using namespace foo;` in C++ (perhaps without the same baggage). + +### Explicit Parameter Blocks + +One of the most important new features of modern APIs like Direct3D 12 and Vulkan is an interface for providing shader parameters using efficient *parameter blocks* that can be stored in GPU memory (these are implemented as descriptor tables/sets in D3D12/Vulkan, and "attribute buffers" in Metal). +However, HLSL and GLSL don't support explicit syntax for parameter blocks, and so shader programmers are left to manually pack parameters into blocks either using `register`/`layout` modifiers, or with API-based remapping (in the D3D12 case). + +Slang supports a simple and explicit syntax for exploiting parameter blocks: + +```hlsl +struct ViewParams +{ + float3 cameraPos; + float4x4 viewProj; + TextureCube envMap; +}; + +ParameterBlock gViewParams; +``` + +In this example, the fields of `gViewParams` will be assigned to registers/bindings in a way that supports allocating them into a single parameter block. +For example, when generating GLSL for Vulkan, the Slang compiler will generate a single `uniform` block (for `cameraPos` and `viewProj`) and a global `textureCube` for `envMap`, both decorated with the same `layout(set = ...)`. + + +### Interfaces + +Slang supports declaring `interface`s that user-defined `struct` types can implement. +For example, here is a simple interface for light sources: + +```hlsl +// light.slang + +struct LightSample { float3 intensity; float3 direction; }; + +interface ILight +{ + LightSample sample(float3 position); +} +``` + +We can now define a simple user type that "conforms to" (implements) the `ILight` interface: + +```hlsl +// point-light.slang + +import light; + +struct PointLight : ILight +{ + float3 position; + float3 intensity; + + LightSample sample(float3 hitPos) + { + float3 delta = hitPos - position; + float distance = length(delta); + + LightSample sample; + sample.direction = delta / distance; + sample.intensity = intensity * falloff(distance); + return sample; + } +} +``` + +### Generics + +Slang supports *generic* declarations, using the common angle-bracket (`<>`) syntax from languages like C#, Java, etc. +For example, here is a generic function that works with any type of light: + +```hlsl +// diffuse.slang +import light; + +float4 computeDiffuse( float4 albedo, float3 P, float3 N, L light ) +{ + LightSample sample = light.sample(P); + float nDotL = max(0, dot(N, sample.direction)); + return albedo * nDotL; +} +``` + +The `computeDiffuse` function works with any type `L` that implements the `ILight` interface. +Unlike with C++ templates, the `computeDiffuse` function can be compiled and type-checked once (you won't suddenly get unexpected error messages when plugging in a new type). + +#### Global-Scope Generic Parameters + +Putting generic parameter directly on functions is helpful, but in many cases existing HLSL shaders declare their parameters at global scope. +For example, we might have a shader that uses a global declaration of material parameters: + +```hlsl +Material gMaterial; +``` + +In order to allow such a shader to be converted to use a generic parameter for the material type (to allow for specialization), Slang supports declaring type parameters at the global scope: + +```hlsl +type_param M : IMaterial; +M gMaterial; +``` + +Conceptually, you can think of this syntax as wrapping your entire shader program in a generic with parameter ``. +This isn't beautiful syntax, but it may help when incrementally porting an existing HLSL codebase to use Slang's features. + +### Associated Types + +Sometimes it is difficult to define an interface because each type that implements it might need to make its own choice about some intermediate type. +As a concrete example, suppose we want to define an interface `IMaterial` for material surface shaders, where each material might use its own BRDF. +We want to support evaluating the *pattern* of the surface separate from the reflectance function. + +```hlsl +// A reflectance function +interface IBRDF +{ + float3 eval(float3 wi, float3 wo); +} +struct DisneyBRDF : IBRDF { ... }; +struct KajiyaKay : IBRDF { ... }; + +// a surface pattern +interface IMaterial +{ + ??? evalPattern(float3 position, float2 uv); +} +``` + +What is the type `???` that `evalPattern` should return? We know that it needs to be a type that supports `IBRDF`, but *which* type? +One material might want to use `DisneyBRDF` while another wants to use `KajiyaKay`. + +The solution in Slang, as in modern languages like Swift and Rust, is to use *associated types* to express the dependence of the BRDF type on the material type: + +```hlsl +interface IMaterial +{ + associatedtype B : IBRDF; + B evalPattern(float3 position, float2 uv); +} + +struct MyCoolMaterial : IMaterial +{ + typedef DisneyBRDF B; + B evalPattern(float3 position, float2 uv) + { ... } +} +``` + +Associated types are an advanced concept, and we only recommend using them when they are needed to define a usable interface. + + +Future Extensions +----------------- + +### Implicit Generics Syntax + +The syntax for generics and interfaces in Slang is currently explicit, but verbose: + +```hlsl +float4 computeDiffuse( L light, ... ) +{ ... } +``` + +As a future change, we would like to allow using an interface like `ILight` as an ordinary parameter type: + +```hlsl +float4 computeDiffuse( ILight light, ... ) +{ ... } +``` + +This simpler syntax would act like "syntactic sugar" for the existing explicit generics syntax, so it would retain all of the important performance properties. + +### Returning a Value of Interface Type + +While the above dealt with using an interface as a parameter type, we would eventually like to support using an interface as the *return* type of a function: + +```hlsl +ILight getALightSource(Scene scene) { ... } +``` + +Implementing this case efficiently is more challenging. In most cases, an associated type can be used instead when an interface return type would be desired. + + +Not Supported +------------- + +Some features of the current HLSL language are not supported, but probably will be given enough time/resources: + +* Local variables of texture/sampler type (or that contain these) +* Matrix swizzles +* Explicit `packoffset` annotations on members of `cbuffer`s + +Some things from HLSL are *not* planned to be supported, unless there is significant outcry from users: + +* Pre-D3D10 and D3D11 syntax and operations +* The "effect" system, and the related `<>` annotation syntax +* Explicit `register` bindings on textures/samplers nested in `cbuffer`s +* Any further work towards making HLSL a subset of C++ (simply because implementing a full C++ compiler is way out of scope for the Slang project) diff --git a/lib/All/slang/share/doc/slang/language-reference/README.md b/lib/All/slang/share/doc/slang/language-reference/README.md new file mode 100644 index 0000000..95bd6e5 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/README.md @@ -0,0 +1,19 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Slang Language Reference +======================== + +Contents +-------- + +* [Introduction](introduction.md) +* [Basic Concepts](basics.md) +* [Lexical Structure](lexical-structure.md) +* [Preprocessor](preprocessor.md) +* [Types](types.md) +* [Expressions](expressions.md) +* [Statements](statements.md) +* [Declarations](declarations.md) +* [Attributes](attributes.md) +* [Graphics Shaders and Compute Kernels](shaders-and-kernels.md) +* [Glossary](glossary.md) diff --git a/lib/All/slang/share/doc/slang/language-reference/attributes.md b/lib/All/slang/share/doc/slang/language-reference/attributes.md new file mode 100644 index 0000000..f4d900d --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/attributes.md @@ -0,0 +1,32 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Attributes +========== + +> Note: This section is not yet complete. + +## [[vk::spirv_instruction]] + +** SPIR-V only ** + +This attribute is only available for Vulkan SPIR-V output. + +The attribute allows access to SPIR-V intrinsics, by supplying a function declaration with the appropriate signature for the SPIR-V op and no body. The intrinsic takes a single parameter which is the integer value for the SPIR-V op. + +In the example below the add function, uses the mechanism to directly use the SPIR-V integer add 'op' which is 128 in this case. + +```HLSL +// 128 is OpIAdd in SPIR-V +[[vk::spirv_instruction(128)]] +uint add(uint a, uint b); + +RWStructuredBuffer resultBuffer; + +[numthreads(4,1,1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + uint threadId = dispatchThreadID.x; + resultBuffer[threadId] = add(threadId, threadId); +} +``` + diff --git a/lib/All/slang/share/doc/slang/language-reference/basics-behavior.md b/lib/All/slang/share/doc/slang/language-reference/basics-behavior.md new file mode 100644 index 0000000..d492fbf --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics-behavior.md @@ -0,0 +1,33 @@ +# Program Behavior + +## Observable behavior {#observable} + +TODO + +## Classification of Behavior {#classification} + +Slang classifies the observable behavior of a program as follows: + +1. **Precisely defined.** The observable behavior is defined precisely for all targets. Examples of precisely + defined behavior: + - Basic [unsigned integer](types-fundamental.md#integer) operations such as addition, subtraction, + multiplication. +2. **Implementation-defined.** The observable behavior is defined by the target and it is documented. The target + consists of the shader compilation target, the declared extensions, and the target device with + drivers. Examples of implementation-defined behavior: + - Size of [bool](types-fundamental.md#boolean) + - Evaluation of [floating point](types-fundamental.md#floating) numbers. For example, whether the target + implements [IEEE 754-2019](https://doi.org/10.1109/IEEESTD.2019.8766229) standard or something else. + - Memory layout when composed from fundamental types + - Target capabilities + - Available texture types and operations +3. **Unspecified.** The observable behavior is defined by the target but documentation is not + required. Examples of unspecified behavior: + - The bit-exact formulae for texture sampling algorithms + - Memory layouts of opaque types and their underlying data +4. **Undefined.** The program behavior is undefined. No guarantees are made. Possible results include a + program crash; data corruption; and differing computational results depending on optimization level, target + language/driver/device, or timing. Examples of undefined behavior: + - Data race + - Out-of-bounds memory access + - Application use of Slang internal language features diff --git a/lib/All/slang/share/doc/slang/language-reference/basics-execution-divergence-reconvergence.md b/lib/All/slang/share/doc/slang/language-reference/basics-execution-divergence-reconvergence.md new file mode 100644 index 0000000..7a8ecfa --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics-execution-divergence-reconvergence.md @@ -0,0 +1,189 @@ +# Execution Divergence and Reconvergence + +Threads are said to be on a *uniform path* or *converged path* when either their execution has not diverged or +it has reconverged. When the threads are on a uniform path, the control flow is said to be *uniform*. + +In structured control flow, divergence occurs when threads take different control flow +paths on conditional branches. Threads reconverge when the branches join. + +Control flow uniformity is considered in the following scopes: +- *Thread-group-uniform path*: all threads in the thread group are on a uniform path. +- *Wave-uniform path*: all threads in the wave are on a uniform path. + +In addition, a *mutually convergent* set of threads refers to the threads in a wave that are on a mutually +uniform path. When the execution has diverged, there is more than one such set. + + +> 📝 **Remark 1:** All threads start on uniform control flow at the shader entry point. + +> 📝 **Remark 2:** In SPIR-V terminology: uniform control flow (or converged control flow) is the state when +> all threads execute the same +> [dynamic instance](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#DynamicInstance) of an +> instruction. + +> 📝 **Remark 3:** Uniformity does not mean synchronicity. Even when the threads are on a uniform path, it +> does not mean that their progress is uniform. In particular, threads in a wave are not guaranteed to execute +> in lockstep, even if the programming model follows SIMT. Synchronization can be forced with a control flow +> barrier, but this usually incurs a performance overhead. + +> 📝 **Remark 4:** Avoiding long divergent execution paths is often a good strategy to improve performance. + + +## Divergence and Reconvergence in Structured Control Flow {#divergence} + +**`if` statements:** + +Divergence occurs when some threads take the *then* branch and others take the *else* +branch. Reconvergence occurs when threads exit the *then* and *else* branches. + +Example 1: +```hlsl +// divergence occurs when some threads evaluate +// the condition as `true` and others as `false` +if (cond) +{ + // "then" path +} +else +{ + // "else" path +} +// reconvergence +``` + +Example 2: +```hlsl +// divergence occurs when some threads evaluate +// the condition as `true` and others as `false` +if (cond) +{ + // "then" path +} +// reconvergence +``` + +> 📝 **Remark**: There is no divergence when all threads take the same branch. + + +**`switch` statements:** + +Divergence occurs when threads jump to different case groups. Reconvergence occurs when threads exit the +switch statement. Additionally, reconvergence between threads on adjacent case label groups occurs on a switch +case fall-through. + +A case group is the set of case labels that precede the same non-empty statement. + +Example 1: +```hlsl +// divergence occurs when threads jump to different +// case label groups: +switch (value) +{ +// first case group +case 0: +case 2: + doSomething1(); + break; + +// second case group +case 1: + doSomething2(); + break; + +// third case group +case 3: +default: + doSomething3(); + break; +} +// reconvergence +``` + +Example 2: +```hlsl +// divergence occurs when threads jump to different +// case label groups: +switch (value) +{ +case 0: // first case group + doSomething1(); + // fall-through + +case 1: // second case group + // reconvergence between the first and + // the second case group + doSomething2(); + + // fall-through + +default: // third case group + + // reconvergence between the second and the third case group + // + // all threads are now on the same path + + doSomething3(); + break; +} +// no reconvergence here, since it already happened in +// the default case group. +``` + +**Loop statements:** + +Divergence occurs when some threads exit a loop while the rest continue. Reconvergence occurs when all +threads have exited the loop. + +Example 1: +```hlsl +[numthreads(128,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + uint numLoops = 50 + (threadId.x & 1); + for (uint i = 0; i < numLoops; ++i) + { + // divergence after 50 iterations: + // - even-numbered threads exit the loop + // - odd-numbered threads continue for one more iteration + } + // reconvergence +} +``` + +## Thread-Group-Tangled Functions on Divergent Paths + +Thread-group-tangled functions are supported only on thread-group-uniform paths. It is +[undefined behavior](basics-behavior.md#classification) to invoke a thread-group-tangled function on a +divergent path. + + +## Wave-Tangled Functions on Divergent Paths + +The wave-tangled functions require special consideration when the execution within the wave has diverged: +1. Not all targets support wave-tangled functions on divergent paths. When unsupported, the results are + [undefined](basics-behavior.md#classification) when invoked on divergent paths. See + [target platforms](../target-compatibility.md) for details. +2. When supported, wave-tangled functions apply only between the mutually convergent thread + set by default. That is, synchronization occurs between those threads that are on the same path. + +Example 1: +```hlsl +[numthreads(128,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + uint minimumThreadId = 0; + + // trigger divergence + if ((threadId.x & 1) == 0) + { + // smallest thread id that took the 'then' branch + minimumThreadId = WaveActiveMin(threadId.x); + } + else + { + // smallest thread id that took the 'else' branch + minimumThreadId = WaveActiveMin(threadId.x); + } + // reconvergence +} +``` diff --git a/lib/All/slang/share/doc/slang/language-reference/basics-memory-model.md b/lib/All/slang/share/doc/slang/language-reference/basics-memory-model.md new file mode 100644 index 0000000..e86014c --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics-memory-model.md @@ -0,0 +1,3 @@ +# Memory Model + +TODO diff --git a/lib/All/slang/share/doc/slang/language-reference/basics-program-execution.md b/lib/All/slang/share/doc/slang/language-reference/basics-program-execution.md new file mode 100644 index 0000000..aa64999 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics-program-execution.md @@ -0,0 +1,102 @@ +# Program Execution + +At a high level, Slang program execution is defined as follows: + +1. Workload for a Slang program is *dispatched* (compute) or *launched* (graphics). +2. The dispatched or launched workload is divided into entry point *invocations*, which are executed by + *threads*. + +An individual entry point invocation handles one point of parametric input. The input parameters and the entry +point return value are specific to the types of the entry points. For example: +- A fragment shader entry point is invoked once per rasterized fragment. The set of entry point invocations is + determined by the rasterizer. Per-invocation inputs for the fragment shader come from the rasterizer and the + vertex shader stage. The output of a fragment shader is a per-fragment value. For example, a vector with + red/green/blue/alpha color components for an RGBA render target. +- A compute kernel entry point is invoked once per user-defined input parameter point. The inputs are the + *thread coordinates* that identify the invocation. A compute kernel has no intrinsic output. Instead, it + stores the results in output buffers. + +Inputs and outputs of different graphics shaders and compute kernels are described in more detail in [graphics +shaders and compute kernels](shaders-and-kernels.md). + +The graphics launches are determined by the draw calls and the graphics pipeline configuration. How a launch +is precisely divided into shader entry point invocations depends on the target. + +A compute dispatch is explicit, and it has an application-defined subdivision structure. For a compute +dispatch, the application defines the input parameter space as a grid of thread groups as follows: + +1. A compute dispatch is a user-specified 3-dimensional set of integer-valued points. The user passes a + 3-dimensional grid dimension vector `grid_dim`, which specifies the grid points `g` such that + `0`≤`g.x`<`grid_dim.x`, `0`≤`g.y`<`grid_dim.y`, `0`≤`g.z`<`grid_dim.z`. +2. For every point in the grid, a thread group is instantiated. The thread group size is similarly specified + with a 3-dimensional vector `group_dim`. Within the thread group, individual thread invocations `b` are + instantiated such that `0`≤`b.x`<`group_dim.x`, `0`≤`b.y`<`group_dim.y`, + `0`≤`b.z`<`group_dim.z`. The thread group dimensions are typically specified in the compute entry + point as an attribute or as compute dispatch parameters. +3. An individual invocation is executed by an individual thread for every grid and thread group point + combination. There are a total of + `grid_dim.x`\*`grid_dim.y`\*`grid_dim.z`\*`group_dim.x`\*`group_dim.y`\*`group_dim.z` invocations per + dispatch. + +In both graphics launches and compute dispatches, individual invocations are grouped into waves. The wave size +is a power-of-two in the range [4, 128] and is defined by the target. + +In graphics launches, waves are formed from the launch by a target-defined mechanism. They need not have +more in common than that they belong in the same pipeline stage using the same entry point. In particular, a +wave in a fragment stage may process fragments from different geometric primitives. + +In compute dispatches, a wave is subdivided from a thread group in a target-defined manner. Usually, a wave +consists of adjacent invocations, but in general, the application should not make any assumptions about the +wave shapes. + +Some waves may be only partially filled when the compute thread group or the graphics launch does not align +with the wave size. In compute dispatches, the thread group size should generally be a multiple of the wave +size for best utilization. + + +# Thread Group Execution Model + +All threads within a thread group execute on the same set of execution resources. This allows a thread group +to share local memory allocated with the `groupshared` attribute. Related barriers include +`GroupMemoryBarrier()` and `GroupMemoryBarrierWithGroupSync()`. + +The thread group execution model applies only to compute kernels. + + +# Wave Execution Model + +All threads in a wave execute in the single instruction, multiple threads (SIMT) model. + +Threads in a wave can synchronize and share data efficiently using *wave-tangled* functions such as ballots, +reductions, shuffling, control flow barriers with the wave scope, and similar operations. For example, atomic +memory accesses to the same memory location by multiple threads can often be coalesced within the wave and +then performed by a single thread. This can significantly reduce the number of atomic memory accesses, and +thus, increase performance. + +Wave-tangled functions operate over all participating threads in the wave. In general, the inputs for a +wave-tangled function are the inputs of all participating threads, and similarly, the outputs of a +wave-tangled function are distributed over the participating threads executing the function. + +Usually, the participating threads are the active threads on a [mutually convergent +path](basics-execution-divergence-reconvergence.md). + +The threads within a wave belong to one of the following classes: +- *active thread*---a thread that participates in producing a result. +- *inactive thread*---a thread that does not produce any side effects. A thread can be inactive for one of the + following reasons: + - The thread is not executing the [current path](basics-execution-divergence-reconvergence.md#divergence). + - The wave could not be fully utilized when assigning threads. + - The thread has executed a `discard` statement, which disables the thread (fragment shaders only). +- *helper thread*---a thread that is used to compute derivatives, typically for fragment quads. A helper + thread does not produce any other side effects, and it does not participate in wave-tangled functions unless + otherwise stated. + +Despite the SIMT execution model, Slang does not require that wave invocations execute in lockstep, unless +they are on a mutually convergent control flow path and they are executing synchronizing functions such as +control flow barriers (*e.g.*, `GroupMemoryBarrierWithWaveSync()`). + +> 📝 **Remark 1:** The actual execution hardware may or may not be implemented using an SIMT instruction +> set. In particular, a CPU target would generally not use SIMT instructions. + +> 📝 **Remark 2:** In SPIR-V terminology, wave-tangled functions are called *tangled instructions* with the +> subgroup scope. diff --git a/lib/All/slang/share/doc/slang/language-reference/basics-translation-overview.md b/lib/All/slang/share/doc/slang/language-reference/basics-translation-overview.md new file mode 100644 index 0000000..c815f04 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics-translation-overview.md @@ -0,0 +1,3 @@ +# Translation Overview + +TODO diff --git a/lib/All/slang/share/doc/slang/language-reference/basics.md b/lib/All/slang/share/doc/slang/language-reference/basics.md new file mode 100644 index 0000000..b35f9eb --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/basics.md @@ -0,0 +1,9 @@ +# Basic Concepts + +TODO: Add overview + +* [Translation overview](basics-translation-overview.md) +* [Program Execution](basics-program-execution.md) +* [Execution Divergence and Reconvergence](basics-execution-divergence-reconvergence.md) +* [Memory Model](basics-memory-model.md) +* [Program Behavior](basics-behavior.md) diff --git a/lib/All/slang/share/doc/slang/language-reference/declarations.md b/lib/All/slang/share/doc/slang/language-reference/declarations.md new file mode 100644 index 0000000..15c934b --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/declarations.md @@ -0,0 +1,776 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Declarations +============ + +Modules +------- + +A module consists of one or more source units that are compiled together. +The global declarations in those source units comprise the body of the module. + +In general, the order of declarations within a source unit does not matter; declarations can refer to other declarations (of types, functions, variables, etc.) later in the same source unit. +Declarations (other than `import` declarations) may freely be defined in any source unit in a module; declarations in one source unit of a module may freely refer to declarations in other source units. + +Imports +------- + +An import declaration is introduced with the keyword `import`: + +```hlsl +import Shadowing; +``` + +An import declaration searches for a module matching the name given in the declaration, and brings the declarations in that module into scope in the current source unit. + +> Note: an `import` declaration only applies to the scope of the current source unit, and does *not* import the chosen module so that it is visible to other source units of the current module. + +The name of the module being imported may use a compound name: + +```hlsl +import MyApp.Shadowing; +``` + +The mechanism used to search for a module is implementation-specific. + +> Note: The current Slang implementation searches for a module by translating the specified module name into a file path by: +> +> * Replacing any dot (`.`) separators in a compound name with path separators (e.g., `/`) +> +> * Replacing any underscores (`_`) in the name with hyphens (`-`) +> +> * Appending the extension `.slang` +> +> The implementation then looks for a file matching this path on any of its configured search paths. +> If such a file is found it is loaded as a module comprising a single source unit. + +The declarations of an imported module become visible to the current module, but they are not made visible to code that later imports the current module. + +> Note: An experimental feature exists for an "exported" import declaration: +> +> ```hlsl +> // inside A.slang +> __exported import Shadowing; +> ``` +> +> This example imports the declarations from `Shadowing` into the current module (module `A`), +> and also sets up information so that if other code declares `import A` then it can see +> both the declarations in `A` and those in `Shadowing`. + +> Note: Mixing `import` declarations and traditional preprocessor-based (`#include`) modularity +> in a codebase can lead to surprising results. +> +> Some things to be aware of: +> +> * Preprocessor definitions in your module do *not* affect the code of modules you `import`. +> +> * Preprocessor definitions in a module you `import` do *not* affect your code +> +> * The above caveats also apply to "include guards" and `#pragma once`, since they operate at the granularity of a source unit (not across modules) +> +> * If you `import` two modules, and then both `#include` the same file, then those two modules may end up with duplicate declarations with the same name. +> +> As a general rule, be wary of preprocessor use inside of code meant to be an `import`able module. + +Variables +--------- + +Variables are declared using the keywords `let` and `var`: + +```hlsl +let x = 7; +var y = 9.0; +``` + +A `let` declaration introduces an immutable variable, which may not be assigned to or used as the argument for an `in out` or `out` parameter. +A `var` declaration introduces a mutable variable. + +An explicit type may be given for a variable by placing it after the variable name and a colon (`:`): + +```hlsl +let x : int = 7; +var y : float = 9.0; +``` + +If no type is specified for a variable, then a type will be inferred from the initial-value expression. +It is an error to declare a variable that has neither a type specifier or an initial-value expression. +It is an error to declare a variable with `let` without an initial-value expression. + +A variable declared with `var` may be declared without an initial-value expression if it has an explicit type specifier: + +``` +var y : float; +``` + +In this case the variable is _uninitialized_ at the point of declaration, and must be explicitly initialized by assigning to it. +Code that uses the value of an uninitialized variable may produce arbitrary results, or even exhibit undefined behavior depending on the type of the variable. +Implementations *may* issue an error or warning for code that might make use of an uninitialized variable. + +### Traditional Syntax + +Variables may also be declared with traditional C-style syntax: + +```hlsl +const int x = 7; +float y = 9.0; +``` + +For traditional variable declarations a type must be specified. + +> Note: Slang does not support an `auto` type specifier like C++. + +Traditional variable declarations are immutable if they are declared with the `const` modifier, and are otherwise mutable. + +### Variables at Global Scope + +Variables declared at global scope may be either a global constant, a static global variables, or a global shader parameters. + +#### Global Constants + +A variable declared at global scope and marked with `static` and `const` is a _global constant_. + +A global constant must have an initial-value expression, and that initial-value expression must be a compile-time constant expression. + +#### Static Global Variables + +A variable declared at global scope and marked with `static` (but not with `const`) is a _static global variable_. + +A static global variable provides storage for each invocation executing an entry point. +Assignments to a static global variable from one invocation do not affect the value seen by other invocations. + +> Note: the semantics of static global variable are similar to a "thread-local" variable in other programming models. + +A static global variable may include an initial-value expression; if an initial-value expression is included it is guaranteed to be evaluated and assigned to the variable before any other expression that references the variable is evaluated. +There is no guarantee that the initial-value expression for a static global variable is evaluated before entry point execution begins, or even that the initial-value expression is evaluated at all (in cases where the variable might not be referenced at runtime). + +> Note: the above rules mean that an implementation may perform dead code elimination on static global variables, and may choose between eager and lazy initialization of those variables at its discretion. + +#### Global Shader Parameters + +A variable declared at global scope and not marked with `static` (even if marked with `const`) is a _global shader parameter_. + +Global shader parameters are used to pass arguments from application code into invocations of an entry point. +The mechanisms for parameter passing are specific to each target platform. + +> Note: Currently only global shader parameters of opaque types or arrays of opaque types are supported. + +A global shader parameter may include an initial-value epxression, but such an expression does not affect the semantics of the compiled program. + +> Note: Initial-value expressions on global shader parameters are only useful to set up "default values" that can be read via reflection information and used by application code. + +### Variables at Function Scope + +Variables declared at _function scope_ (in the body of a function, initializer, subscript accessor, etc.) may be either a function-scope constant, function-scope static variable, or a local variable. + +#### Function-Scope Constants + +A variable declared at function scope and marked with both `static` and `const` is a _function-scope constant_. +Semantically, a function-scope constant behaves like a global constant except that is name is only visible in the local scope. + +#### Function-Scope Static Variables + +A variable declared at function scope and marked with `static` (but not `const`) is a _function-scope static variable_. +Semantically, a function-scope static variable behaves like a global static variable except that its name is only visible in the local scope. + +The initial-value expression for a function-scope static variable may refer to non-static variables in the body of the function. +In these cases initialization of the variable is guaranteed not to occur until at least the first time the function body is evaluated for a given invocation. + +#### Local Variables + +A variable declared at function scope and not marked with `static` (even if marked with `const`) is a _local variable_. +A local variable has unique storage for each _activation_ of a function by an invocation. +When a function is called recursively, each call produces a distinct activation with its own copies of local variables. + +Functions +--------- + +Functions are declared using the `func` keyword: + +```hlsl +func add(x: int, y: float) -> float { return float(x) + y; } +``` + +Parameters +---------- + +The parameters of the function are declared as `name: type` pairs. + +Parameters may be given a _default value_ by including an initial-value-expression clause: + +```hlsl +func add(x: int, y: float = 1.0f) { ... } +``` + +Parameters may be marked with a _direction_ which affects how data is passed between caller and callee: + +```hlsl +func add(x: in out int, y : float) { x += ... } +``` + +The available directions are: + +* `in` (the default) indicates typical pass-by-value (copy-in) semantics. The callee receives a *copy* of the argument passed by the caller. + +* `out` indicates copy-out semantics. The callee writes to the parameter and then a copy of that value is assigned to the argument of the caller after the call returns. + +* `in out` or `inout` indicates pass-by-value-result (copy-in and copy-out) semantics. The callee receives a copy of the argument passed by the caller, it may manipulate the copy, and then when the call returns the final value is copied back to the argument of the caller. + +An implementation may assume that at every call site the arguments for `out` or `in out` parameters never alias. +Under those assumptions, the `out` and `inout` cases may be optimized to use pass-by-reference instead of copy-in and copy-out. + +> Note: Applications that rely on the precise order in which write-back for `out` and `in out` parameters is performed are already on shaky semantic ground. + +Body +---- + +The _body_ of a function declaration consists of statements enclosed in curly braces `{}`. + +In some cases a function declaration does not include a body, and in these cases the declaration must be terminated with a semicolon (`;`): + +```hlsl +func getCount() -> int; +``` + +> Note: Slang does not require "forward declaration" of functions, although +> forward declarations are supported as a compatibility feature. +> +> The only place where a function declaration without a definition should be +> required is in the body of an `interface` declaration. + + +The result type of a function mayb be specified after the parameter list using a _result type clause_ consisting of an arrow (`->`) followed by a type. +If the function result type is `void`, the result type clause may be elided: + +```hlsl +func modify(x: in out int) { x++; } +``` + + +### Traditional Syntax + +Functions can also be declared with traditional C-style syntax: + +```hlsl +float add(int x, float y) { return float(x) + y; } + +void modify(in out int x) { x ++; } +``` + +> Note: Currently traditional syntax must be used for shader entry point functions, +> because only the traditional syntax currently supports attaching semantics to +> parameters. + +### Entry Points + +An _entry point_ is a function that will be used as the starting point of execution for one or more invocations of a shader. + + + +Structure Types +--------------- + +Structure types are declared using the `struct` keyword: + +```hlsl +struct Person +{ + var age : int; + float height; + + int getAge() { return age; } + func getHeight() -> float { return this.height; } + static func getPopulation() -> int { ... } +} +``` + +The body of a structure type declaration may include variable, type, function, and initializer declarations. + +### Fields + +Variable declarations in the body of a structure type declaration are also referred to as _fields_. + +A field that is marked `static` is shared between all instances of the type, and is semantically like a global variable marked `static`. + +A non-`static` field is also called an _instance field_. + +### Methods + +Function declarations in the body of a structure type declaration are also referred to as _methods_. + +A method declaration may be marked `static`. +A `static` method must be invoked on the type itself (e.g., `Person.getPopulation()`). + +A non-`static` method is also referred to as an _instance method_. +Instance methods must be invoked on an instance of the type (e.g., `somePerson.getAge()`). +The body of an instance method has access to an implicit `this` parameter which refers to the instance on which the method was invoked. + +By default the `this` parameter of an instance method acts as an immutable variable. +An instance method with the `[mutating]` attribute receives a mutable `this` parameter, and can only be invoked on a mutable value of the structure type. + +### Inheritance + +A structure type declaration may include an _inheritance clause_ that consists of a colon (`:`) followed by a comma-separated list of interface types that the structure type inherits from: + +``` +struct Person : IHasAge, IHasName +{ .... } +``` + +When a structure type declares that it inherits from an interface, the programmer asserts that the structure type implements the required members of the interface. + +Currently only interface types may be named in the inheritance clause of a structure type. +A structure type may inherit from multiple interfaces. + +> Note: In language versions prior to Slang 2026, struct-to-struct inheritance was permitted but generates a compiler warning. +> In Slang 2026 and later, struct-to-struct inheritance is not supported and generates an error. + +### Syntax Details + +A structure declaration does *not* need to be terminated with a semicolon: + +```hlsl +// A terminating semicolon is allowed +struct Stuff { ... }; + +// The semicolon is not required +struct Things { ... } +``` + +When a structure declarations ends without a semicolon, the closing curly brace (`}`) must be the last non-comment, non-whitespace token on its line. + +For compatibility with C-style code, a structure type declaration may be used as the type specifier in a traditional-style variable declaration: + +```hlsl +struct Association +{ + int from; + int to; +} associations[] = +{ + { 1, 1 }, + { 2, 4 }, + { 3, 9 }, +}; +``` + +If a structure type declaration will be used as part of a variable declaration, then the next token of the variable declaration must appear on the same line as the closing curly brace (`}`) of the structure type declaration. +The whole variable declaration must be terminated with a semicolon (`;`) as normal. + + +Enumeration Types +----------------- + +Enumeration type declarations are introduced with the `enum` keyword: + +```hlsl +enum Color +{ + Red, + Green = 3, + Blue, +} +``` + +### Cases + +The body of an enumeration type declaration consists of a comma-separated list of case declarations. +An optional trailing comma may terminate the lis of cases. + +A _case declaration_ consists of the name of the case, along with an optional initial-value expression that specifies the _tag value_ for that case. +If the first case declaration in the body elides an initial-value expression, the value `0` is used for the tag value. +If any other case declaration elides an initial-value expressions, its tag value is one greater than the tag value of the immediately preceding case declaration. + +An enumeration case is referred to as if it were a `static` member of the enumeration type (e.g., `Color.Red`). + +### Inheritance + +An enumeration type declaration may include an inheritance clause: + +```hlsl +enum Color : uint +{ ... } +``` + +The inheritance clause of an enumeration declaration may currently only be used to specify a single type to be used as the _tag type_ of the enumeration type. +The tag type of an enumeration must be a built-in scalar integer type. +The tag value of each enumeration case will be a value of the tag type. + +If no explicit tag type is specified, the type `int` is used instead. + +> Note: The current Slang implementation has bugs that prevent explicit tag types from working correctly. + +### Conversions + +A value of an enumeration type can be implicitly converted to a value of its tag type: + +```hlsl +int r = Color.Red; +``` + +Values of the tag type can be explicitly converted to the enumeration type: + +```hlsl +Color red = Color(r); +``` + +Type Aliases +------------ + +A type alias is declared using the `typealias` keyword: + +```hlsl +typealias Height = int; +``` + +A type alias defines a name that will be equivalent to the type to the right of `=`. + +### Traditional Syntax + +Type aliases can also be declared with traditional C-style syntax: + +```hlsl +typedef int Height; +``` + +Constant Buffers and Texture Buffers +------------------------------------ + +As a compatibility feature, the `cbuffer` and `tbuffer` keywords can be used to introduce variable declarations. + +A declaration of the form: + +```hlsl +cbuffer Name +{ + F field; + // ... +} +``` + +is equivalent to a declaration of the form: + +```hlsl +struct AnonType +{ + F field; + // ... +} +__transparent ConstantBuffer anonVar; +``` + +In this expansion, `AnonType` and `anonVar` are fresh names generated for the expansion that cannot collide with any name in user code, and the modifier `__transparent` makes it so that an unqualified reference to `field` can implicitly resolve to `anonVar.field`. + +The keyword `tbuffer` uses an equivalent expansion, but with `TextureBuffer` used instead of `ConstantBuffer`. + +Interfaces +---------- + +An interface is declared using the `interface` keyword: + +```hlsl +interface IRandom +{ + uint next(); +} +``` + +The body of an interface declaration may contain function, initializer, subscript, and associated type declarations. +Each declaration in the body of an interface introduces a _requirement_ of the interface. +Types that declare conformance to the interface must provide matching implementations of the requirements. + +Functions, initializers, and subscripts declared inside an interface must not have bodies; default implementations of interface requirements are not currently supported. + +An interface declaration may have an inheritance clause: + +```hlsl +interface IBase +{ + int getBase(); +} + +interface IDerived : IBase +{ + int getDerived(); +} +``` + +The inheritance clause for an interface must only list other interfaces. +If an interface `I` lists another interface `J` in its inheritance clause, then `J` is a _base interface_ of `I`. +In order to conform to `I`, a type must also conform to `J`. + +Associated Types +---------------- + +An associated type declaration is introduced with `associatedtype`: + +```hlsl +associatedtype Iterator; +``` + +An associated type declaration introduces a type into the signature of an interface, without specifying the exact concrete type to use. +An associated type is an interface requirement, and different implementations of an interface may provide different types that satisfy the same associated type interface requirement: + +``` +interface IContainer +{ + associatedtype Iterator; + ... +} + +struct MyArray : IContainer +{ + typealias Iterator = Int; + ... +} + +struct MyLinkedList : IContainer +{ + struct Iterator { ... } + ... +} +``` + +It is an error to declare an associated type anywhere other than the body of an interface declaration. + +An associated type declaration may have an inheritance clause. +The inheritance clause of an associated type may only list interfaces; these are the _required interfaces_ for the associated type. +A concrete type that is used to satisfy an associated type requirement must conform to all of the required interfaces of the associated type. + +Initializers +------------ + +An initializer declaration is introduced with the `__init` keyword: + +```hlsl +struct MyVector +{ + float x, float y; + + __init(float s) + { + x = s; + y = s; + } +} +``` + +> Note: Initializer declarations are a non-finalized and unstable feature, as indicated by the double-underscore (`__`) prefix on the keyword. +> Arbitrary changes to the syntax and semantics of initializers may be introduced in future versions of Slang. + +An initializer declaration may only appear in the body of an interface or a structure type. +An initializer defines a method for initializing an instance of the enclosing type. + +> Note: A C++ programmer might think of an initializer declaration as similar to a C++ _constructor_. + +An initializer has a parameter list and body just like a function declaration. +An initializer must not include a result type clause; the result type of an initializer is always the enclosing type. + +An initializer is invoked by calling the enclosing type as if it were a function. +E.g., in the example above, the initializer in `MyVector` can be invoked as `MyVector(1.0f)`. + + +An initializer has access to an implicit `this` variable that is the instance being initialized; an initializer must not be marked `static`. +The `this` variable of an initializer is always mutable; an initializer need not, and must not, be marked `[mutating]`. + +> Note: Slang currently does not enforce that a type with an initializer can only be initialized using its initializers. +> It is possible for user code to declare a variable of type `MyVector` above, and explicitly write to the `x` and `y` fields to initialize it. +> A future version of the language may close up this loophole. + +> Note: Slang does not provide any equivalent to C++ _destructors_ which run automatically when an instance goes out of scope. + +Subscripts +---------- + +A subscript declaration is introduced with the `__subscript` keyword: + +```hlsl +struct MyVector +{ + ... + + __subscript(int index) -> float + { + get { return index == 0 ? x : y; } + } +} +``` + +> Note: subscript declarations are a non-finalized and unstable feature, as indicated by the double-underscore (`__`) prefix on the keyword. +> Arbitrary changes to the syntax and semantics of subscript declarations may be introduced in future versions of Slang. + +A subscript declaration introduces a way for a user-defined type to support subscripting with the `[]` braces: + +```hlsl +MyVector v = ...; +float f = v[0]; +``` + +A subscript declaration lists one or more parameters inside parentheses, followed by a result type clause starting with `->`. +The result type clause of a subscript declaration cannot be elided. + +The body of a subscript declaration consists of _accessor declarations_. +Currently only `get` accessor declarations are supported for user code. + +A `get` accessor declaration introduces a _getter_ for the subscript. +The body of a getter is a code block like a function body, and must return the appropriate value for a subcript operation. +The body of a getter can access the parameters of the enclosing subscript, as a well as an implicit `this` parameter of the type that encloses the accessor. +The `this` parameter of a getter is immutable; `[mutating]` getters are not currently supported. + +Extensions +---------- + +An extension declaration is introduced with the `extension` keyword: + +```hlsl +extension MyVector +{ + float getLength() { return sqrt(x*x + y*y); } + static int getDimensionality() { return 2; } +} +``` + +An extension declaration adds behavior to an existing type. +In the example above, the `MyVector` type is extended with an instance method `getLength()`, and a static method `getDimensionality()`. + +An extension declaration names the type being extended after the `extension` keyword. +The body of an extension declaration may include type declarations, functions, initializers, and subscripts. + +> Note: The body of an extension may *not* include variable declarations. +> An extension cannot introduce members that would change the in-memory layout of the type being extended. + +The members of an extension are accessed through the type that is being extended. +For example, for the above extension of `MyVector`, the introduced methods are accessed as follows: + +```hlsl +MyVector v = ...; + +float f = v.getLength(); +int n = MyVector.getDimensionality(); +``` + +An extension declaration need not be placed in the same module as the type being extended; it is possible to extend a type from third-party or standard module code. +The members of an extension are only visible inside of modules that `import` the module declaring the extension; +extension members are *not* automatically visible wherever the type being extended is visible. + +An extension declaration may include an inheritance clause: + +```hlsl +extension MyVector : IPrintable +{ + ... +} +``` + +The inheritance clause of an extension declaration may only include interfaces. +When an extension declaration lists an interface in its inheritance clause, it asserts that the extension introduces a new conformance, such that the type being extended now conforms to the given interface. +The extension must ensure that the type being extended satisfies all the requirements of the interface. +Interface requirements may be satisfied by the members of the extension, members of the original type, or members introduced through other extensions visible at the point where the conformance was declared. + +It is an error for overlapping conformances (that is, of the same type to the same interface) to be visible at the same point. +This includes cases where two extensions declare the same conformance, as well as those where the original type and an extension both declare the same conformance. +The conflicting conformances may come from the same module or difference modules. + +In order to avoid problems with conflicting conformances, when a module `M` introduces a conformance of type `T` to interface `I`, one of the following should be true: + +* the type `T` is declared in module `M`, or +* the type `I` is declared in module `M` + +Any conformance that does not follow these rules (that is, where both `T` and `I` are imported into module `M`) is called a _retroactive_ conformance, and there is no way to guarantee that another module `N` will not introduce the same conformance. +The runtime behavior of programs that include overlapping retroactive conformances is currently undefined. + +Currently, extension declarations can only apply to structure types; extensions cannot apply to enumeration types or interfaces. + +Generics +-------- + +Many kinds of declarations can be made _generic_: structure types, interfaces, extensions, functions, initializers, and subscripts. + +A generic declaration introduces a _generic parameter list_ enclosed in angle brackets `<>`: + +```hlsl +T myFunction(T left, T right, bool condition) +{ + return condition ? left : right; +} +``` + +### Generic Parameters + +A generic parameter list can include one or more parameters separated by commas. +The allowed forms for generic parameters are: + +* A single identifier like `T` is used to declare a _generic type parameter_ with no constraints. + +* A clause like `T : IFoo` is used to introduce a generic type parameter `T` where the parameter is _constrained_ so that it must conform to the `IFoo` interface. + +* A clause like `let N : int` is used to introduce a generic value parameter `N`, which takes on values of type `int`. + +> Note: The syntax for generic value parameters is provisional and subject to possible change in the future. + +Generic parameters may declare a default value with `=`: + +```hlsl +T anotherFunction(vector v); +``` + +For generic type parameters, the default value is a type to use if no argument is specified. +For generic value parameters, the default value is a value of the same type to use if no argument is specified. + +### Explicit Specialization + +A generic is _specialized_ by applying it to _generic arguments_ listed inside angle brackets `<>`: + +```hlsl +anotherFunction +``` + +Specialization produces a reference to the declaration with all generic parameters bound to concrete arguments. + +When specializing a generic, generic type parameters must be matched with type arguments that conform to the constraints on the parameter, if any. +Generic value parameters must be matched with value arguments of the appropriate type, and that are specialization-time constants. + +An explicitly specialized function, type, etc. may be used wherever a non-generic function, type, etc. is expected: + +```hlsl +int i = anotherFunction( int3(99) ); +``` + +### Implicit Specialization + +If a generic function/type/etc. is used where a non-generic function/type/etc. is expected, the compiler attempts _implicit specialization_. +Implicit specialization infers generic arguments from the context at the use site, as well as any default values specified for generic parameters. + +For example, if a programmer writes: + +```hlsl +int i = anotherFunction( int3(99) ); +``` + +The compiler will infer the generic arguments `` from the way that `anotherFunction` was applied to a value of type `int3`. + +> Note: Inference for generic arguments currently only takes the types of value arguments into account. +> The expected result type does not currently affect inference. + +### Syntax Details + +The following examples show how generic declarations of different kinds are written: + +``` +T genericFunction(T value); +funct genericFunction(value: T) -> T; + +__init(T value); + +__subscript(T value) -> X { ... } + +struct GenericType +{ + T field; +} + +interface IGenericInterface : IBase +{ +} +``` + +> Note: Currently there is no user-exposed syntax for writing a generic extension. diff --git a/lib/All/slang/share/doc/slang/language-reference/expressions-operators-member-access.md b/lib/All/slang/share/doc/slang/language-reference/expressions-operators-member-access.md new file mode 100644 index 0000000..8bcd668 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/expressions-operators-member-access.md @@ -0,0 +1,6 @@ +Member access operators +======================= + +PLACEHOLDER: +- operator `[]` +- operator `.` diff --git a/lib/All/slang/share/doc/slang/language-reference/expressions.md b/lib/All/slang/share/doc/slang/language-reference/expressions.md new file mode 100644 index 0000000..64bee73 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/expressions.md @@ -0,0 +1,353 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Expressions +=========== + +Expressions are terms that can be _evaluated_ to produce values. +This section provides a list of the kinds of expressions that may be used in a Slang program. + +In general, the order of evaluation of a Slang expression proceeds from left to right. +Where specific expressions do not follow this order of evaluation, it will be noted. + +Some expressions can yield _l-values_, which allows them to be used on the left-hand-side of assignment, or as arguments for `out` or `in out` parameters. + +Literal Expressions +------------------- + +Literal expressions are never l-values. + +### Integer Literal Expressions + +An integer literal expression consists of a single integer literal token: + +```hlsl +123 +``` + +An unsuffixed integer literal expression always has type `int`. + +### Floating-Point Literal Expressions + +A floating-point literal expression consists of a single floating-point literal token: + +```hlsl +1.23 +``` + +A unsuffixed floating-point literal expression always has type `float`. + +### Boolean Literal Expressions + +Boolean literal expressions use the keywords `true` and `false`. + +### String Literal Expressions + +A string literal expressions consists of one or more string literal tokens in a row: + +```hlsl +"This" "is one" "string" +``` + +Identifier Expression +--------------------- + +An _identifier expression_ consists of a single identifier: + +```hlsl +someName +``` + +When evaluated, this expression looks up `someName` in the environment of the expression and yields the value of a declaration with a matching name. + +An identifier expression is an l-value if the declaration it refers to is mutable. + +### Overloading + +It is possible for an identifier expression to be _overloaded_, such that it refers to one or more candidate declarations with the same name. +If the expression appears in a context where the correct declaration to use can be disambiguated, then that declaration is used as the result of the name expression; otherwise use of an overloaded name is an error at the use site. + +### Implicit Lookup + +It is possible for a name expression to refer to nested declarations in two ways: + +* In the body of a method, a reference to `someName` may resolve to `this.someName`, using the implicit `this` parameter of the method + +* When a global-scope `cbuffer` or `tbuffer` declaration is used, `someName` may refer to a field declared inside the `cbuffer` or `tbuffer` + +Member Expression +----------------- + +A _member expression_ consists of a base expression followed by a dot (`.`) and an identifier naming a member to be accessed: + +```hlsl +base.m +``` + +When `base` is a structure type, this expression looks up the field or other member named by `m`. +Just as for an identifier expression, the result of a member expression may be overloaded, and might be disambiguated based on how it is used. + +A member expression is an l-value if the base expression is an l-value and the member it refers to is mutable. + +### Implicit Dereference + +If the base expression of a member reference is a _pointer-like type_ such as `ConstantBuffer`, then a member reference expression will implicitly dereference the base expression to refer to the pointed-to value (e.g., in the case of `ConstantBuffer` this is the buffer contents of type `T`). + +### Vector Swizzles + +When the base expression of a member expression is of a vector type `vector` then a member expression is a _vector swizzle expression_. +The member name must conform to these constraints: + +* The member name must comprise between one and four ASCII characters +* The characters must be come either from the set (`x`, `y`, `z`, `w`) or (`r`, `g`, `b`, `a`), corresponding to element indics of (0, 1, 2, 3) +* The element index corresponding to each character must be less than `N` + +If the member name of a swizzle consists of a single character, then the expression has type `T` and is equivalent to a subscript expression with the corresponding element index. + +If the member name of a swizzle consists of `M` characters, then the result is a `vector` built from the elements of the base vector with the corresponding indices. + +A vector swizzle expression is an l-value if the base expression was an l-value and the list of indices corresponding to the characters of the member name contains no duplicates. + +### Matrix Swizzles + +> Note: The Slang implementation currently doesn't support matrix swizzles. + +### Static Member Expressions + +When the base expression of a member expression is a type instead of a value, the result is a _static member expression_. +A static member expression can refer to a static field or static method of a structure type. +A static member expression can also refer to a case of an enumeration type. + +A static member expression (but not a member expression in general) may use the token `::` instead of `.` to separate the base and member name: + +```hlsl +// These are equivalent +Color.Red +Color::Red +``` + +This Expression +--------------- + +A _this expression_ consists of the keyword `this` and refers to the implicit instance of the enclosing type that is being operated on in instance methods, subscripts, and initializers. + +The type of `this` is `This`. + +Parenthesized Expression +---------------------- + +An expression wrapped in parentheses `()` is a _parenthesized expression_ and evaluates to the same value as the wrapped expression. + +Call Expression +--------------- + +A _call expression_ consists of a base expression and a list of argument expressions, separated by commas and enclosed in `()`: + +```hlsl +myFunction( 1.0f, 20 ) +``` + +When the base expression (e.g., `myFunction`) is overloaded, a call expression can disambiguate the overloaded expression based on the number and type or arguments present. + +The base expression of a call may be a member reference expression: + +```hlsl +myObject.myFunc( 1.0f ) +``` + +In this case the base expression of the member reference (e.g., `myObject` in this case) is used as the argument for the implicit `this` parameter of the callee. + +### Mutability + +If a `[mutating]` instance is being called, the argument for the implicit `this` parameter must be an l-value. + +The argument expressions corresponding to any `out` or `in out` parameters of the callee must be l-values. + +A call expression is never an l-value. + +### Initializer Expressions + +When the base expression of a call is a type instead of a value, the expression is an initializer expression: + +```hlsl +float2(1.0f, 2.0f) +``` + +An initializer expression initialized an instance of the specified type using the given arguments. + +An initializer expression with only a single argument is treated as a cast expression: + +```hlsl +// these are equivalent +int(1.0f) +(int) 1.0f +``` + +Subscript Expression +-------------------- + +A _subscript expression_ consists of a base expression and a list of argument expressions, separated by commas and enclosed in `[]`: + +```hlsl +myVector[someIndex] +``` + +A subscript expression invokes one of the subscript declarations in the type of the base expression. Which subscript declaration is invoked is resolved based on the number and types of the arguments. + +A subscript expression is an l-value if the base expression is an l-value and if the subscript declaration it refers to has a setter or by-reference accessor. + +Subscripts may be formed on the built-in vector, matrix, and array types. + + +Initializer List Expression +--------------------------- + +An _initializer list expression_ comprises zero or more expressions, separated by commas, enclosed in `{}`: + +``` +{ 1, "hello", 2.0f } +``` + +An initialier list expression may only be used directly as the initial-value expression of a variable or parameter declaration; initializer lists are not allowed as arbitrary sub-expressions. + +> Note: This section will need to be updated with the detailed rules for how expressions in the initializer list are used to initialize values of each kind of type. + +Cast Expression +--------------- + +A _cast expression_ attempt to coerce a single value (the base expression) to a desired type (the target type): + +```hlsl +(int) 1.0f +``` + +A cast expression can perform both built-in type conversions and invoke any single-argument initializers of the target type. + +### Compatibility Feature + +As a compatibility feature for older code, Slang supports using a cast where the base expression is an integer literal zero and the target type is a user-defined structure type: + +```hlsl +MyStruct s = (MyStruct) 0; +``` + +The semantics of such a cast are equivalent to initialization from an empty initializer list: + +```hlsl +MyStruct s = {}; +``` + +Assignment Expression +--------------------- + +An _assignment expression_ consists of a left-hand side expression, an equals sign (`=`), and a right-hand-side expressions: + +```hlsl +myVar = someValue +``` + +The semantics of an assignment expression are to: + +* Evaluate the left-hand side to produce an l-value, +* Evaluate the right-hand side to produce a value +* Store the value of the right-hand side to the l-value of the left-hand side +* Yield the l-value of the left-hand-side + +Operator Expressions +-------------------- + +### Prefix Operator Expressions + +The following prefix operators are supported: + +| Operator | Description | +|-----------|-------------| +| `+` | identity | +| `-` | arithmetic negation | +| `~` | bit-wise Boolean negation | +| `!` | Boolean negation | +| `++` | increment in place | +| `--` | decrement in place | + +A prefix operator expression like `+val` is equivalent to a call expression to a function of the matching name `operator+(val)`, except that lookup for the function only considers functions marked with the `__prefix` keyword. + +The built-in prefix `++` and `--` operators require that their operand is an l-value, and work as follows: + +* Evaluate the operand to produce an l-value +* Read from the l-value to yield an _old value_ +* Increment or decrement the value to yield a _new value_ +* Write the new value to the l-value +* Yield the new value + +### Postfix Operator Expressions + +The following postfix operators are supported: + +| Operator | Description | +|-----------|-------------| +| `++` | increment in place | +| `--` | decrement in place | + +A postfix operator expression like `val++` is equivalent to a call expression to a function of the matching name `operator++(val)`, except that lookup for the function only considers functions marked with the `__postfix` keyword. + +The built-in prefix `++` and `--` operators require that their operand is an l-value, and work as follows: + +* Evaluate the operand to produce an l-value +* Read from the l-value to yield an _old value_ +* Increment or decrement the value to yield a _new value_ +* Write the new value to the l-value +* Yield the old value + +### Infix Operator Expressions + +The follow infix binary operators are supported: + +| Operator | Kind | Description | +|-----------|-------------|-------------| +| `*` | Multiplicative | multiplication | +| `/` | Multiplicative | division | +| `%` | Multiplicative | remainder of division | +| `+` | Additive | addition | +| `-` | Additive | subtraction | +| `<<` | Shift | left shift | +| `>>` | Shift | right shift | +| `<` | Relational | less than | +| `>` | Relational | greater than | +| `<=` | Relational | less than or equal to | +| `>=` | Relational | greater than or equal to | +| `==` | Equality | equal to | +| `!=` | Equality | not equal to | +| `&` | BitAnd | bitwise and | +| `^` | BitXor | bitwise exclusive or | +| `\|` | BitOr | bitwise or | +| `&&` | And | logical and | +| `\|\|` | Or | logical or | +| `+=` | Assignment | compound add/assign | +| `-=` | Assignment | compound subtract/assign | +| `*=` | Assignment | compound multiply/assign | +| `/=` | Assignment | compound divide/assign | +| `%=` | Assignment | compound remainder/assign | +| `<<=` | Assignment | compound left shift/assign | +| `>>=` | Assignment | compound right shift/assign | +| `&=` | Assignment | compound bitwise and/assign | +| `\|=` | Assignment | compound bitwise or/assign | +| `^=` | Assignment | compound bitwise xor/assign | +| `=` | Assignment | assignment | +| `,` | Sequencing | sequence | + +With the exception of the assignment operator (`=`), an infix operator expression like `left + right` is equivalent to a call expression to a function of the matching name `operator+(left, right)`. + +### Conditional Expression + +The conditional operator, `?:`, is used to select between two expressions based on the value of a condition: + +```hlsl +useNegative ? -1.0f : 1.0f +``` + +The condition may be either a single value of type `bool`, or a vector of `bool`. +When a vector of `bool` is used, the two values being selected between must be vectors, and selection is performed component-wise. + +> Note: Unlike C, C++, GLSL, and most other C-family languages, Slang currently follows the precedent of HLSL where `?:` does not short-circuit. +> +> This decision may change (for the scalar case) in a future version of the language. +> Programmer are encouraged to write code that does not depend on whether or not `?:` short-circuits. diff --git a/lib/All/slang/share/doc/slang/language-reference/glossary.md b/lib/All/slang/share/doc/slang/language-reference/glossary.md new file mode 100644 index 0000000..c8bd4c3 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/glossary.md @@ -0,0 +1,91 @@ +# Glossary + +[Compute Dispatch](basics-program-execution.md) +: See Dispatch. + +[Dispatch](basics-program-execution.md) +: A single dispatch of compute work. A dispatch is an explicit operation that specifies the input parameter + grid on which thread groups are instantiated. + +Entry point (TODO: link) +: A designated function from which a thread begins execution. + +[Graphics launch](basics-program-execution.md) +: See Launch. + +[Implementation-defined behavior](basics-behavior.md#classification) +: The observable behavior is defined by the implementation, and it is documented in the [target platforms + documentation](../target-compatibility.md) or documentation provided by the implementation. Implementation + includes the target language, the device and its driver, and declared extensions and available capabilities. + +[Launch](basics-program-execution.md) +: A single launch of graphics work. A graphics launch consists of an unspecified number of draw calls that + activate the graphics pipeline. + +[Mutually convergent set of threads](basics-execution-divergence-reconvergence.md) +: A set of threads in a wave that are on the same uniform control flow path. When the execution has diverged, + there is more than one such set. + +[Observable behavior](basics-behavior.md#observable) +: Program behavior observable over the execution interface. The interface includes resource variables, + shared memory, and execution control. + +[Precisely defined behavior](basics-behavior.md#classification) +: The observable behavior is precisely defined for all targets. + +Program (TODO: link) +: A program is a composition of units of linkable code. A program includes a set of entry points, which may be + invoked by a compute dispatch or by a graphics launch. + +[Tangled function](basics-program-execution.md) +: A function in which a set of threads participates. The scope of a tangled function is either wave or thread + group. Tangled functions include synchronous operations such as control barriers and cooperative functions + that collect inputs from and distribute outputs to the participating threads. + +[Thread](basics-program-execution.md) +: A sequential stream of executed instructions. In Slang, thread execution starts from an entry point + invocation. The thread terminates when it finishes executing the entry point, when it is discarded, or when + it exits abnormally. + +[Thread group](basics-program-execution.md) +: The second-level group of threads in the execution hierarchy. The thread group size is determined by the + application within target-specified limits. A thread group executes on the same execution resources, and it + can communicate efficiently using shared memory (`groupshared` modifier). + +[Thread-group-tangled function](basics-program-execution.md) +: A function in which all threads of a thread group participate. Examples include thread-group-level control + barriers. Unless otherwise stated, it is [undefined behavior](basics-behavior.md#classification) to invoke + thread-group-tangled functions on non-thread-group-uniform paths. + +[Thread-group-uniform path](basics-execution-divergence-reconvergence.md) +: All threads in the thread group are on a uniform path. + +[Undefined behavior](basics-behavior.md#classification) +: The observable behavior is not defined. Possible results include crashes, data corruption, and inconsistent + execution results across different optimization levels and different targets. + +[Uniform control flow](basics-execution-divergence-reconvergence.md) +: All threads are on a uniform path. + +[Uniform path](basics-execution-divergence-reconvergence.md) +: A control flow path is uniform when the control flow has not diverged or it has reconverged. Divergence + occurs when threads take different paths on conditional branches. Reconvergence occurs when the conditional + branches join. Control flow uniformity is usually considered in the thread-group and the wave scopes. + +[Unspecified behavior](basics-behavior.md#classification) +: The observable behavior is unspecified but within boundaries. Documentation is not required. + +[Wave](basics-program-execution.md) +: The smallest-granularity group of threads in the execution hierarchy. The wave size is a power of two in + the range [4, 128] defined by the target. Threads in a wave may participate in wave-tangled functions such as + wave ballots and wave reductions. For an example, see `WaveActiveMin()`. + +[Wave-tangled function](basics-program-execution.md) +: A function in which a subset of threads of the wave participates. Typically, the subset consists of the + active and mutually convergent threads. Wave-tangled functions include reductions such as `WaveActiveMin()`, + ballots such as `WaveActiveBallot()`, and functions that imply a wave-level control flow barrier such as + `GroupMemoryBarrierWithWaveSync()`. + +[Wave-uniform path](basics-execution-divergence-reconvergence.md) +: All threads in the wave are on a uniform path. + diff --git a/lib/All/slang/share/doc/slang/language-reference/introduction-goals.md b/lib/All/slang/share/doc/slang/language-reference/introduction-goals.md new file mode 100644 index 0000000..2eed02d --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/introduction-goals.md @@ -0,0 +1,3 @@ +# Slang Language Goals + +TODO diff --git a/lib/All/slang/share/doc/slang/language-reference/introduction-typographical-conventions.md b/lib/All/slang/share/doc/slang/language-reference/introduction-typographical-conventions.md new file mode 100644 index 0000000..1758a2c --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/introduction-typographical-conventions.md @@ -0,0 +1,124 @@ +# Typographical Conventions + +## Grammar + +The Slang grammar in this document is presented using a variation of the +[Extended Backus–Naur form](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form) as follows: + + +**Terminal symbol** +> **`'terminal'`** --- terminal symbol spelled exactly as is within quotes
+> **\** --- terminal symbol expressed by a regular expression + +[Terminal symbols](https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols#Terminal_symbols) are those +that can appear in the language. In the Slang language reference manual, two forms are used: literal strings that +appear exactly as defined and symbols defined by regular expressions. Whitespace characters between terminal symbols +are generally meaningless and ignored except where explicitly stated. + + +**Non-terminal symbol** +> *`nonterminal`* + +[Non-terminal symbols](https://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols#Nonterminal_symbols) do +not appear in the language. They are used in defining production rules. + + +**Production Rule** + +> *`lhs`* = \ + +A production rule defines how the left-hand-side non-terminal *`lhs`* may be substituted with the +right-hand-side grammatical expression \. The expression consists of non-terminals and terminals using +the grammar expression building blocks described below. + +Sometimes more than one production rule definitions are provided for the left-hand-side non-terminal. This +means that the non-terminal may be substituted with any of the definitions, which is grammatically equivalent +to alternation. Multiple production rules are used to associate semantics for individual production rules. + +In case more multiple production rules may be successfully used, the semantics of the rule introduced earlier +apply, unless explicit precedence (*i.e.*, priority) is provided. + +Note that a production rule definition is not explicitly terminated with a semi-colon (;). + + +**Concatenation** + +> *`lhs`* = *`symbol1`* *`symbol2`* ... *`symbolN`* + +[Concatenation](https://en.wikipedia.org/wiki/Concatenation) expresses a sequence of symbols, and it is +expressed without a comma. Symbols may be terminal or non-terminal. + + +**Alternation** + +> *`lhs`* = *`alternative1`* \| *`alternative2`* + +[Alternation](https://en.wikipedia.org/wiki/Alternation_(formal_language_theory)) expresses alternative +productions. That is, one (and exactly one) alternative is used. + + +**Grouping** +> *`lhs`* = ( *`subexpr`* ) + +Grouping is used to denote the order of production. + + +**Optional** +> *`lhs`* = [ *`subexpr`* ] + +An optional subexpression may occur zero or one times in the production. + + +**Repetition** +> *`lhs`* = *`expr`*\*      --- 0 or more times repetition
+> *`lhs`* = *`expr`*+      --- 1 or more times repetition + +A repeated expression occurs any number of times (* -repetition); or one or more times (+ -repetition). + +(*`expr`*+) is equivalent to (*`expr`* *`expr`*\*). + + +**Precedence** + +The following precedence list is used in the production rule expressions: + +|**Precedence**| **Grammar expressions** | **Description** +|--------------|:---------------------------|:--------------------------------- +|Highest | ( ... ) [ ... ] | grouping, optional +| | \* \+ | repetition +| | *`symbol1`* *`symbol2`* | concatenation (left-associative) +| | *`symbol1`* \| *`symbol2`* | alternation (left-associative) +|Lowest | = | production rule definition + +For example, the following production rule definitions are equivalent: +> *`lhs`* = `expr1` `expr2`+ \| `expr3` [ `expr4` `expr5` ] `expr6`
+> +> *`lhs`* = (`expr1` `expr2`+) \| ((`expr3` [ (`expr4` `expr5`) ]) `expr6`)
+ + +## Code Examples + +Code examples are presented as follows. + +**Example:** +```hlsl +struct ExampleStruct +{ + int a, b; +} +``` + +## Remarks and Warnings + +Remarks provide supplemental information such as recommendations, background information, rationale, and +clarifications. Remarks are non-normative. + +> 📝 **Remark:** Remarks provide useful information. + +Warnings provide important information that the user should be aware of. For example, warnings call out +experimental features that are subject to change and internal language features that should not be used in +user code. + +> ⚠️ **Warning:** Avoid using Slang internal language features. These exist to support Slang internal modules +> such as `hlsl.meta.slang`. Internal features are generally undocumented. They are subject to change without +> notice, and they may have caveats or otherwise not work as expected. diff --git a/lib/All/slang/share/doc/slang/language-reference/introduction.md b/lib/All/slang/share/doc/slang/language-reference/introduction.md new file mode 100644 index 0000000..2cdb70c --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/introduction.md @@ -0,0 +1,42 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +# Introduction + +Slang is a programming language primarily designed for use in *shader programming*, by which we mean +performance-oriented GPU programming for real-time graphics. + + +## General Topics + +* [Language Goals (TODO)](introduction-goals.md) +* [Typographical Conventions](introduction-typographical-conventions.md) + + +## Purpose of this document + +This document aims to provide a detailed reference for the Slang language and its supported constructs. + +The Slang compiler *implementation* may deviate from the language as documented here in a few key ways: + +* The implementation is necessarily imperfect and can have bugs. + +* The implementation may not fully support constructs documented here, or their capabilities may not be as + complete as what is documented. + +* The implementation may support certain constructs that are not properly documented. Constructs that are: + - *deprecated* --- These are called out with a ⚠️ **Warning**. Other documentation may be removed to + discourage use. + - *experimental* --- These are called out with a ⚠️ **Warning**. The constructs are subject to change and the + documentation may not be yet up to date. + - *internal* --- These are called out with a ⚠️ **Warning**. The constructs are often not otherwise + documented to discourage use. + +Where possible, this document calls out known deviations between the language as defined here and the +implementation in the compiler, often including GitHub issue links. + + +## Terminology + +> Note: This section is not yet complete. +> +> This section should detail how the document uses terms like "may" and "must," if we intend for those to be used in a manner consistent with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). diff --git a/lib/All/slang/share/doc/slang/language-reference/lexical-structure.md b/lib/All/slang/share/doc/slang/language-reference/lexical-structure.md new file mode 100644 index 0000000..c966ab6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/lexical-structure.md @@ -0,0 +1,121 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Lexical Structure +================= + +Source Units +------------ + +A _source unit_ comprises a sequence of zero or more _characters_ which for purposes of this document are defined as Unicode scalars (code points). + +Encoding +-------- + +Implementations *may* accept source units stored as files on disk, buffers in memory, or any appropriate implementation-specified means. +When source units are stored as byte sequences, they *should* be encoded using UTF-8. +Implementations *may* support additional implemented-specified encodings. + +Whitespace +---------- + +_Horizontal whitespace_ consists of space (U+0020) and horizontal tab (U+0009). + +A _line break_ consists of a line feed (U+000A), carriage return (U+000D) or a carriage return followed by a line feed (U+000D, U+000A). +Line breaks are used as line separators rather than terminators; it is not necessary for a source unit to end with a line break. + +Escaped Line Breaks +------------------- + +An _escaped line break_ comprises a backslack (`\`, U+005C) follow immediately by a line break. + +Comments +-------- + +A _comment_ is either a line comment or a block comment: + +```hlsl +// a line comment +/* a block comment */ +``` + +A _line comment_ comprises two forward slashes (`/`, U+002F) followed by zero or more characters that do not contain a line break. +A line comment extends up to, but does not include, a subsequent line break or the end of the source unit. + +A _block comment_ begins with a forward slash (`/`, U+002F) followed by an asterisk (`*`, U+0052). +A block comment is terminated by the next instance of an asterisk followed by a forward slash (`*/`). +A block comment contains all characters between where it begins and where it terminates, including any line breaks. +Block comments do not nest. +It is an error if a block comment that begins in a source unit is not terminated in that source unit. + +Phases +------ + +Compilation of a source unit proceeds _as if_ the following steps are executed in order: + +1. Line numbering (for subsequent diagnostic messages) is noted based on the locations of line breaks + +2. Escaped line breaks are eliminated. No new characters are inserted to replace them. Any new escaped line breaks introduced by this step are not eliminated. + +3. Each comments is replaced with a single space (U+0020) + +4. The source unit is _lexed_ into a sequence of tokens according the lexical grammar in this chapter + +5. The lexed sequence of tokens is _preprocessed_ to produce a new sequence of tokens (Chapter 3) + +6. Subsequent processing is performed on the preprocessed sequence of tokens + +Identifiers +----------- + +An _identifier_ begins with an uppercase or lowercase ASCII letter (`A` through `Z`, `a` through `z`), or an underscore (`_`). +After the first character, ASCII digits (`0` through `9`) may also be used in an identifier. + +The identifier consistent of a single underscore (`_`) is reserved by the language and must not be used by programs. +Otherwise, there are no fixed keywords or reserved words. +Words that name a built-in language construct can also be used as user-defined identifiers and will shadow the built-in definitions in the scope of their definition. + +Literals +-------- + +### Integer Literals + +An _integer literal_ consists of an optional radix specifier followed by digits and an optional suffix. + +The _radix specifier_ may be: + +* `0x` or `0X` to specify a hexadecimal literal (radix 16) +* `0b` or `0B` to specify a binary literal (radix 2) + +When no radix specifier is present a radix of 10 is used. + +Octal literals (radix 8) are not supported. +A `0` prefix on an integer literal does *not* specify an octal literal as it does in C. +Implementations *may* warn on integer literals with a `0` prefix in case users expect C behavior. + +The _digits_ of an integer literal may include ASCII `0` through `9`. +In the case of a hexadecimal literal, digits may include the letters `A` through `F` (and `a` through `f`) which represent digit values of 10 through 15. +It is an error for an integer literal to include a digit with a value greater than or equal to the radix. +The digits of an integer literal may also include underscore (`_`) characters, which are ignored and have no semantic impact. + +The _suffix_ on an integer literal may be used to indicate the desired type of the literal: + +* A `u` suffix indicates the `uint` type +* An `l` or `ll` suffix indicates the `int64_t` type +* A `ul` or `ull` suffix indicates the `uint64_t` type + +### Floating-Point Literals + +> Note: This section is not yet complete. + +### String Literals + +> Note: This section is not yet complete. + +### Character Literals + +> Note: This section is not yet complete. + +Operators and Punctuation +------------------------- + +> Note: This section is not yet complete. diff --git a/lib/All/slang/share/doc/slang/language-reference/preprocessor.md b/lib/All/slang/share/doc/slang/language-reference/preprocessor.md new file mode 100644 index 0000000..de579ef --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/preprocessor.md @@ -0,0 +1,19 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Preprocessor +============ + +Slang supports a C-style preprocessor with the following directives: + +* `#include` +* `#define` +* `#undef` +* `#if`, `#ifdef`, `#ifndef` +* `#else`, `#elif` +* `#endif` +* `#error` +* `#warning` +* `#line` +* `#pragma` + +> Note: This section is not yet complete. diff --git a/lib/All/slang/share/doc/slang/language-reference/shaders-and-kernels.md b/lib/All/slang/share/doc/slang/language-reference/shaders-and-kernels.md new file mode 100644 index 0000000..9d0a46c --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/shaders-and-kernels.md @@ -0,0 +1,26 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Graphics Shaders and Compute Kernels +==================================== + +This section describes the graphics and compute entry points, and their inputs and outputs. + +> **TODO** + +Graphics pipeline stage entry points: (aka graphics shaders) +- fragment +- vertex +- geometry +- hull +- domain +- raygeneration +- intersection +- anyhit +- closesthit +- miss +- callable +- task +- mesh + +Compute kernel entry points: +- compute diff --git a/lib/All/slang/share/doc/slang/language-reference/statements.md b/lib/All/slang/share/doc/slang/language-reference/statements.md new file mode 100644 index 0000000..71b1a12 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/statements.md @@ -0,0 +1,253 @@ +> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate. + +Statements +========== + +Statements are used to define the bodies of functions and determine order of evaluation and control flow for an entire program. +Statements are distinct from expressions in that statements do not yield results and do not have types. + +This section lists the kinds of statements supported by Slang. + +Expression Statement +-------------------- + +An expression statement consists of an expression followed by a semicolon: + +```hlsl +doSomething(); +a[10] = b + 1; +``` + +An implementation may warn on an expression statement that has to effect on the results of execution. + +Declaration Statement +--------------------- + +A declaration may be used as a statement: + +```hlsl +let x = 10; +var y = x + 1; +int z = y - x; +``` + +> Note: Currently only variable declarations are allowed in statement contexts, but other kinds of declarations may be enabled in the future. + +Block Statement +--------------- + +A block statement consists of zero or more statements wrapped in curly braces `{}`: + +```hlsl +{ + int x = 10; + doSomething(x); +} +``` + +A block statement provides local scoping to declarations. +Declarations in a block are visible to later statements in the same block, but not to statements or expressions outside of the block. + +Empty Statement +--------------- + +A single semicolon (`;`) may be used as an empty statement equivalent to an empty block statement `{}`. + +Conditional Statements +---------------------- + +### If Statement + +An _if statement_ consists of the `if` keyword and a conditional expression in parentheses, followed by a statement to execute if the condition is true: + +```hlsl +if(somethingShouldHappen) + doSomething(); +``` + +An if statement may optionally include an _else clause_ consisting of the keyword `else` followed by a statement to execute if the condition is false: + +```hlsl +if(somethingShouldHappen) + doSomething(); +else + doNothing(); +``` + +### Switch Statement + +A _switch statement_ consists of the `switch` keyword followed by an expression wrapped in parentheses and a _body statement_: + +```hlsl +switch(someValue) +{ + ... +} +``` + +The body of a switch statement must be a block statement, and its body must consist of switch case clauses. +A _switch case clause_ consists of one or more case labels or default labels, followed by one or more statements: + +```hlsl +// this is a switch case clause +case 0: +case 1: + doBasicThing(); + break; + +// this is another switch case clause +default: + doAnotherThing(); + break; +``` + +A _case label_ consists of the keyword `case` followed by an expressions and a colon (`:`). +The expression must evaluate to a compile-time constant integer. + +A _default label_ consists of the keyword `default` followed by a colon (`:`). + +It is an error for a case label or default label to appear anywhere other than the body of a `switch` statement. +It is an error for a statement to appear inside the body of a `switch` statement that is no part of a switch case clause. + +Switch case clauses may either exit via a `break` or other control transfer statement, or "fall through" to the next case clause by omitting the `break`: + +```hlsl +switch(value) +{ +case 0: + x = 10; + // Fall through to case 1 +case 1: + result = x + value; + break; +default: + result = -1; + break; +} +``` + +> **Note:** Some targets (FXC/D3D11 and WGSL) do not support fall-through natively. For these targets, the compiler restructures the code by duplicating the fall-through destination into each source case. This may affect wave/subgroup convergence if the duplicated code contains wave operations. Warning 41026 is emitted when this restructuring occurs. + +Loop Statements +--------------- + +### For Statement + +A _for statement_ uses the following form: + +```hlsl +for( ; ; ) +``` + +The _initial statement_ is optional, but may declare a variable whose scope is limited to the for statement. + +The _condition expression_ is optional. If present it must be an expression that can be coerced to type `bool`. If absent, a true value is used as the condition. + +The _side effect expression_ is optional. If present it will executed for its effects before each testing the condition for every loop iteration after the first. + +The _body statement_ is a statement that will be executed for each iteration of the loop. + +### While Statement + +A _while statement_ uses the following form: + +```hlsl +while( ) +``` + +and is equivalent to a `for` loop of the form: + +```hlsl +for( ; ; ) +``` + +### Do-While Statement + +A _do-while statement_ uses the following form: + +```hlsl +do while( ) +``` + +and is equivalent to a `for` loop of the form: + +```hlsl +for(;;) +{ + + if() continue; else break; +} +``` + +Control Transfer Statements +--------------------------- + +### Break Statement + +A `break` statement transfers control to after the end of the closest lexically enclosing switch statement or loop statement: + +```hlsl +break; +``` + +### Continue Statement + +A `continue` statement transfers control to the start of the next iteration of a loop statement. +In a for statement with a side effect expression, the side effect expression is evaluated when `continue` is used: + +```hlsl +break; +``` + +### Return Statement + +A `return` statement transfers control out of the current function. + +In the body of a function with a `void` result type, the `return` keyword may be followed immediately by a semicolon: + +```hlsl +return; +``` + +Otherwise, the `return` keyword must be followed by an expression to use as the value to return to the caller: + +```hlsl +return someValue; +``` + +The value returned must be able to coerce to the result type of the lexically enclosing function. + +### Discard Statement + +A `discard` statement can only be used in the context of a fragment shader, in which case it causes the current invocation to terminate and the graphics system to discard the corresponding fragment so that it does not get combined with the framebuffer pixel at its coordinates. + +Operations with side effects that were executed by the invocation before a `discard` will still be performed and their results will become visible according to the rules of the platform. + +Compile-Time For Statement +-------------------------- + +A _compile-time for statement_ is used as an alternative to preprocessor techniques for loop unrolling. +It looks like: + +```hlsl +$for( in Range(, )) +``` + +The _initial value_ and _upper bound_ expressions must be compile-time constant integers. +The semantics of a compile-time for statement are as if it were expanded into: + +```hlsl +{ + let = ; + +} +{ + let = + 1; + +} +... +{ + let = - 1; + +} +``` diff --git a/lib/All/slang/share/doc/slang/language-reference/types-array.md b/lib/All/slang/share/doc/slang/language-reference/types-array.md new file mode 100644 index 0000000..cc3f8be --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-array.md @@ -0,0 +1,125 @@ +# Array Types + +An *array type* is specifies an array of contiguously allocated elements. The array size may be either known +at compile-time or determined at runtime. The array size is always fixed during the lifetime of the array +object. + +## Declaration Syntax + +```hlsl +// (1) 1-dimensional array of length N +var varName : ElementType[N]; +ElementType[N] varName; +ElementType varName[N]; + +// (2) N-element array of M-element arrays +// +var varName : ElementType[M][N]; +ElementType[M][N] varName; +ElementType varName[N][M]; // note the order of N, M + +// (3) 1-dimensional array of unknown length +var varName : ElementType[]; +ElementType[] varName; +ElementType varName[]; + +// (4) Unknown-length array of M-element arrays +var varName : ElementType[M][]; +ElementType[M][] varName; +ElementType varName[][M]; + +// (5) Type alias for N-element array of M-element arrays +typealias ArrayType = ElementType[3][2]; +``` + +where: +- `ElementType` is the type of the array element. The element type may not have an unknown length. + - This implies that only the outermost dimension may have an unknown length. +- Array length expressions `N` and `M` are specialization-time constant integers. + - When specified, array length must be non-negative. +- `varName` is the variable identifier + +The declarations within each group are equivalent. + +When using the `var` or `let` syntax for variable declaration, array length declarations may only appear in the +type. + +An array with any dimension length of 0 is called a 0-length array. A 0-length array has 0 +size. Instantiations of 0-length arrays are discarded. This includes variables, function parameters, and +struct data member. 0-length arrays may not be accessed during runtime using the subscript operator. + +Restrictions for unknown-length arrays: +- When a non-const data member in a `struct` is an unknown-length array, it must be the last data member. +- An unknown-length array cannot be instantiated as a local variable unless the length can be inferred at + compile-time in which case it becomes a known-length array. +- A function parameter with an unknown-length array cannot be `out` or `inout`. + +> 📝 **Remark 1:** Declaring an array as part of the type is recommended. For example: +> ```hlsl +> var arr : int[3][4]; +> ``` + +> 📝 **Remark 2:** When using the C-style variable declaration syntax, array declarations binding to the variable +> identifier are applied from right to left. However, when binding to the type, the declarations are +> applied from left to right. Consider: +> ```hlsl +> int[2][3] arr[5][4]; +> ``` +> which is equivalent to: +> ```hlsl +> int[2][3][4][5] arr; +> ``` + +> 📝 **Remark 3:** Equivalent to `ElementType[N][M]` array type declaration would be +> `std::array, M>` in C++. + +> 📝 **Remark 4:** Unlike in C and C++, array types in Slang do not decay to pointer types. The implication is that +> array objects are always passed as values in assignment and function calls, similar to `std::array`. To +> avoid memory copies when possible, the compiler attempts to optimize these as pass by constant references or +> pointers when the target supports it. + +> 📝 **Remark 5:** 0-length arrays can be used to disable data members in `struct` types. See [Generics (TODO)](TODO) +> for further information. + + +### Element Count Inference for Unknown-Length Array + +When a variable is declared with an unknown-length array type and it also includes an initial-value expression: +```hlsl +int a[] = { 0xA, 0xB, 0xC, 0xD }; +``` +the compiler will attempt to infer the element count based on the type and/or structure of the initial-value expression. +In the above case, the compiler will infer an element count of 4 from the structure of the initializer-list expression. +Thus, the preceding declaration is equivalent to: +```hlsl +int a[4] = { 0xA, 0xB, 0xC, 0xD }; +``` +A variable declared in this fashion semantically has a known-length array type and not an unknown-length array +type. The use of an unknown-length array type for the declaration is a convenience feature. + + +## Memory Layout + +### Natural Layout + +The _stride_ of an array element type is the size of the element rounded up to the smallest multiple of its +alignment. The stride defines the byte offset difference between adjacent elements. + +The natural layout rules for an array type `T[]` or `T[N]`: + +* Element `i` of the array starts at a byte offset relative to the array base address that is `i` times the + element stride of the array. +* The alignment of the array type is the alignment of `T`. +* The size of an unknown-length array type is unknown. +* The size of a known-length array with zero elements is zero +* The size of a known-size array with a nonzero number `N` of elements is the size of `T` plus `N - 1` times the element stride of the array + +### C-Style Layout + +The C-style layout of an array type differs from the natural layout in that the array size is `N` times the +element stride. + +### D3D Constant Buffer Layout + +The D3D constant buffer layout of an array type differs from the natural layout in that the array size is `N` +times the element stride. diff --git a/lib/All/slang/share/doc/slang/language-reference/types-attributes.md b/lib/All/slang/share/doc/slang/language-reference/types-attributes.md new file mode 100644 index 0000000..7fff10c --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-attributes.md @@ -0,0 +1,6 @@ +# Type Attributes + +**TODO:** Describe user-visible type-related attributes: +- `open`, `sealed` +- `anyValueSize` +- `RequirePrelude` diff --git a/lib/All/slang/share/doc/slang/language-reference/types-class.md b/lib/All/slang/share/doc/slang/language-reference/types-class.md new file mode 100644 index 0000000..7ab68c3 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-class.md @@ -0,0 +1,3 @@ +# Classes + +TODO diff --git a/lib/All/slang/share/doc/slang/language-reference/types-enum.md b/lib/All/slang/share/doc/slang/language-reference/types-enum.md new file mode 100644 index 0000000..db501d5 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-enum.md @@ -0,0 +1,3 @@ +# Enumerations + +TODO diff --git a/lib/All/slang/share/doc/slang/language-reference/types-extension.md b/lib/All/slang/share/doc/slang/language-reference/types-extension.md new file mode 100644 index 0000000..8f3e045 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-extension.md @@ -0,0 +1,177 @@ +# Type Extension + +## Syntax + +[Struct extension](#struct) declaration: +> **`'extension'`** *`type-expr`*
+>     [**`':'`** *`bases-clause`*]
+> **`'{'`** *`member-list`* **`'}'`** + +[Generic struct extension](#generic-struct) declaration: +> **`'extension'`** *`generic-params-decl`* *`type-expr`*
+>     [**`':'`** *`bases-clause`*]
+>     (**`'where'`** *`where-clause`*)\*
+> **`'{'`** *`member-list`* **`'}'`** + +### Parameters + +- *`type-expr`* is the type to extend. +- *`generic-params-decl`* are the generic parameters for a [generic struct extension](#generic-struct). +- *`bases-clause`* is an optional list of [interface](types-interface.md) conformance specifications to be added. +- *`where-clause`* is an optional generic constraint expression. See [Generics (TODO)](TODO). +- *`member-list`* is a list of struct members to be added. A member is one of: + - *`var-decl`* is a member static variable declaration. See [Variables (TODO)](TODO) + - *`type-decl`* is a nested [type declaration](types.md). + - *`function-decl`* is a member function declaration. See [Functions (TODO)](TODO) + - *`constructor-decl`* is a [constructor declaration](types-struct.md#constructor). + - *`property-decl`* is a [property declaration](types-struct.md#property). + - *`subscript-op-decl`* is a [subscript operator declaration](types-struct.md#subscript-op). + - *`function-call-op-decl`* is a [function call operator declaration](types-struct.md#function-call-op). + + +## Description + +An existing `struct` type or a set of `struct` types can be extended with one or more `extension` +declarations. An `extension` may be used to add static data members, member functions, constructors, +properties, subscript operators, and function call operators to an existing type. An `extension` may not +change the data layout of a `struct`, that is, it cannot be used to append non-static data members. + +> 📝 **Remark:** An [interface](types-interface.md) type cannot be extended. This would add new requirements +> to all conforming types, which would invalidate existing conformances. + +## Struct Extension {#struct} + +A previously defined `struct` can be extended using an `extension` declaration. The declaration appends new +members to the `struct` definition. + +**Example 1:** +```hlsl +struct ExampleStruct +{ + uint32_t a; + + uint32_t getASquared() + { + return a * a; + } +} + +extension ExampleStruct +{ + // add a member function to ExampleStruct + [mutating] void addToA(uint32_t x) + { + a = a + x; + } +} +``` + +An extension can also be used to provide interface requirements to a struct. + +**Example 2:** +```hlsl +interface IReq +{ + int requiredFunc(); +} + +struct TestClass : IReq +{ +} + +extension TestClass +{ + int requiredFunc() + { + return 42; + } +} + +[shader("compute")] +void main(uint3 id : SV_DispatchThreadID) +{ + TestClass obj = { }; + + obj.requiredFunc(); +} +``` + +And finally, an extension can add new interface conformances to a struct: + +**Example 3:** +```hlsl +interface IReq +{ + int requiredFunc(); +} + +struct TestClass +{ +} + +extension TestClass : IReq +{ + int requiredFunc() + { + return 42; + } +} + +[shader("compute")] +void main(uint3 id : SV_DispatchThreadID) +{ + IReq obj = TestClass(); + + obj.requiredFunc(); +} +``` + +> ⚠️ **Warning:** When an extension and the base structure contain a member with the same signature, it is +> currently undefined which member is effective. ([Issue #9660](https://github.com/shader-slang/slang/issues/9660)) + + +## Generic Struct Extension {#generic-struct} + +All structs conforming to an interface may be extended using a generic extension declaration. The generic +extension declaration adds new members to all conforming types. In case there are multiple declarations with +the same signature, the one in the concrete type takes precedence. + +**Example:** +```hlsl +interface IBase +{ + int getA(); +} + +struct ConcreteInt16 : IBase +{ + int16_t a; + + int getA() + { + return a; + } +} + +struct ConcreteInt32 : IBase +{ + int32_t a; + + int getA() + { + return a; + } +} + +extension T +{ + // added to all types conforming to + // interface IBase + int getASquared() + { + return getA() * getA(); + } +} +``` + +See [Generics (TODO)](TODO) for further information on generics. diff --git a/lib/All/slang/share/doc/slang/language-reference/types-fundamental.md b/lib/All/slang/share/doc/slang/language-reference/types-fundamental.md new file mode 100644 index 0000000..88fff04 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-fundamental.md @@ -0,0 +1,80 @@ +# Fundamental Types + +The following types are collectively called the _fundamental types_: +- The `void` type +- The scalar Boolean type +- The scalar integer types +- The scalar floating point types + + +## Void Type {#void} + +The type `void` contains no data and has a single unnamed value. + +A function with return type `void` does not return a value. + +Variables, arrays elements, or structure data members may not have type `void`. + + +## Scalar Types {#scalar} + +### Boolean Type {#boolean} + +Type `bool` is used to represent Boolean truth values: `true` and `false`. + +The size of `bool` is target-defined. Similarly, the underlying bit patterns for `true` and `false` are +target-defined. The use of `bool` should be avoided when a specific in-memory layout of a data structure is +required. This includes data shared between different language targets even on the same device. + + +### Integer Types {#integer} + +The following integer types are defined: + +| Name | Description | +|----------------------|-------------------------| +| `int8_t` | 8-bit signed integer | +| `int16_t` | 16-bit signed integer | +| `int`, `int32_t` | 32-bit signed integer | +| `int64_t` | 64-bit signed integer | +| `uint8_t` | 8-bit unsigned integer | +| `uint16_t` | 16-bit unsigned integer | +| `uint`, `uint32_t` | 32-bit unsigned integer | +| `uint64_t` | 64-bit unsigned integer | + +All arithmetic operations on signed and unsigned integers wrap on overflow. + +All target platforms support the `int`/`int32_t` and `uint`/`uint32_t` types. The support for other types depends on the target and target capabilities. See [target platforms](../target-compatibility.md) for details. + +All integer types are stored in memory with their natural size and alignment on all target that support them. + +### Floating-Point Types {#floating} + +The following floating-point type are defined: + +| Name | Description | Precision (sign/exponent/significand bits) | +|-----------------------|------------------------------|--------------------------------------------| +| `half`, `float16_t` | 16-bit floating-point number | 1/5/10 | +| `float`, `float32_t` | 32-bit floating-point number | 1/8/23 | +| `double`, `float64_t` | 64-bit floating-point number | 1/11/52 | + +Rules for rounding, denormals, infinite values, and not-a-number (NaN) values are generally +target-defined. IEEE 754 compliant targets adhere to the +[IEEE 754-2019](https://doi.org/10.1109/IEEESTD.2019.8766229) standard. + +All targets support the `float`/`float32_t` type. Support for other types is target-defined. See +[target platforms](../target-compatibility.md) for details. + + +## Alignment and data layout + +The size of a Boolean type is targed-defined. All other fundamental types have precisely defined sizes. + +All fundamental types are _naturally aligned_. That is, their alignment is the same as their size. + +All fundamental types use [little-endian](https://en.wikipedia.org/wiki/Endianness) representation. + +All signed integers use [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) representation. + +> 📝 **Remark:** Fundamental types in other languages are not always naturally aligned. In particular, the alignment +> of C type `uint64_t` on x86-32 is typically 4 bytes. diff --git a/lib/All/slang/share/doc/slang/language-reference/types-interface.md b/lib/All/slang/share/doc/slang/language-reference/types-interface.md new file mode 100644 index 0000000..388461d --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-interface.md @@ -0,0 +1,507 @@ +# Interfaces + +## Syntax + +Interface declaration: + +> [*`modifier-list`*]
+> **`'interface'`** *`identifier`* [*`generic-params-decl`*]
+>     [**`':'`** *`bases-clause`*]
+>     (**`'where'`** *`where-clause`*)\*
+> **`'{'`** *`member-list`* **`'}'`** + +Associated named type declaration: + +> *`associated-type-decl`* =
+>     **`'associatedtype'`** *`identifier`*
+>     [**`':'`** *`bases-clause`*]
+>     (**`'where'`** *`where-clause`*)\*
+>     **`';'`** + +### Parameters + +- *`modifier-list`* is an optional list of modifiers (TODO: link) +- *`identifier`* is the name of the declared interface type +- *`generic-params-decl`* is an optional generic parameters declaration. See [Generics (TODO)](TODO). +- *`bases-clause`* is an optional list of inherited [interfaces](types-interface.md). +- *`where-clause`* is an optional generic constraint expression. See [Generics (TODO)](TODO). +- *`member-list`* is a list of interface members. A member is one of: + - *`var-decl`* is a `static` `const` member variable declaration of type + [int](types-fundamental.md#integer) or [bool](types-fundamental.md#boolean). See [Variables (TODO)](TODO) + - *`associated-type-decl`* is an associated type declaration. See below. + - *`function-decl`* is a member function declaration. See [Functions (TODO)](TODO) + - *`constructor-decl`* is a [constructor declaration](types-struct.md#constructor). + - *`property-decl`* is a [property declaration](types-struct.md#property). + - *`subscript-op-decl`* is a [subscript operator declaration](types-struct.md#subscript-op). + - *`function-call-op-decl`* is a [function call operator declaration](types-struct.md#function-call-op). + + + +## Description + +An `interface` specifies a set of member functions that a conforming type must provide. An interface can then +be used in place of a concrete type, allowing for the same code to use different concrete types via the +methods defined by the interface. + +An interface consists of: + +- Any number of member function prototypes, [constructors](types-struct.md#constructor), or + [function call operator declarations](types-struct.md#function-call-op) without a body. A concrete type + inheriting from the interface must provide compatible member function implementations with the same names. +- Any number of member functions or [function call operators](types-struct.md#function-call-op) with the + implementation body, which are added to the inheriting type (either a concrete `struct` or another + `interface`). Constructors are not allowed. + - Inheriting types may override member functions by using the `override` modifier with a compatible member + function declaration. +- Any number of [property](types-struct.md#property) or [subscript operator](types-struct.md#subscript-op) + declarations. An interface may declare either `get` or `set` or both methods without the implementation + body. A concrete type inheriting from the interface must provide implementations for the property and + subscript operator declarations. + - A property or a subscript operator declaration may be implemented with compatible `get` and `set` methods + as required by the interface. + - Alternatively, a property may be implemented by declaring a compatible variable with a matching name. +- Any number of *associated named types*, which a concrete inheriting type must provide. An associated named + type may be provided by: + - Declaring a nested [structure](types-struct.md) with the same name. OR + - Defining a type alias for the name with [typealias](types.md#alias) or + [typedef](types.md#alias) declarations. +- Any number of `static` `const` data members without initializers. A concrete inheriting type must provide + compatible static data members with the same names and types. + - The type of a `static` `const` member must be either `int` or `bool`. + +The interface member functions may be static or non-static. + +An object of a type conforming to an interface can be converted to the interface type. + +An interface may also inherit from another interface. The inherited members add to the inheriting interface. + +A member function implementation is compatible with an interface member function when: +- The implementation function can be called with the parameter types of the interface; AND +- The implementation function return type can be converted to the interface function return type. + +A member property (or variable) is compatible with an interface member property when the implementation +property (or variable) is convertible to the interface property and vice versa. + +Interface members may be declared with access control specifiers `public` or `internal`. The default member +visibility is the same as the visibility of the interface. See [access control (TODO)](TODO) for further +information. + +When a [structure](types-struct.md) implements an interface member requirement, the visibility of the member +may not be higher than the requirement. However, it can be lower. + +**Example:** + +```hlsl +interface IReq +{ +} + +interface ITest +{ + // Static data member requirement + static const int staticDataMember; + + // Static member function requirement + static float staticMethod(int a); + + // Property requirement + property testProp : float + { + get; // must be readable + set; // must be writable + } + + // Constructor requirement + __init(float f); + + // Non-static member function requirement + float someMethod(int a); + + // Overridable non-static member function + // with default implementation. + float someMethodWithDefaultImplementation(int a) + { + return testProp + float(a); + } + + // Function call operator requirement + float operator () (uint x, uint y); + + // Subscript operator requirement + __subscript (uint i0) -> float { get; set; } + + // Associated type requirement + associatedtype AssocType; + + // Associated type requirement, provided type must + // conform to IReq + associatedtype AssocTypeWithRequirement : IReq; +} + +struct TestClass : ITest +{ + // Required data member + static const int staticDataMember = 5; + + // Required static member function + static float staticMethod(int a) + { + return float(a) * float(a); + } + + float propUnderlyingValue; + float arr[10] = { }; + + // Required constructor + __init(float f) + { + propUnderlyingValue = f + 1.0f; + } + + // Required property + // + // Note that alternatively, a data member + // "float testProp;" could have also been provided. + property testProp : float + { + get + { + return propUnderlyingValue - 1.0f; + } + + set(float newVal) + { + propUnderlyingValue = newVal + 1.0f; + } + } + + // Required non-static member function + // + // Note that the parameters and the return value + // are not required to match as long as they are + // compatible. + float someMethod(int64_t a) + { + return float(a) * propUnderlyingValue; + } + + // Required function call operator + float operator () (uint x, uint y) + { + return float(x * y); + } + + // Required subscript operator + __subscript (uint i0) -> float + { + get + { + return arr[i0]; + } + + set + { + arr[i0] = newValue; + } + } + + // Required associated type provided by using a + // type alias. + typealias AssocType = int; + + // Required associated type provided by a nested type. + struct AssocTypeWithRequirement : IReq + { + } +} +``` + +> 📝 **Remark 1:** The test for an inheriting member function compatibility is equivalent to whether a wrapper +> function with the interface member function signature may invoke the inheriting member function, passing the +> parameters and the return value as is. +> +> For example: +> ```hlsl +> interface IBase +> { +> // a member function that a concrete type +> // must provide +> int32_t someFunc(int8_t a, int16_t b); +> } +> +> struct Test : IBase +> { +> // Implementation of IBase.someFunc(). This is +> // compatible because the corresponding wrapper +> // is well-formed (see below) +> int16_t someFunc(int a, int32_t b) +> { +> return int16_t(a + b); +> } +> } +> +> // A wrapper invoking Test.someFunc() with the +> // parameters and the return value of the interface +> // member function declaration +> int32_t IBase_wrapper_Test_someFunc( +> Test obj, int8_t a, int16_t b) +> { +> return obj.someFunc(a, b); +> } +> ``` + +> 📝 **Remark 2:** An interface can also be parameterized using generics. +> +> For example: +> +> ```hlsl +> interface ITypedReq +> { +> T someFunc(T param); +> } +> +> struct TestClass : ITypedReq +> { +> uint someFunc(uint param) +> { +> return 123 + param; +> } +> } +> +> [shader("compute")] +> void main(uint3 id : SV_DispatchThreadID) +> { +> TestClass obj = { }; +> +> obj.someFunc(id.x); +> } +> ``` +> +> See [Generics (TODO)](TODO) for further information on generics. + + +## Interface-Conforming Variants + +> ⚠️ **Warning:** This language feature is experimental and subject to change. + +A variable declared with an interface type is an *interface-conforming variant*–or *interface variant* for +short. An interface variant may have any type conforming to the interface. When an interface variant is +instantiated, the following restrictions apply: + +- The types conforming to the interface type may not have data members with opaque types such as `Texture2D` +- The types conforming to the interface type may not have data members with non-copyable types +- The types conforming to the interface type may not have data members with unsized types + +Further, invoking a member function of an interface variant has performance overhead due to dynamic +dispatching. + +> 📝 **Remark 1:** Function parameters with interface types do not impose the above restrictions when invoked +> with variables with types known at compile time. + +> 📝 **Remark 2:** Initializing an interface variant using the default initializer is deprecated. Invoking a +> default-initialized interface variant is undefined behavior. + +> 📝 **Remark 3:** In `slangc`, an interface variant is said to have an [existential +> type](https://en.wikipedia.org/wiki/Type_system#Existential_types), meaning that its type exists such that +> it conforms to the specified interface. + + +## Example + +```hlsl +RWStructuredBuffer outputBuffer; + +interface IBase +{ + // a member function that concrete types + // must define + int getA(); + + // a static const data member that concrete types + // must define + static const int8_t bias; +} + +interface ITest : IBase +{ + // Note: concrete types inheriting from this interface + // must define getA() + + // a member function defined by the interface, + // to be overridden by ConcreteInt16 + int someFunc() + { + return getA() + bias; + } + + // a static member function that ConcreteInt16 and + // ConcreteInt32 must provide. + static int getUnderlyingWidth(); +} + +struct ConcreteInt32 : ITest +{ + static const int8_t bias = 3; + + int32_t a; + + int32_t getA() + { + return a; + } + + static int getUnderlyingWidth() + { + return 32; + } +} + +struct ConcreteInt16 : ITest +{ + static const int8_t bias = 1; + + int16_t a; + + int getA() + { + return a; + } + + // override default implementation of someFunc() + override int someFunc() + { + return a + 5; + } + + static int getUnderlyingWidth() + { + return 16; + } +} + +// This function accepts any object conforming to +// interface ITest +int getValSquared(ITest i) +{ + return i.getA() * i.getA(); +} + +// This function creates a concrete object and returns +// it as an interface variant. +ITest createConcrete(bool is32, uint initialValue) +{ + if (is32) + return ConcreteInt32(initialValue); + else + return ConcreteInt16(initialValue); +} + +[shader("compute")] +[numthreads(16, 16, 1)] +void main(uint3 id : SV_DispatchThreadID) +{ + int ret; + + // Pass an object to a function + // with interface-typed argument + if ((id.x & 1) == 1) + { + ConcreteInt32 val = { id.y }; + + // A copy of getValSquared() is specialized for + // ConcreteInt32. + ret = getValSquared(val); + } + else + { + ConcreteInt16 val = { id.y }; + + // A copy of getValSquared() is specialized for + // ConcreteInt16. + ret = getValSquared(val); + } + + outputBuffer[id.x] = ret; + + // An interface variant. Declaring this imposes + // restrictions on the types conforming to the + // interface. + ITest iobj; + + if ((id.x & 1) == 1) + { + // create and assign a ConcreteInt32 object to the + // interface variant + iobj = createConcrete(true, id.y); + } + else + { + // create and assign a ConcreteInt16 object to the + // interface variant + iobj = createConcrete(false, id.y); + } + + // Note: Invoking a member function of an interface variant + // has the overhead of dynamic dispatching. + outputBuffer[id.x] += iobj.someFunc(); + + // Dynamic dispatch overhead also here: + outputBuffer[id.x] += iobj.getUnderlyingWidth(); +} +``` + + +## Memory Layout and Dispatch Mechanism + +The memory layout of an interface-conforming variant is unspecified. Type-based dynamic dispatching of a +member function invocation is unspecified. Both are subject to change in future versions of `slangc`. + +### Non-Normative Description of Interface-Conforming Variants + +> 📝 **Remark:** The contents of this section are informational only and subject to change. + +In the current implementation, the layout of an interface-conforming variant is a tagged union, conceptually +as follows: + +```hlsl +// Note: unions do not exist in Slang +union InterfaceConcreteObjectTypes +{ + ConcreteType1 obj1; + ConcreteType2 obj2; + ConcreteType3 obj3; + // ... +} + +struct InterfaceImplementationType +{ + uint32_t typeTag; + InterfaceConcreteObjectTypes tuple; +} +``` + +However, since Slang does not have union types where the underlying data is reinterpreted as one of the union +types, union types are emulated. Emulation is performed by packing/unpacking the data for a concretely-typed +object to/from the underlying representation. This involves memory copies. + +When the type is not known at compile-time, dynamic dispatch based on the type tag is performed to invoke +member functions. Internally, this is performed as follows: + +1. A `switch` statement based on the type tag selects the correct type-specific implementation for the + subsequent steps. +2. The concretely-typed object from the union is unpacked (non-static member functions only) +3. The member function of the concrete type is invoked +4. The concretely-typed object is packed back to the union (non-static mutating member functions only) + +When the type is known at compile-time, the code using an interface type is specialized for the concrete +type. This avoids the performance overhead of dynamic dispatching and union types. + +### Non-Normative Description of Interface-typed Function Parameters + +> 📝 **Remark:** The contents of this section are informational only and subject to change. + +In the current implementation, when a function with an interface-typed parameter is invoked with a type known +at compile time, the function is specialized for the concrete type. This essentially creates a copy of the +function with the interface-typed parameter replaced with a concrete-typed parameter. + +See also [Generic Functions](TODO-Generics.md). diff --git a/lib/All/slang/share/doc/slang/language-reference/types-pointer.md b/lib/All/slang/share/doc/slang/language-reference/types-pointer.md new file mode 100644 index 0000000..0ebbeea --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-pointer.md @@ -0,0 +1,173 @@ +# Pointer Types + +A pointer to type `T` represents an address of an object of type `T`. + +> ⚠️ **Warning:** Pointers are not yet fully implemented in `slangc`. + +Current limitations include: +- Pointers to local memory are supported only on CUDA and CPU targets. +- Slang does not support pointers to opaque handle types such as `Texture2D`. + For handle pointers, use `DescriptorHandle` instead. +- Slang does not currently support `const` pointers. +- Slang does not support custom alignment specification. Functions + [loadAligned()](../../../core-module-reference/global-decls/loadaligned-4.html) and + [storeAligned()](../../../core-module-reference/global-decls/storealigned-5.html) may be used for loads and + stores using pointers with known alignment. +- Pointers are not supported on all targets. +- Slang does not currently support inheritance with pointers. In particular, a pointer to a structure + conforming to interface `I` cannot be cast to a pointer to `I`. + +See also GitHub issue [#9061](https://github.com/shader-slang/slang/issues/9061). + +## Declaration Syntax {#syntax} + +> *`simple-type-id-spec`* =
+>     [*`modifier-list`*]
+>     *`type-identifier`*
+>     [*`generic-params-decl`*]
+>     (**`'['`** [*`constant-index-expr`*] **`']'`** | **`'*'`** )* + +See [type specifier syntax](types.md#syntax) for full type specifier syntax. + +> 📝 **Remark 1:** A pointer type specified with the declaration syntax is equivalent to +> [generic pointer type](#generic-pointer) `Ptr`. + +> 📝 **Remark 2:** Pointers can also be declared using [variable declarations](declarations.md). In this case, a +> variable is declared as a pointer to a type, rather than the type itself being a pointer type. + + +### Parameters + +- *`modifier-list`* is an optional list of modifiers (TODO: link) +- *`type-identifier`* is an identifier that names an existing type or a generic type. For example, this may be + a [fundamental type](types-fundamental.md), [vector/matrix generic type](types-vector-and-matrix.md), + user-defined type such as a named [structure type](types-struct.md), [interface type](types-interface.md), + [enumeration type](types-enum.md), type alias, or a type provided by a module. +- *`generic-params-decl`* is a generic parameters declaration. See [Generics (TODO)](TODO). +- **`'['`** [*`constant-index-expr`*] **`']'`** is an [array dimension declaration](types-array.md) with an + optional constant integral expression specifying the dimension length. +- **`'*'`** is a [pointer declaration](types-pointer.md). + + +## Generic Pointer Types {#generic-pointer} + +Type aliases provided by the Slang standard library: +- A generic pointer type: [Ptr](../../../core-module-reference/types/ptr-0/index.html) +- Pointer to immutable data: [ImmutablePtr](../../../core-module-reference/types/immutableptr-09.html) + +### Parameters + +- *`T`* is the element type. +- *`AccessMode`* is the storage access mode. +- *`AddressSpace`* is the storage address space. + +See [pointer traits](#traits). + +## Description + +The pointer declaration `*` applied to a base type creates a pointer type. The base type may be +any [addressable](types-traits.md) type including pointer and [array](types-array.md) types. + +To obtain the address of an object, the *address-of* operator `&` is used. The address may be assigned to a +pointer variable with a matching type. Alternatively, `__getAddress(obj)` may be used. + +To access the *pointed-to* object, the pointer dereference operator `*` is used. If the pointed-to type is a +[structure](types-struct.md) or a [class](types-class.md) type, the member access operators `.` or `->` may be +used to dereference the pointer and access a member. + +When a pointer points to an array element, an integer value may be added to or subtracted from it. The +resulting pointer points to an element offset by that value. + +A pointer value belongs to one of the following classes: +- a pointer to an object with matching [traits](#traits), including a pointer to an array element +- a pointer past the end of an object +- a null pointer, which is a special pointer value that points to nothing +- an invalid pointer, otherwise. + +It is [undefined behavior](basics-behavior.md#classification) to dereference a pointer that does not point to +an object with matching traits. + +For a comprehensive description, see [pointer expressions (TODO)](expressions.md). + +> ⚠️ **Warning:** When a pointer is to an element in a multi-dimensional array, pointer arithmetic must +> always result in a pointer that is in the same innermost array or a pointer past the last object in the +> array (which may not be dereferenced). Any other result is +> [undefined behavior](basics-behavior.md#classification). + +> 📝 **Remark 1:** Currently, there are no `const` pointers in Slang. Pointers to read-only data and immutable +> data may be declared with [generic pointer types](#generic-pointer). + +> 📝 **Remark 2:** Consider the following pointer arithmetic: +> +> ```hlsl +> var arr : uint[10] = { }; +> var ptr : uint *; +> +> ptr = &arr[9]; // OK: ptr points to the last element +> // of the array +> +> ptr++; // Still OK: ptr points to one past the +> // last element +> +> ptr++; // Pointer is now invalid +> +> ptr--; // No validity guarantees with invalid +> // pointers in pointer expressions; +> // dereferencing would be undefined behavior +> ``` + + +## Pointer Traits {#traits} + +A pointer type has the following traits: +- type of the pointed-to object +- access mode +- address space + +A valid pointer may only point to objects with matching traits. + +The default pointer address space is `AddressSpace.Device`, and the default access mode is +`Access.ReadWrite`. It is not possible to use different address spaces or access modes using the declaration +syntax. + +Pointers for other address spaces and access modes may be declared by using type alias +[Ptr](../../../core-module-reference/types/ptr-0/index.html) provided +by the standard library. There is no implicit conversion from read-write to read-only pointers. + + +## Examples {#examples} + +### Pointers Denoting a Range + +```hlsl +RWStructuredBuffer outputBuffer; + +cbuffer Globals +{ + Ptr g_inputData; + uint g_inputDataLen; +} + +// Calculate sum of half-open range [start, end) +uint sumOfValues(uint *start, uint *end) +{ + uint sum = 0; + + for (uint *i = start; i != end; ++i) + { + sum = sum + *i; + } + + return sum; +} + +[numthreads(1, 1, 1)] +void main(uint3 id : SV_DispatchThreadID) +{ + // Calculate sum of elements 0, 1, ..., 9 provided + // the input data buffer is big enough. + outputBuffer[id.x] += + sumOfValues( + g_inputData, &g_inputData[min(g_inputDataLen, 10)]); +} +``` diff --git a/lib/All/slang/share/doc/slang/language-reference/types-special.md b/lib/All/slang/share/doc/slang/language-reference/types-special.md new file mode 100644 index 0000000..0199853 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-special.md @@ -0,0 +1,22 @@ +# Special Types + +## Opaque Types {#opaque} + +Opaque types are built-in types that have target-defined representation in memory. This includes the bit +representation, the underlying type, and characteristics such as size and alignment. Other shader languages +may refer to these as *opaque handle types*, *opaque descriptor types*, *resource object types*, or *resource +data types*. + +The full list of opaque types supported by Slang can be found in the core module reference. Some important +examples: + +* Texture types such as `Texture2D`, `TextureCubeArray`, `DepthTexture2D`, and `RWTexture2DMS` +* Combined texture-sampler types such as `Sampler2D` and `Sampler2DShadow` +* Sampler state types: `SamplerState` and `SamplerComparisonState` +* Buffer types like `ConstantBuffer` and `StructuredBuffer` +* Parameter blocks: `ParameterBlock` + +Slang makes no guarantees about layout rules or type conversion rules of opaque types. + + +**TODO**: Add other special types diff --git a/lib/All/slang/share/doc/slang/language-reference/types-struct.md b/lib/All/slang/share/doc/slang/language-reference/types-struct.md new file mode 100644 index 0000000..bee7e92 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-struct.md @@ -0,0 +1,656 @@ +# Structures + +## Syntax + +Struct *no-body* declaration: +> *`struct-decl`* =
+>     [*`modifier-list`*]
+>     **`'struct'`** [*`identifier`*] [*`generic-params-decl`*]
+>         [**`':'`** *`bases-clause`*] [**`'='`** *`type-expr`*] **`';'`** + +Struct *with-members* declaration: +> *`struct-decl`* =
+>     [*`modifier-list`*]
+>     **`'struct'`** [*`identifier`*] [*`generic-params-decl`*]
+>         [**`':'`** *`bases-clause`*]
+>         (**`'where'`** *`where-clause`*)\*
+> **`'{'`** *`member-list`* **`'}'`** + +Struct *link-time extern type* declaration: +> *`struct-decl`* =
+>     [*`modifier-list`*]
+>     **`'extern'`** **`'struct'`** [*`identifier`*] [*`generic-params-decl`*]
+>         [**`':'`** *`bases-clause`*] [**`'='`** *`type-expr`*] **`';'`** + +Struct *link-time export type alias* declaration: +> *`struct-decl`* =
+>     [*`modifier-list`*]
+>     **`'export'`** **`'struct'`** [*`identifier`*] [*`generic-params-decl`*]
+>         [**`':'`** *`bases-clause`*] **`'='`** *`type-expr`* **`';'`** + +Member list: +> *`member-list`* =
+>     ( *`var-decl`*
+>     | *`type-decl`*
+>     | *`function-decl`*
+>     | *`constructor-decl`*
+>     | *`property-decl`*
+>     | *`subscript-op-decl`*
+>     | *`function-call-op-decl`* )* + +### Parameters + +- *`modifier-list`* is an optional list of modifiers (TODO: link) +- *`identifier`* is an optional name of the declared struct type +- *`generic-params-decl`* is an optional generic parameters declaration. See [Generics (TODO)](TODO). +- *`bases-clause`* is an optional list of inherited [interfaces](types-interface.md). +- *`type-expr`* is an optional type expression for an alias type. See [Modules (TODO)](TODO). +- *`where-clause`* is an optional generic constraint expression. See [Generics (TODO)](TODO). +- *`member-list`* is a list of struct members. A member is one of: + - *`var-decl`* is a member variable declaration. See [Variables (TODO)](TODO) + - *`type-decl`* is a nested [type declaration](types.md). + - *`function-decl`* is a member function declaration. See [Functions (TODO)](TODO) + - *`constructor-decl`* is a [constructor declaration](#constructor). + - *`property-decl`* is a [property declaration](#property). + - *`subscript-op-decl`* is a [subscript operator declaration](#subscript-op). + - *`function-call-op-decl`* is a [function call operator declaration](#function-call-op). + +> ⚠️ **Warning:** `Slangc` currently accepts bracketed attributes right after the **`'struct'`** keyword. This +> is deprecated syntax and expected to be removed. Bracketed attributes should be added in *`modifier-list`*, +> instead. ([Issue #9691](https://github.com/shader-slang/slang/issues/9691)) + + +## Description + +A structure is a type consisting of an ordered sequence of members. A `struct` declaration has the following +forms: + +- The *no-body* declaration specifies an existence of a structure type. The declaration simply specifies that + a structure type with the specified name exists. This enables its use in type expressions without the member + declarations. +- The *with-members* declaration defines the structure type with a layout and an [extensible](types-extension.md) + list of non-layout members. +- The *link-time extern type* declaration specifies the existence of a structure type that is defined in + another module. See [Modules (TODO)](TODO). +- The *link-time export type* declaration specifies that a structure type is exported with a type alias. See + [Modules (TODO)](TODO). + +When the *`identifier`* is specified, it is the name of the structure. Otherwise, the structure is anonymous, +which means that it is assigned an unspecified unique name. The main use of anonymous structures is in inline +type definition expressions. For example, `struct { int a; } obj;` defines variable `obj` with an anonymous +structure type that has field `int a;`. Anonymous structure declarations are meaningful only in the +*with-members* form. + +A structure member is declared in the structure body and is one of the following: +- A static data member; declared as a variable with the `static` keyword. +- A non-static data member (*aka.* field); declared as a variable. +- A [constructor](#constructor). +- A [static member function](#static-member-function); declared as a function with the `static` modifier + keyword. +- A [non-static member function](#nonstatic-member-function); declared as a function without the `static` + modifier keyword. +- A nested type; declared as a type or a type alias. +- A [`property` declaration](#property). +- A [`__subscript` declaration](#subscript-op). +- A [function call operator declaration](#function-call-op). + +A data member and a member function can be declared with the `static` keyword. + +- The storage for a static data member is allocated from the global storage. A static member function may: + - Access static data members of the structure. + - Invoke other static member functions of the structure. +- The storage for a non-static data member is allocated as part of the structure. A non-static member function may: + - Access both the static and the non-static data members. + - Invoke both the static and the non-static member functions. + +Data members may be assigned with a default initializer. The following rules apply: +- When an object is initialized using an initializer list, the default initializer of a non-static data member + specifies the initial value when the initializer list does not provide one. +- When an object is initialized using a constructor, the default initializer of a non-static data member + specifies the initial value of the data member. A constructor may override this, unless the member is + `const`. +- `static const` data members must have a default initializer. + +For further information, see [Initialization (TODO)](TODO). + +The non-static data members are allocated sequentially within the `struct` when a variable of this type is +allocated. See [Variables (TODO)](TODO). + +A nested type is a regular type enclosed within the scope of the outer `struct`. + +A structure may conform to one or more [interface](types-interface.md) types. + +A structure may be extended with a [type extension](types-extension.md). + +`struct` members may be declared with access control specifiers `public`, `internal`, or `private` (specified +in *`modifier-list`*). The default member visibility is `internal`. Nested `struct` members have access to +`private` members of the enclosing `struct`. See [access control (TODO)](TODO) for further information. + + +> ⚠️ **Warning:** Structure inheriting from another structure is deprecated. It may not work as expected. + + +## Objects {#object} + +An object is an *instance* of a `struct`. An instance consists of all non-static data members defined in a +`struct`. The data members may be initialized using an initializer list or a constructor. For details, see +[variable declarations](declarations.md). + +## Constructors {#constructor} + +### Syntax + +Declaration without body: (interfaces only) +> **`'__init'`** **`'('`** *`param-list`* **`')'`** (**`'where'`** *`where-clause`*)\* **`';'`** + +Declaration with body: +> **`'__init'`** **`'('`** *`param-list`* **`')'`** (**`'where'`** *`where-clause`*)\*
+>     **`'{'`** *`body-stmt`*\* **`'}'`** + + +### Description + +When a user-provided constructor is defined for a `struct`, a constructor is executed on object +instantiation. A constructor can have any number of parameters. A constructor does not have a return +type. More than one constructors may be defined in which case overload resolution is performed to select the +most appropriate constructor given the initialization parameters. + +The constructor parameters are provided in the optional initializer list. When an initializer is not provided, +the no-parameter constructor is invoked. + +If a non-static data member is not initialized by the constructor, it has an undefined state after object +instantiation. + +`const` data members cannot be initialized by the constructor. + +*`where-clause`* is an optional generic constraint expression, discussed in [Generics (TODO)](TODO). + + +**Example:** +```hlsl +struct TestClass +{ + int a, b; + + __init() + { + a = 1; + b = 2; + } + + __init(int _a) + { + a = 1; + b = 2; + } + + __init(int _a, int _b) + { + a = _a; + b = _b; + } +} + +TestClass obj1; +// obj1.a = 1; +// obj1.b = 2; +// +// Note: TestClass obj1 = { }; also calls the constructor +// without parameters + +TestClass obj2 = { 42 }; +// obj2.a = 42; +// obj2.b = 2; + +TestClass obj3 = { 42, 43 }; +// obj3.a = 42; +// obj3.b = 43; + +``` + +When no user-provided constructor is defined, an aggregate initialization is performed, instead. In aggregate +initialization, an initializer list contains values for the `struct` non-static data members. If the +initializer list does not contain enough values, the remaining data members are default-initialized. If no +initializer list is provided, a class without a user-provided constructor is instantiated in an undefined +state. + +> 📝 **Remark 1:** When a class without user-provided constructor is instantiated without an initializer list, the +> object's initial state is undefined. This includes data members which have members with user-provided +> constructors. +> +> ```hlsl +> struct TestField +> { +> int x; +> __init() { x = 5; } +> } +> +> struct TestClass +> { +> int a, b; +> TestField f; +> } +> +> // note: obj is instantiated with an undefined state +> // regardless of TestField having a user-provided constructor. +> +> TestClass obj; +> ``` + +> 📝 **Remark 2:** Accessing data members that are in undefined state is undefined behavior. + + +## Static Member Functions {#static-member-function} + +A static member function is a regular function enclosed within the `struct` name space. Static member +functions may access only static structure members. + +Invocation of a static member function does not require an object. + + +## Non-static Member Functions {#nonstatic-member-function} + +A non-static member function has a hidden parameter `this` that refers to an object. The hidden parameter +is used to reference the object data members and to invoke other non-static member functions. + +In the function body, other members may be referenced using `this.`, although it is optional. + +By default, only a read access to the object members is allowed by a member function. If write access is +required, the member function must be declared with the `[mutating]` attribute. + +Non-static member functions cannot be invoked without an object. + +> 📝 **Remark:** In C++ terminology, a member function is `const` by default. Attribute `[mutating]` makes it +> a non-`const` member function. + + +## Properties {#property} + +### Syntax + +Modern syntax, implicit `get` declaration: (interfaces only) +> **`'property'`** *`identifier`* **`':'`** *`type-expr`* **`';'`** + +Modern syntax, explicit accessor declarations: +> **`'property'`** *`identifier`* **`':'`** *`type-expr`*
+> **`'{'`** *`accessor-decl`*\* **`'}'`** + +Traditional syntax, implicit `get` declaration: (interfaces only) +> **`'property'`** *`traditional-var-decl`* **`';'`** + +Traditional syntax, explicit accessor declarations: +> **`'property'`** *`traditional-var-decl`*
+> **`'{'`** *`accessor-decl`*\* **`'}'`** + +Accessor declaration syntax, no body: (interfaces only) +> *`accessor-decl`* =
+>     (**`'get'`** \| **`'set'`**) [**`'('`** *`param-list`* **`')'`**] **`';'`** + +Accessor declaration syntax, with body: +> *`accessor-decl`* =
+>     (**`'get'`** \| **`'set'`**) [**`'('`** *`param-list`* **`')'`**]
+>     **`'{'`** *`body-stmt`*\* **`'}'`** + +### Description + +A property is a non-static member that provides a data member access interface. Properties of objects are +accessed similarly to data members: reading a property is directed to the `get` accessor of the property and +writes are directed to the `set` accessor, respectively. + +A property that only provides the `get` accessor is a read-only property. A property that only provides the +`set` accessor is a write-only property. A property that provides both is a read/write property. + +The parentheses in the `get` accessor declaration are optional. The `get` accessor accepts no parameters. + +The parentheses and the parameter in the `set` accessor declaration are optional. In case the parameter is not +specified in the declaration, parameter `newValue` with the same type as the property is provided to the `set` +body. + +The property declaration forms without accessor or accessor body declarations are useful only in +[interface](types-interface.md) declarations. + +> ⚠️ **Warning:** Property reference accessor `ref` is a Slang internal language feature. It is subject to +> change and may not work as expected. + + +**Example:** +```hlsl +struct TestClass +{ + float m_val; + + // automatically updated derivative of m_val + bool m_valIsPositive; + + property someProp : float + { + get + { + return m_val; + } + + set + { + m_val = newValue; + m_valIsPositive = (newValue > 0.0f); + } + } +} + +[shader("compute")] +void main(uint3 id : SV_DispatchThreadID) +{ + TestClass obj = { }; + + // this sets both obj.m_val and obj.m_valIsPositive + obj.someProp = 3.0f; +} +``` + +> 📝 **Remark 1:** A property can be used to replace a non-`static` data member when additional logic is desired to +> be added systematically to data member access. This can avoid refactoring call sites. + +> 📝 **Remark 2:** A non-static data member can be used to implement an interface property requirement. See +> [interfaces](types-interface.md) for details. + +> 📝 **Remark 3:** In the example above, the property could have also been declared as: +> +> ```hlsl +> struct TestClass +> { +> // ... +> +> property someProp : float +> { +> get() +> { +> return m_val; +> } +> +> set(float newVal) +> { +> m_val = newVal; +> m_valIsPositive = (newVal > 0.0f); +> } +> } +> } +> ``` + +## Accessing Members and Nested Types + +The static and non-static structure members and nested types are accessed using \``.`\`. + +> ⚠️ **Warning:** The C++-style scope resolution operator \``::`\` is deprecated. It should not be used. + + +**Example:** + +```hlsl +// struct type declaration +struct TestStruct +{ + // data member + int a; + + // static data member, initial value 5 + static int b = 5; + + // static constant data member, initial value 6 + static const int c = 6; + + // nested type + struct NestedStruct + { + static int c = 6; + int d; + } + + // member function with read-only access + // to non-static data members + int getA() + { + // also just plain "return a" would do + return this.a; + } + + // member function with read/write access + // to non-static data members + [mutating] int incrementAndReturnA() + { + // modification of data member + // requires [mutating] + a = a + 1; + + return a; + } + + // static member function + static int getB() + { + return b; + } + + static int incrementAndReturnB() + { + // [mutating] not needed for + // modifying static data member + b = b + 1; + + return b; + } +} + +// instantiate an object of type TestStruct using defaults +TestStruct obj = { }; + +// instantiate an object of type NestedStruct +TestStruct.NestedStruct obj2 = { }; + +// access an object data member directly +obj.a = 42; + +// access a static data member directly +int tmp0 = TestStruct.b + TestStruct.NestedStruct.c; + +// invoke object member functions +int tmp1 = obj.getA(); +int tmp2 = obj.incrementAndReturnA(); + +// invoke static members functions + +// '.' can be used to resolve scope +int tmp3 = TestStruct.getB(); + +// '::' is equivalent to '.' for static member access, +// but '.' is recommended. +int tmp4 = TestStruct::incrementAndReturnB(); +``` + +## Subscript operator {#subscript-op} + +### Syntax + +Implicit `get` declaration: (interfaces only) +> **`'__subscript'`** [**`'('`** *`param-list`* **`')'`**]
+ +Explicit accessor declarations: +> **`'__subscript'`** [**`'('`** *`param-list`* **`')'`**] **`'->'`** *`type-expr`*
+> **`'{'`** *`accessor-decl`*\* **`'}'`** + +See [properties](#property) for *`accessor-decl`* syntax. + +### Description + +A subscript `[]` operator can be added in a structure using a `__subscript` declaration. It is conceptually +similar to a `property` with the main differences being that it operates on the instance of a `struct` +(instead of a member) and it accepts parameters. + +A subscript declaration may have any number of parameters, including no parameters at all. + +The `get` accessor of a `__subscript` declaration is invoked when the subscript operator is applied to an +object to return a value. The parentheses in the `get` accessor declaration are optional. + +The `set` accessor of a `__subscript` declaration is invoked when the subscript operator is applied to an +object to assign a value. The parentheses and the parameter in the `set` accessor declaration are optional. In +case the parameter is not specified in the declaration, a parameter `newValue` with the same type as specified +for the subscript operator is provided to the `set` body. + +Multiple `__subscript` declarations are allowed as long as the declarations have different +signatures. Overload resolution is the same as overload resolution with function invocations. + +> ⚠️ **Warning:** Subscript operator reference accessor `ref` is a Slang internal language feature. It is +> subject to change and may not work as expected. + +**Example:** + +```hlsl +RWStructuredBuffer outputBuffer; + +struct TestStruct +{ + var arr : float[10][10]; + + // declare a 0-parameter subscript operator + __subscript () -> float + { + get { return arr[0][0]; } + set { arr[0][0] = newValue; } + } + + // declare a 1-parameter subscript operator + __subscript (int i) -> float + { + get { return arr[0][i]; } + set { arr[0][i] = newValue; } + } + + // declare a 2-paramater subscript operator + __subscript (int i0, int i1) -> float + { + get { return arr[i1][i0]; } + set { arr[i1][i0] = newValue; } + } +} + +void main(uint3 id : SV_DispatchThreadID) +{ + TestStruct x = { }; + + x[] = id.z; + x[id.y] = id.z; + x[id.x, id.y] = id.z; + + outputBuffer[id.x] = x[]; + outputBuffer[id.y] = x[id.x]; + outputBuffer[id.z] = x[id.x, id.y]; +} +``` + +## Function call operator {#function-call-op} + +### Syntax + +Declaration without body: (interfaces only) +> *`type-expr`* **`'operator'`** **`'(' ')'`** **`'('`** *`param-list`* **`')'`** **`';'`** + +Declaration with body: +> *`type-expr`* **`'operator'`** **`'(' ')'`** **`'('`** *`param-list`* **`')'`**
+> **`'{'`** *`body-stmt`*\* **`'}'`** + +### Description + +A function call `()` operator can be added using an `operator ()` declaration. This allows applying parameters +to an object as if the object was a function. + +Multiple declarations are allowed as long as the declarations have different signatures. Overload resolution +is the same as overload resolution with function invocations. + +**Example:** + +```hlsl +RWStructuredBuffer outputBuffer; + +struct TestStruct +{ + float base; + + float operator () () + { + return base; + } + + float operator () (uint x) + { + return base * float(x); + } + + float operator () (uint x, uint y) + { + return base * float(x) * float(y); + } +} + +void main(uint3 id : SV_DispatchThreadID) +{ + TestStruct obj = { 42.0f }; + + outputBuffer[0] += obj(); + outputBuffer[0] += obj(id.y); + outputBuffer[0] += obj(id.z, id.z * 2); +} +``` + + +# Memory Layout + +## Natural Layout + +The *natural layout* for a structure type uses the following rules: + +- The alignment of a structure is the maximum of 1, alignment of any member, and alignment of any parent type. +- The data is laid out in order of: + - Parent types + - Non-static data members +- Offset of the data items: + - The offset of the first data item is 0 + - The offset of the *Nth* data item is the offset+size of the previous item rounded up to the alignment of + the item +- The size of the structure is offset+size of the last item. That is, the structure is not tail-padded and rounded + up to the alignment of the structure. + +The following algorithm may be used: + +1. Initialize variables `size` and `alignment` to zero and one, respectively +2. For each field `f` of the structure type: + 1. Update `alignment` to be the maximum of `alignment` and the alignment of `f` + 2. Set `size` to the smallest multiple of `alignment` not less than `size` + 3. Set the offset of field `f` to `size` + 4. Add the size of `f` to `size` + +When this algorithm completes, `size` and `alignment` will be the size and alignment of the structure type. + +> 📝 **Remark:** Most target platforms do not use the natural layout directly, but it provides a baseline for +> defining other layouts. Any layout for a structure type must guarantee an alignment at least as large as the +> standard layout. + +## C-Style Layout + +The C-style layout of a structure type differs from the natural layout in that the structure size is rounded +up to the structure alignment. This mirrors the layout rules used by typical C/C++ compilers. + +## D3D Constant Buffer Layout + +D3D constant buffer layout is similar to the natural layout with two differences: + +- The minimum alignment is 16. +- If a data member crosses a 16-byte boundary and its offset is not aligned by 16, the offset is rounded up to the + next multiple of 16. + - In HLSL, this is called an _improper straddle_. + +This Type +--------- + +Within the body of a structure or interface declaration, the keyword `This` may be used to refer to the +enclosing type. Inside of a structure type declaration, `This` refers to the structure type itself. Inside +of an interface declaration, `This` refers to the concrete type that is conforming to the interface (that is, +the type of `this`). diff --git a/lib/All/slang/share/doc/slang/language-reference/types-traits.md b/lib/All/slang/share/doc/slang/language-reference/types-traits.md new file mode 100644 index 0000000..93909d5 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-traits.md @@ -0,0 +1,13 @@ +# Type Traits + +**TODO**: Describe all language-related type traits. + +Incomplete list: +- copyable/non-copyable (do we have movable/non-movable?) +- opaque/non-opaque +- known size/unknown size. Note: this might need further classification into implementation-specified sizes + known by `slangc` vs sizes that only the target compiler knows (but sizeof() would still work) +- allowed storage duration: static (globals), block (function locals/params/return) +- serializable/non-serializable (types that can be assigned to interface-typed variables) +- addressable/non-addressable (types that are valid types for pointers) +- etc diff --git a/lib/All/slang/share/doc/slang/language-reference/types-vector-and-matrix.md b/lib/All/slang/share/doc/slang/language-reference/types-vector-and-matrix.md new file mode 100644 index 0000000..eba5574 --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types-vector-and-matrix.md @@ -0,0 +1,237 @@ +# Vector and Matrix Types + +## Vector Types + +A `vector` represents a vector of `N` elements of type `T` where: +- `T` is a [fundamental scalar type](types-fundamental.md) +- `N` is a [specialization-time constant integer](TODO-Generics.md) in range [1, 4] denoting the number of elements. + +The default values for `T` and `N` are `float` and `4`. This is for backwards compatibility. + +### Element Access + +An element of a vector is accessed by the following means: +- Using the subscript operator `[]` (index `0` denotes the first element) +- Using the member of object operator `.` where the elements are named `x`, `y`, `z`, `w` corresponding to indexes `0`, `1`, `2`, `3`. + +Example: +```hlsl +vector v = { 1, 2, 3, 4 }; + +int tmp; + +tmp = v[0]; // tmp is 1 +tmp = v.w; // tmp is 4 +v[1] = 9; // v is { 1, 9, 3, 4 }; +``` + +Multiple elements may be referenced by specifying two or more elements after the member access operator. This can be used to: +- Extract multiple elements. The resulting type is a vector with the size equal to the number of selected elements. The same element may be specified multiple times. +- Assign multiple elements using a vector with the size equal to the number of selected elements. The elements must be unique. + +Example: +```hlsl +vector v = { 1, 2, 3, 4 }; + +int2 tmp2; +int3 tmp3; + +tmp2 = v.xy; // tmp2 is { 1, 2 } +tmp3 = v.xww; // tmp3 is { 1, 4, 4 } +v.xz = vector(-1, -3); // v becomes { -1, 2, -3, 4 } +``` + +### Operators + +When applying an unary arithmetic operator, the operator applies to all vector elements. + +Example: +```hlsl +vector v = { 1, 2, 3, 4 }; + +vector tmp; +tmp = -v; // tmp is { -1, -2, -3, -4 }; +``` + +When applying a binary arithmetic operator where the other operand is scalar, the operation applies to all vector elements with the scalar parameter. + +Example: +```hlsl +vector v = { 1, 2, 3, 4 }; + +vector tmp; +tmp = v - 1; // tmp is { 0, 1, 2, 3 }; +tmp = 4 - v; // tmp is { 4, 3, 2, 1 }; +``` + +When applying a binary assignment operator where the right-hand operand is scalar, the assignment applies to all vector element with the scalar parameter. + +Example: +```hlsl +vector v = { 1, 2, 3, 4 }; + +v += 1; // v becomes { 2, 3, 4, 5 }; +v = 42; // v becomes { 42, 42, 42, 42 }; +``` + +When applying a binary arithmetic, assignment, or comparison operator with two vectors of same length, the operator is applied element-wise. + +Example: +```hlsl +vector v1 = { 1, 2, 3, 4 }; +vector v2 = { 5, 6, 7, 8 }; + +vector tmp; +tmp = v1; // tmp is { 1, 2, 3, 4 }; +tmp = v1 + v2; // tmp is { 6, 8, 10, 12 }; +tmp = v1 * v2; // tmp is { 5, 12, 21, 32 }; + +vector cmpResult; +cmpResult = (v1 == vector(1, 3, 2, 4)); +// cmpResult is { true, false, false, true } + +v1 -= v2; // v1 becomes { -4, -4, -4, -4 }; +``` + +### Standard Type Aliases + +Slang provides type aliases for all vectors between size 1 and 4 for fundamental scalar types. The type alias has name `N` where `` is one of the fundamental types and `N` is the vector length. + +Example: + +```hlsl +float4 v = { 1.0f, 2.0f, 3.0f, 4.0f }; // vector +int32_t2 i2 = { 1, 2 }; // vector +bool3 b3 = { true, false, false }; // vector +``` + +### Memory Layout + +The memory layout of a vector type is `N` contiguous values of type `T` with no padding. + +The alignment of a vector type is target-defined. The alignment of `vector` is at least the alignment of `T` and at most `N` times the alignment of `T`. + + +## Matrix Types + +Type `matrix` represents a `R`×`C` matrix of elements of type `T` where: +- `T` is a [fundamental scalar type](types-fundamental.md) +- `R` is a [specialization-time constant integer](TODO-Generics.md) in range [1, 4] denoting the number of rows. +- `C` is a [specialization-time constant integer](TODO-Generics.md) in range [1, 4] denoting the number of columns. + +The default values for `T`, `R`, `C` are `float`, `4`, `4`. This is for backwards compatibility. + +### Row and element access ### + +A row of a matrix is accessed by the subscript operator `[]` (index `0` denotes the first row). + +The element of a row is accessed by the following means: +- Using the subscript operator `[]` (index `0` denotes the first column) +- Using the member of object operator `.` where the columns are named `x`, `y`, `z`, `w` corresponding to column indexes `0`, `1`, `2`, `3`. + +Example: +```hlsl +matrix v = { + 1, 2, 3, 4, // row index 0 + 5, 6, 7, 8, // row index 1 + 9, 10, 11, 12 // row index 2 +}; + +int tmp1 = v[1][2]; // tmp1 is 7 (row index 1, column index 2) +int tmp2 = v[1].w; // tmp2 is 8 (row index 1, column index 3) +int4 tmp3 = v[2]; // tmp3 is { 9, 10, 11, 12 } +int2 tmp4 = v[0].yx; // tmp4 is { 2, 1 } +``` + + +### Operators + +When applying an unary operator, the operator applies to all matrix elements. + +When applying a binary operator, it is applied element-wise. Both the left-hand side and the right-hand side operands must be matrices of the same dimensions. + +The [matrix multiplication](https://en.wikipedia.org/wiki/Matrix_multiplication) is performed using function `mul()`, which has the following basic forms: +- matrix/matrix form `mul(m1, m2)` where `m1` is an `M`×`N` matrix and `m2` is an `N`×`P` matrix. The result is an `M`×`P` matrix. +- vector/matrix form `mul(v, m)` where `v` is a vector of length `N` and `m` is an `N`×`P` matrix. The result is a vector of length `P`. + - `v` is interpreted as a row vector, *i.e.*, a `1`×`N` matrix. +- matrix/vector form `mul(m, v)` where `m` is an `M`×`N` matrix and `v` is a vector of length `N`. The result is a vector of length `M`. + - `v` is interpreted as a column vector, *i.e.*, an `N`×`1` matrix. + +> 📝 **Remark 1:** The operator `*` performs element-wise multiplication. It should be used only when the element-wise multiplication of same-sized matrices is desired. + +> 📝 **Remark 2:** The operator `*` differs from GLSL, where it performs matrix multiplication. When porting code from GLSL to Slang, replace matrix multiplications using `*` with calls to `mul()`. + + +### Standard Type Aliases + +Slang provides type aliases for all matrices between 1 and 4 rows and columns for fundamental scalar +types. The type alias has name `RxC` where `` is one of the fundamental +types, `R` is the number of rows, and `C` is the number of columns. + +Example: + +```hlsl +// matrix +float4x3 m = { + 1.1f, 1.2f, 1.3f, + 2.1f, 2.2f, 2.3f, + 3.1f, 3.2f, 3.3f, + 4.1f, 4.2f, 4.3f, +}; +``` + + +### Memory Layout + +Matrix types support both _row-major_ and _column-major_ memory layout. +Implementations may support command-line flags or API options to control the default layout to use for matrices. + +Under row-major layout, a matrix is laid out in memory equivalently to an `R`-element array of `vector` elements. + +Under column-major layout, a matrix is laid out in memory equivalent to the row-major layout of its transpose. +That is, the layout is equivalent to a `C`-element array of `vector` elements. + +> 📝 **Remark 1:** Slang currently does *not* support the HLSL `row_major` and `column_major` modifiers to set the +> layout used for specific declarations. + +The alignment of a matrix is target-specified. In general, it is at least the alignment of the element and at +most the size of the matrix rounded up to the next power of two. + + +### Important Note for OpenGL, Vulkan, Metal, and WebGPU Targets ### + +Slang considers matrices as rows of vectors (row major), similar to HLSL and the usual mathematical +conventions. However, many graphics APIs including OpenGL, Vulkan, Metal, and WebGPU consider matrices as +columns of vectors (column major). + +Summary of differences + +| | Slang and HLSL | GLSL, SPIR-V, MSL, WGSL | +|------------------------------------|------------------|-------------------------| +| Initializer element ordering | Row major | Column major | +| type for float, 3 rows × 4 columns | `float3x4` | `mat4x3` (or similar) | +| Element access | `m[row][column]` | `m[column][row]` | + +However, for efficient element access with the subscript operator `[]`, Slang reinterprets columns as rows and +vice versa on these targets. That is, a Slang `float3x4` matrix type maps to a `mat3x4` matrix type in +GLSL. This also applies to row major and column major memory layouts. Similar reinterpretation is performed +also by other compilers when compiling HLSL to SPIR-V. + +Perhaps most notably, this reinterpretation results in swapped order in matrix multiplication in target +code. For example: + +Slang source code: +```hlsl +float4 doMatMul(float4x3 m, float3 v) +{ + return mul(m, v); +} +``` + +Translated GLSL target code: +```glsl +vec4 doMatMul_0(mat4x3 m_0, vec3 v_0) +{ + return (((v_0) * (m_0))); +} +``` diff --git a/lib/All/slang/share/doc/slang/language-reference/types.md b/lib/All/slang/share/doc/slang/language-reference/types.md new file mode 100644 index 0000000..0818d2e --- /dev/null +++ b/lib/All/slang/share/doc/slang/language-reference/types.md @@ -0,0 +1,177 @@ +# Types + +Slang types: +* [Fundamental Types](types-fundamental.md) +* [Vector and Matrix Types](types-vector-and-matrix.md) +* [Structures](types-struct.md) and [Classes](types-class.md) + * [Extensions](types-extension.md) +* [Array Types](types-array.md) +* [Pointers](types-pointer.md) +* [Interfaces](types-interface.md) +* [Special Types](types-special.md) + +Other topics: +* [Type Traits](types-traits.md) +* [Type Attributes](types-attributes.md) + + +## Type Specifiers {#specifier} + +A [type specifier](#specifier) names a type. Type specifiers are used in variable declarations, function +parameter and return type declarations, and elsewhere where a type is required. Type specifiers are divided +into two categories: + +- A **simple type specifier** is a type expression that names a type but never declares one. Simple type + specifiers are used in function parameter and return type declarations, modern variable declarations, type + constraints, and other places where the ability to declare new types is not expected. Two main forms + exist: + - *Simple type identifier specifier* based on a previously declared type, optionally with an array + declaration and generic parameters. + - *Simple function type specifier* specifying a function type. +- A **type specifier** is a type expression that names a type, possibly by declaring it. A simple type + specifier is a subset of the full type specifier. A type specifier is a part of the + [variable declaration](declarations.md) syntax, which is used to declare variables, as the name suggests. + +### Syntax {#syntax} + +Simple type specifier: +> *`simple-type-spec`* =
+>     (*`simple-type-id-spec`*
+>     |*`simple-type-func-spec`*) + +Type specifier for named non-array, array, non-pointer, and pointer types: +> *`simple-type-id-spec`* =
+>     [*`modifier-list`*]
+>     *`type-identifier`*
+>     [*`generic-params-decl`*]
+>     (**`'['`** [*`constant-index-expr`*] **`']'`** | **`'*'`** )* + +Type specifier for function types: +> *`simple-type-func-spec`* =
+>     [*`modifier-list`*]
+>     **`'functype'`** **`'('`** *`param-list`* **`')'`** **`'->'`** *`simple-type-id-spec`* + +Full type specifier, possibly declaring a new type: +> Simple type specifier:
+> *`type-spec`* = *`simple-type-spec`* +>

+> struct/class/enum type specifier:
+> *`type-spec`* =
+>     (*`struct-decl`* | *`class-decl`* | *`enum-decl`*)
+>     [*`generic-params-decl`*]
+>     (**`'['`** [*`constant-index-expr`*] **`']'`** | **`'*'`** )*
+ +#### Parameters + +- *`modifier-list`* is an optional list of modifiers (TODO: link) +- *`type-identifier`* is an identifier that names an existing type or a generic type. For example, this may be + a [fundamental type](types-fundamental.md), [vector/matrix generic type](types-vector-and-matrix.md), + user-defined type such as a named [structure type](types-struct.md), [interface type](types-interface.md), + [enumeration type](types-enum.md), type alias, or a type provided by a module. +- *`generic-params-decl`* is a generic parameters declaration. See [Generics (TODO)](TODO). +- **`'['`** [*`constant-index-expr`*] **`']'`** is an [array dimension declaration](types-array.md) with an + optional constant integral expression specifying the dimension length. +- **`'*'`** is a [pointer declaration](types-pointer.md). +- *`param-list`* is a function parameter list. See [function parameter list (TODO)](TODO). +- *`struct-decl`* is a [structure](types-struct.md) type declaration, possibly also defining the type. +- *`class-decl`* is a [class (TODO)](types-class.md) type declaration, possibly also defining the type. +- *`enum-decl`* is an [enumeration (TODO)](types-enum.md) type declaration, possibly also defining the type. + + +### Description + +A type specifier names a type and possibly also declares a new type. The named type is always a non-generic +type. If *`type-identifier`* specifies a generic type, generic parameters *`generic-params-decl`* must be +provided to fully specialize the type. + +Simple type specifiers *`simple-type-spec`* only name types but never declare new types. Simple type +specifiers are used in: +- [modern variable (TODO)](TODO) declarations +- [function parameter (TODO)](TODO) declarations +- [function return value type (TODO)](TODO) declarations +- [structure property](types-struct.md#property) +- [structure subscript operator](types-struct.md#subscript-op) +- [generic type parameter declarations (TODO)](TODO) +- [typealias](#alias) declarations + +Declaration of new types is allowed in: +- Global declaration statements (TODO: link) +- Function body declaration statements (TODO: link) +- Traditional variable declarations (TODO: link) +- [structure](types-struct.md) members declaring nested types +- [extension](types-extension.md) members declaring nested types +- [typedef](#alias) declarations + +> 📝 **Remark 1:** *`simple-type-spec`* is a syntactic subset of the full *`type-expr`*. The subset only names +> a type but never declares one. + +> 📝 **Remark 2:** The dual nature of type expressions---naming and possibly declaring a type---is a side +> effect of the C-style type expression grammar. This extends to traditional variable declarations where a +> single declaration can declare a type and one or more variables. (TODO: link) + +> 📝 **Remark 3:** Unlike in C++, `const`, `inline`, `volatile`, and similar keywords are modifiers. This +> restricts their allowed placement to the left of the type specifier. For example, `const int a = 5;` is a +> valid variable declaration but `int const a = 5;` is not. + + +## Type Alias Declarations {#alias} + +A [type alias](#alias) is a name that refers to a previously declared type. + +### Syntax + +Type alias declaration: +> **`'typealias'`** *`identifier`* **`'='`** *`simple-type-spec`* **`';'`** + +Typedef declaration: +> **`'typedef'`** *`type-spec`* *`identifier`* **`';'`** + +Generic type alias declaration: +> **`'typealias'`** *`identifier`*
+>      *`generic-params-decl`* (**`'where'`** *`where-clause`*)\* **`'='`**
+>     *`simple-type-spec`* [*`generic-params-decl`*] **`';'`** + +### Description + +A `typealias` declaration introduces a name for a type. A `typedef` declaration is an alternative syntax that +also allows declaring a new type. + +A generic type alias declaration declares a parameterized alias for a generic type. This is described in +[Generics (TODO)](TODO). + + +## Complete and Incomplete Types {#incomplete} + +A type is incomplete when it is declared but not defined. An incomplete type cannot be used to declare +variables. An incomplete type other than `void` may be completed with a subsequent definition. For further +information, see [declarations](declarations.md). + + +## Memory Layout + +Types in Slang do not generally have identical memory layouts in different targets. Any unspecified details on +layout may depend on the target language, the target device, the declared extensions, the compiler options, +and the context in which a type is used. + + +## Known and Unknown Size + +Every type has either a known or an unknown size. Types with unknown size generally stem from unknown-length +arrays: +* An unknown-length array type has an unknown size. +* The size of a structure type is unknown if it has a non-static data member with unknown size. + +The use of types with unknown size is restricted as follows: +* A type with unknown size cannot be used as the element type of an array. +* A type with unknown size can only be used as the last field of a structure type. +* A type with unknown size cannot be used as a generic argument to specialize a user-defined type, function, + etc. Specific built-in generic types/functions may support unknown-size types, and this will be documented + on the specific type/function. +* A type with unknown size cannot be instantiated as a variable. + +> 📝 **Remark:** Unknown size is different from unspecified or target-specified size. Many +> [special types](types-special.md) have target-specified sizes; sizes of [structures](types-struct.md) and +> [arrays](types-array.md) are subject to target-specific alignment rules; and certain +> [fundamental types](types-fundamental.md) such as `bool` have target-specified sizes. Types with unspecified +> or target-specified sizes are not subject to the restrictions of types with unknown sizes, although they may +> have other restrictions. diff --git a/lib/All/slang/share/doc/slang/layout.md b/lib/All/slang/share/doc/slang/layout.md new file mode 100644 index 0000000..75e4b98 --- /dev/null +++ b/lib/All/slang/share/doc/slang/layout.md @@ -0,0 +1,228 @@ +Parameter Layout Rules +====================== + +An important goal of the Slang project is that the rules for how shader parameters get assigned to `register`s/`binding`s is completely deterministic, so that users can rely on the compiler's behavior. +This document will attempt to explain the rules that Slang employs at a high level. +Eventually it might evolve into a formal specification of the expected behavior. + +Guarantees +---------- + +The whole point of having a deterministic layout approach is the guarantees that it gives to users, so we will start by explicitly stating the guarantees that users can rely upon: + +* A single top-level shader parameter will always occupy a contiguous range of bindings/registers for each resource type it consumes (e.g., a contiguous range of `t` registers, a contiguous range of bytes in a `cbuffer`, etc.). + +* The amount of resources a parameter consumes depends only on its type, and top-level context in which it appears (e.g., is it in a `cbuffer`? an entry-point varying parameter? etc.). + +* A shader parameter that is declared the same way in two different programs will get the same *amount* of resources (registers/bytes) allocated for it in both programs, but it might get a different starting offset/register. + +* Changing the bodies of functions in shader code cannot change the layout of shader parameters. In particular, just because a shader parameter is "dead" does not mean it gets eliminated. + +* If the user doesn't use explicit `register`/`layout` modifiers to bind parameters, then each module will get a contiguous range of bindings, and the overall program will always use a contiguous range starting from zero for each resource type. + +Overview of the Layout Algorithm +-------------------------------- + +Layout is applied to a Slang *compile request* which comprises one or more *translation units* of user code, and zero or more `import`ed modules. +The compile request also specifies zero or more *entry points* to be compiled, where each entry point identifies a function and a profile to use. + +Layout is always done with respect to a chosen *target*, and different targets might compute the resource usage for types differently, or apply different alignment. +Within a single target there may also be different layout rules (e.g., the difference between GLSL `std140` and `std430`). + +Layout proceeds in four main phases: + +1. Establish a global ordering on shader parameters +2. Compute the resource requirements of each shader parameter +3. Process shader parameters with fixed binding modifiers +4. Allocate bindings to parameter without fixed binding modifiers + +Ordering (and Collapsing) Shader Parameters +------------------------------------------- + +Shader parameters from the user's code always precede shader parameters from imported modules. +The order of parameters in the user's code is derived by "walking" through the code as follows: + +* Walk through each translation unit in the order they were added via API (or the order they were listed on the command line) + +* Walk through each source file of a translation unit in the order they were added/listed + +* Walk through global-scope shader parameter declarations (global variables, `cbuffer`s, etc.) in the order they are listed in the (preprocessed) file. + +* After all global parameters for a translation unit have been walked, walk through any entry points in the translation unit. + +* When walking through an entry point, walk through all of its function parameters (both uniforms and varyings) in order, and then walk the function result as a varying output parameter. + +When dealing with global-scope parameters in the user's code, it is possible for the "same" parameter to appear in multiple translation units. +Any two global shader parameters in user code with the same name are assumed to represent the same parameter, and will only be included in the global order at the first location where they are seen. +It is an error for the different declarations to have a mismatch in type, or conflicting explicit bindings. + +Parameters from `import`ed modules are enumerated after the user code, using the order in which modules were first `import`ed. +The order of parameters within each module is the same as when the module was compiled, which matches the ordering given above. + +Computing Resource Requirements +------------------------------- + +Each shader parameter computes its resource requirements based on its type, and how it is declared. + +* Global-scope parameters, entry point `uniform` parameters, and `cbuffer` declarations all use the "default" layout rules + +* Entry point non-`uniform` parameters use "varying" layout rules, either input or output + +* A few other special case rules exist (e.g., for laying out the elements of a `StructuredBuffer`), but most users will not need to worry about these + +Note that the "default" rules are different for D3D and GL/Vulkan targets, because they have slightly different packing behavior. + +### Plain Old Data + +Under the default rules simple scalar types (`bool`, `int`, `float`, etc.) are laid out as "uniform" data (that is, bytes of ordinary memory). +In most cases, the size matches the expected data type size (although be aware that most targets treat `bool` as a synonym for `int`) and the alignment is the same as the size. + +### Vectors + +Vectors are laid out as N sequential scalars. +Under HLSL rules, a vector has the same alignment as its scalar type. +Under GLSL `std140` rules, a vector has an alignment that is its size rounded up to the next power of two (so a `float3` has `float4` alignment). + +### Opaque Types + +"Opaque" types include resource/sampler types like `Texture2D` and `SamplerState`. +These consume a single "slot" of the appropriate category for the chosen API. + +Note that when compiling for D3D, a `Texture2D` and a `SamplerState` will consume different resources (`t` and `s` registers, respectively), but when compiling for Vulkan, they both consume the same resource ("descriptor table slot"). + +Opaque types currently all have an alignment of one. + +### Structures + +A structure is laid out by initializing a counter for each resource type, and then processing fields sequential (in declaration order): + +* Compute resource usage for the field's type + +* Adjust counters based on the alignment of the field for each resource type where it has non-zero usage + +* Assign an offset to the field for each resource type where it has non-zero usage + +* Add the resource usage of the field to the counters + + +An important wrinkle is that when doing layout for HLSL, we must ensure that if a field with uniform data that is smaller than 16 bytes would straddle a 16-byte boundary, we advance to the next 16-byte aligned offset. + +The overall alignment of a `struct` is the maximum alignment of its fields or the default alignment (if it is larger). +The default alignment is 16 for both D3D and Vulkan targets. + +The final resource usage of a `struct` is rounded up to a multiple of the alignment for each resource type. Note that we allow a `struct` to consume zero bytes of uniform storage. + +It is important to note that a `struct` type can use resources of many different kinds, so in general we cannot talk about the "size" of a type, but only its size for a particular kind of resource (uniform bytes, texture registers, etc.). + +### Sized Arrays + +For uniform data, the size of the element type is rounded up to the target-specific minimum (e.g., 16 for D3D and Vulkan constant buffers) to arrive at the *stride* of the array. The total size of the array is then the stride times the element count. + +For opaque resource types, the D3D case simply takes the stride to be the number of registers consumed by each element, and multiplies this by the element count. + +For Vulkan, an array of resources uses only a single `binding`, so that the stride is always zero for these resource kinds, and the resource usage of an array is the same as its element type. + +### Unsized Arrays + +The uniform part of an unsized array has the same stride as for the sized case, but an effectively infinite size. + +For register/binding resource usage, a Vulkan unsized array is just like a sized one, while a D3D array will consume a full register *space* instead of individual registers. + +### Constant Buffers + +To determine the resource usage of a constant buffer (either a `cbuffer { ... }` declaration or a `ConstantBuffer`) we look at the resource usage of its element type. + +If the element uses any uniform data, the constant buffer will use at least one constant-buffer register (or whatever the target-specific resource is). +If the element uses any non-uniform data, that usage will be added to that of the constant buffer. + +### Parameter Blocks + +A parameter block is similar to a constant buffer. +If the element type uses any uniform data, we compute resource usage for a constant buffer. +We then add in any non-uniform resource usage for the element types. + +If the target requires use of register spaces (e.g., for Vulkan), then a parameter block uses a single register space; otherwise it exposes the resource usage of its element type directly. + +Processing Explicit Binding Modifiers +------------------------------------- + +If the user put an explicit binding modifier on a parameter, and that modifier applies to the current target, then we use it and "reserve" space in the overall binding range. + +Traditional HLSL `register` modifiers only apply for D3D targets. +Slang currently allows GLSL-style `layout(binding =...)` modifiers to be attached to shader parameters, and will use those modifiers for GL/Vulkan targets. + +If two parameters reserve overlapping ranges, we currently issue an error. +This may be downgraded to a warning for targets that support overlapping ranges. + +Allocating Bindings to Parameters +--------------------------------- + +Once ranges have been reserved for parameters with explicit bindings, the compiler goes through all parameters again, in the global order and assigns them bindings based on their resource requirements. + +For each resource type used by a parameter, it is allocated the first contiguous range of resources of that type that have not been reserved. + +Splitting of Arrays +------------------- + +In order to support `struct` types that mix uniform and non-uniform data, the Slang compiler always "splits" these types. +For example, given: + +```hlsl +struct LightInfo { float3 pos; Texture2D shadowMap; }; + +LightInfo gLight; +``` + +Slang will generate code like: + +```hlsl +float3 gLight_pos; +Texture2D gLight_shadowMap; +``` + +In a simple case like the above, this doesn't affect layout at all, but once arrays get involved, the layout can be more complicated. Consider this case: + +```hlsl +struct Pair { Texture2D a; Texture2D b; }; +Pair gPairs[8]; +``` + +The output from the splitting step is equivalent to: + +```hlsl +Texture2D gPairs_a[8]; +Texture2D gPairs_b[8]; +``` + +While this transformation is critical for having a type layout algorithm that applies across all APIs (and also it is pretty much required to work around various bugs in downstream compilers), it has the important down-side that the value `gPairs[0]` does not occupy a contiguous range of registers (although the top-level shader parameter `gPairs` *does*). + +The Slang reflection API will correctly report the information about this situation: + +* The "stride" of the `gPairs` array will be reported as one, because `gPairs[n+1].a` is always one register after `gPairs[n].a`. + +* The offset of the `gPairs.b` field will be reported as 8, because `gPairs[0].b` will be 8 registers after the starting register for `gPairs`. + +The Slang API tries to provide the best information it can in this case, but it is still important for users who mix arrays and complex `struct` types to know how the compiler will lay them out. + +Generics +-------- + +Generic type parameters complicate these layout rules. +For example, we cannot compute the exact resource requirements for a `vector` without knowing what the type `T` is. + +When computing layouts for fully specialized types or programs, no special considerations are needed: the rules as described in this document still apply. +One important consequence to understand is that given a type like: + +```hlsl +struct MyStuff +{ + int a; + T b; + int c; +} +``` + +the offset computed for the `c` field depends on the concrete type that gets plugged in for `T`. +We think this is the least surprising behavior for programmers who might be familiar with things like C++ template specialization. + +In cases where confusion about a field like `c` getting different offsets in different specializations is a concern, users are encouraged to declare types so that all non-generic-dependent fields come before generic-dependent ones. diff --git a/lib/All/slang/share/doc/slang/llvm-target.md b/lib/All/slang/share/doc/slang/llvm-target.md new file mode 100644 index 0000000..96a57c0 --- /dev/null +++ b/lib/All/slang/share/doc/slang/llvm-target.md @@ -0,0 +1,183 @@ +Slang LLVM Targets +================== + +The LLVM targets are capable of creating LLVM IR and object code for arbitrary +target triples (`--`, e.g. `x86_64-unknown-linux`). This +allows for highly performant and debuggable Slang code on almost any platform, +as long as an LLVM backend exists for it. + +The current state is highly experimental and there are many missing features. +The feature also focuses heavily on CPUs for now. + +## Targets + +The HOST / SHADER split from the [CPU target](cpu-target.md) applies here as well. + +The following targets always use LLVM: +* `llvm-ir` / `SLANG_HOST_LLVM_IR` generates LLVM IR in the text representation, suitable for free-standing functions. +* `llvm-shader-ir` / `SLANG_SHADER_LLVM_IR` generates LLVM IR for compute shader entry points. + +The following targets use LLVM when `-emit-cpu-via-llvm` or `EmitCPUMethod=SLANG_EMIT_CPU_VIA_LLVM` is specified: +* `host-object-code` / `SLANG_HOST_OBJECT_CODE` generates position-independent object code, which can be +linked into an executable or a static or dynamic library. +* `shader-object-code` / `SLANG_OBJECT_CODE` generates object code for compute shader entry points. +* `SLANG_HOST_HOST_CALLABLE` and `SLANG_SHADER_HOST_CALLABLE` JIT compile the module. + +Support for `exe` / `SLANG_HOST_EXECUTABLE` and `sharedlib` / +`SLANG_HOST_SHARED_LIBRARY` may be added later, once the LLVM target has +stabilized. For compiling to platforms other than the current CPU running the +Slang compiler, the following options are provided: + +* `-llvm-target-triple `. The default is the host machine's triple. +* `-llvm-cpu ` sets the target CPU, similar to Clang's `-mcpu=`. +* `-llvm-features ` sets the available features, similar to LLC's `-mattr=`. + +## Features + +* Compile stand-alone programs in Slang for platforms supported by LLVM +* Focus on memory layout correctness: type layouts such as the scalar layout are handled correctly +* Does not depend on external compilers (although, currently depends on external linkers!) +* Works well with debuggers! + +## Standalone programs + +You can write functions decorated with `export` to make them visible from the +resulting object code, and `__extern_cpp` to unmangle their names. So, for a +standalone Slang application, the entry point is: + +```slang +export __extern_cpp int main(int argc, NativeString* argv) +{ + // Do whatever you want here! + return 0; +} +``` + +To cross-compile, you can use `-llvm-target-triple `. For now, +you'll need to compile into an object file and use a compiler or linker to turn +that into an executable, e.g. with `clang main.o -o main.exe`. + +## Application Binary Interface + +This section defines the ABI rules which code generated by the LLVM target +follows and expects of external code calling into it. + +The default type layout aligns vectors to the next power of two, structures are +aligned and padded up to the largest alignment among their fields, and booleans +are a single byte. + +If you specify a different layout with flags like `-fvk-use-c-layout` or +`-fvk-use-scalar-layout`, all structure and array types on the stack and heap +will follow those layout rules. + +### Types and resources + +* `StructuredBuffer` and `ByteAddressBuffer` are stored as `{ Type* data; intptr_t size; }`, +where `size` is the number of elements in `data`. + +* Vectors are passed as LLVM vector types; there's no direct equivalent in standard C or C++. + +* Matrix types are lowered into arrays of vectors. Column and row major matrices are supported as normal. + +### Aggregate parameters + +All aggregates (structs and arrays) are always passed by reference in Slang's +LLVM emitter. Other than that, the target platform's C calling conventions are +followed. This stems from [LLVM not handling aggregates correctly](https://discourse.llvm.org/t/passing-structs-to-c-functions/83938/8) in calling conventions, and requiring every frontend to painstakingly +reimplement the same per-target logic if they want full C compatibility. + +This means that if you declare a function like this in Slang: +```slang +export __extern_cpp MyStruct func(MyStruct val); +``` + +It would have the following signature in C: +```slang +void func(const MyStruct *val, MyStruct *returnval); +``` + +In other words, aggregate parameters are turned into pointers and aggregate +return values are turned into an additional pointer-typed parameter at the end +of the parameter list. + +### C foreign functions + +Due to the aggregate parameter passing limitation of LLVM, calling arbitrary C +functions from Slang is complicated, and a hypothetical binding generator would +need to generate calling convention adapter functions. A binding generator would +be a useful tool to include, but remains as future work. + +## Limitations + +The LLVM target support is work-in-progress, and there are currently many +limitations. + +### CPU targets only + +Currently, support is limited to conventional CPU targets. The emitted LLVM IR +is not compatible with LLVMs SPIR-V target, for example. At least resource +bindings and pointer address spaces would have to be accounted for to expand +support to GPU targets. Slang already has native emitters for GPU targets, so +you can use those instead of going through LLVM. + +### Pointer size + +Currently, the Slang compiler assumes that the size of pointers matches the +compiler's host platform. This means that on a 64-bit PC, only target triples +with 64-bit pointers generate correct code. This can be a difficulty if one +wants to build Slang programs for a 32-bit microcontroller, and should +hopefully be fixed eventually. + +### Missing compute shader features + +* No `groupshared` +* No barriers. +* No atomics. +* No wave operations. + +These limitations stem from the fact that work items / threads of a work group +are currently run serially instead of actually being in parallel. This may be +improved upon later. + +### Limited vectorization + +Vector instructions are vectorized in the way typical CPU math libraries +(e.g. GLM) vectorize, as long as the target CPU allows for vector instructions. +This is worse than how GPUs do it, where each work item / thread gets a SIMD +lane. This aspect may be improved upon later. + +### Compatibility with prior CPU Slang features + +There are limitations regarding features of the existing C++ based [CPU target](./cpu-target.md). +The following features are not yet supported: + +* `String` type. +* `new`. +* `class`. +* COM interfaces. + +The implementations of these rely on C++ features, and are not trivial to +implement in LLVM. Support for them may be added later. + +### Missing types + +* No texture or sampler types. +* No acceleration structures. + +These are missing due to limitation of scope for the initial implementation, +and may be added later. + +## Gotchas + +### Out-of-bounds buffer access + +Attempting to index past the end of any buffer type is undefined behaviour. It +is not guaranteed to return zero as in HLSL; segmentation faults and memory +corruption are more than likely to occur! + +### `sizeof` + +Slang's `sizeof` may appear to "lie" to you about structs that contain padding, +unless you specify `-fvk-use-scalar-layout`. That's because it queries layout +information without knowing about the actual layout being used. Use `__sizeOf` +instead to get accurate sizes from LLVM, e.g. for memory allocation purposes. diff --git a/lib/All/slang/share/doc/slang/nvapi-support.md b/lib/All/slang/share/doc/slang/nvapi-support.md new file mode 100644 index 0000000..cb96f65 --- /dev/null +++ b/lib/All/slang/share/doc/slang/nvapi-support.md @@ -0,0 +1,89 @@ +NVAPI Support +============= + +Slang provides support for [NVAPI](https://developer.nvidia.com/nvapi) in several ways + +* Slang allows the use of NVAPI directly, by the inclusion of the `#include "nvHLSLExtns.h"` header in your Slang code. Doing so will make all the NVAPI functions directly available and usable within your Slang source code. +* NVAPI is used to provide features implicitly for certain targets. For example support for [RWByteAddressBuffer atomics](target-compatibility.md) on HLSL based targets is supported currently via NVAPI. +* Direct and implicit NVAPI usage can be freely mixed. + +Direct usage of NVAPI +===================== + +Direct usage of NVAPI just requires the inclusion of the appropriate NVAPI header, typically with `#include "nvHLSLExtns.h` within your Slang source. As is required by NVAPI before the `#include` it is necessary to specify the slot and perhaps space usage. For example a typical direct NVAPI usage inside a Slang source file might contain something like... + +``` +#define NV_SHADER_EXTN_SLOT u0 +#include "nvHLSLExtns.h" +``` + +In order for the include to work, it is necessary for the include path to include the folder that contains the nvHLSLExtns.h and associated headers. + +Implicit usage of NVAPI +======================= + +It is convenient and powerful to be able to directly use NVAPI calls, but will only work on such targets that support the mechansism, even if there is a way to support the functionality some other way. + +Slang provides some cross platform features on HLSL based targets that are implemented via NVAPI. For example RWByteAddressBuffer atomics are supported on Vulkan, DX12 and CUDA. On DX12 they are made available via NVAPI, whilst CUDA and Vulkan have direct support. When compiling Slang code that uses RWByteAddressBuffer atomics Slang will emit HLSL code that use NVAPI. In order for the downstream compiler to be able to compile this HLSL it must be able to include the NVAPI header `nvHLSLExtns.h`. + +It worth discussing briefly how this mechanism works. Slang has a 'prelude' mechanism for different source targets. The prelude is a piece of text that is inserted before the source that is output from compiling the input Slang source code. There is a default prelude for HLSL that is something like + +``` +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif +``` + +If there are any calls to NVAPI implicitly from Slang source, then the following is emitted before the prelude + +``` +#define SLANG_HLSL_ENABLE_NVAPI 1 +#define NV_SHADER_EXTN_SLOT u0 +#define NV_SHADER_EXTN_REGISTER_SPACE space0 +``` + +Thus causing the prelude to include nvHLSLExtns.h, and specifying the slot and potentially the space as is required for inclusion of nvHLSLExtns.h. + +The actual values for the slot and optionally the space, are found by Slang examining the values of those values at the end of preprocessing input Slang source files. + +This means that if you compile Slang source that has implicit use NVAPI, the slot and optionally the space must be defined. This can be achieved with a command line -D, through the API or through having suitable `#define`s in the Slang source code. + +It is worth noting if you *replace* the default HLSL prelude, and use NVAPI then it will be necessary to have something like the default HLSL prelude part of your custom prelude. + +Downstream Compiler Include +--------------------------- + +There is a subtle detail that is perhaps worth noting here around the downstream compiler and `#include`s. When Slang outputs HLSL it typically does not contain any `#include`, because all of the `#include` in the original source code have been handled by Slang. Slang then outputs everything required to compile to the downstream compiler *without* any `#include`. When NVAPI is used explicitly this is still the case - the NVAPI headers are consumed by Slang, and then Slang will output HLSL that does not contain any `#include`. + +The astute reader may have noticed that the default Slang HLSL prelude *does* contain an include, which is enabled via SLANG_HLSL_ENABLE_NVAPI macro which Slang will set with implicit NVAPI use. + +``` +#ifdef SLANG_HLSL_ENABLE_NVAPI +#include "nvHLSLExtns.h" +#endif +``` + +This means that the *downstream* compiler (such as DXC and FXC) must be able to handle this include. Include paths can be specified for downstream compilers via the [-X mechanism](user-guide/08-compiling.md#downstream-arguments). So for example... + +``` +-Xfxc -IpathTo/nvapi -Xdxc -IpathTo/nvapi +``` + +In the explicit scenario where `nvHLSLExtns.h` is included in Slang source, the include path must be specified in Slang through the regular mechanisms. + +In a scenario with both implicit and explicit use, both Slang *and* the downstream compiler need to have a suitable path specified. Things can be more complicated if there is mixed implicit/explicit NVAPI usage and in the Slang source the include path is set up such that NVAPI is included with + +``` +#include "nvapi/nvHLSLExtns.h" +``` + +Since Slang and the downstream compilers can specify different include paths, the downstream compiler include path can be such that `#include "nvHLSLExtns.h"` works with the default prelude. + +Another way of working around this issue is to alter the prelude for downstream compilers such that it contains an absolute path for the `#include`. This is the mechanism that is currently used with the Slang test infrastructure. + +Links +----- + +More details on how this works can be found in the following PR + +* [Simplify workflow when using NVAPI #1556](https://github.com/shader-slang/slang/pull/1556) diff --git a/lib/All/slang/share/doc/slang/repro.md b/lib/All/slang/share/doc/slang/repro.md new file mode 100644 index 0000000..4d469fa --- /dev/null +++ b/lib/All/slang/share/doc/slang/repro.md @@ -0,0 +1,90 @@ +Slang Compilation Reproduction +============================== + +Slang has both API and command line support for reproducing compilations, so called 'repro' functionality. + +One use of the feature is if a compilation fails, or produces an unexpected or wrong result, it provides a simple to use mechanism where the compilation can be repeated or 'reproduced', most often on another machine. Instead of having to describe all the options, and make sure all of the files that are used are copied, and in such a way that it repeats the result, all that is required is for the compilation to be run on the host machine with repro capture enabled, and then that 'repro' used for a compilation on the test machine. There are also some mechanisms where the contents of the original compilation can be altered. + +The actual data saved is the contents of the SlangCompileRequest. Currently no state is saved from the SlangSession. Saving and loading a SlangCompileRequest into a new SlangCompileRequest should provide two SlangCompileRequests with the same state, and with the second compile request having access to all the files contents the original request had directly in memory. + +There are a few command line options + +* `-dump-repro [filename]` dumps the compilations state (ie post attempting to compile) to the file specified afterwards +* `-extract-repro [filename]` extracts the contents of the repro file. The contained files are placed in a directory with a name, the same as the repro file minus the extension. Also contains a 'manifest'. +* `-load-repro [filename]` loads the repro and compiles using it's options. Note this must be the last arg on the command line. +* `-dump-repro-on-error` if a compilation fails will attempt to save a repro (using a filename generated from first source filename) +* `-repro-file-system [filename]` makes the repros file contents appear as the file system during a compilation. Does not set any compilation options. +* `-load-repro-directory [directory]` compiles all of the .slang-repro files found in `directory` + +The `manifest` made available via `-extract-repro` provides some very useful information + +* Provides an approximation of the command line that will produce the same compilation under [compile-line] +* A list of all the unique files held in the repro [files]. It specified their 'unique name' (as used to identify in the repro) and their unique identifier as used by the file system. +* A list of how paths map to unique files. Listed as the path used to access, followed by the unique name used in the repro + +First it is worth just describing what is required to reproduce a compilation. Most straightforwardly the options setup for the compilation need to be stored. This would include any flags, and defines, include paths, entry points, input filenames and so forth. Also needed will be the contents of any files that were specified. This might be files on the file system, but could also be 'files' specified as strings through the slang API. Lastly we need any files that were referenced as part of the compilation - this could be include files, or module source files and so forth. All of this information is bundled up together into a file that can then later be loaded and compiled. This is broadly speaking all of the data that is stored within a repro file. + +In order to capture a complete repro file typically a compilation has to be attempted. The state before compilation can be recorded (through the API for example), but it may not be enough to repeat a compilation, as files referenced by the compilation would not yet have been accessed. The repro feature records all of these accesses and contents of such files such that compilation can either be completed or at least to the same point as was reached on the host machine. + +One of the more subtle issues around reproducing a compilation is around filenames. Using the API, a client can specify source files without names, or multiple files with the same name. If files are loaded via `ISlangFileSystem`, they are typically part of a hierarchical file system. This could mean they are referenced relatively. This means there can be distinct files with the same name but differentiated by directory. The files may not easily be reconstructed back into a similar hieararchical file system - as depending on the include paths (or perhaps other mechanisms) the 'files' and their contents could be arranged in a manner very hard to replicate. To work around this the repro feature does not attempt to replicate a hierarchical file system. Instead it gives every file a unique name based on their original name. If there are multiple files with the same name it will 'uniquify' them by appending an index. Doing so means that the contents of the file system can just be held as a flat collection of files. This is not enough to enable repeating the compilation though, as we now need Slang to know which files to reference when they are requested, as they are now no longer part of a hierarchical file system and their names may have been altered. To achieve this the repro functionality stores off a map of all path requests to their contents (or lack there of). Doing so means that the file system still appears to Slang as it did in the original compilation, even with all the files being actually stored using the simpler 'flat' arrangement. + +This means that when a repro is 'extracted' it does so to a directory which holds the files with their unique 'flat' names. The name of the directory is the name of the repro file without it's extension, or if it has no extension, with the postfix '-files'. This directory will be referred to from now on as the `repro directory`. + +When a repro is loaded, before files are loaded from the repro itself, they will first be looked for via their unique names in the `repro directory`. If they are not there the contents of the repro file will be used. If they are there, their contents will be used instead of the contents in the repro. This provides a simple mechanism to be able to alter the source in a repro. The steps more concretely would be... + +1) First extract the repro (say with `-extract-repro`) +2) Go to the `repro directory` and edit files that you wish to change. You can also just delete files that do not need changing, as they will be loaded from the repro. +3) Load the repro - it will now load any files requested from the `repro directory` + +Now you might want to change the compilation options. Using -load-repro it will compile with the options as given. It is not possible to change those options as part of -load-repro. If you want to change the compilation options (and files), you can use -extract-repro, and look at the manifest which will list a command line that will typically repeat the compilation. Now you can just attach the repro as a file system, and set the command line options as appropriate, based on the command line listed in the manifest. Note! If there is a fairly complex directory hierarchy, it may be necessary to specify the input sources paths *as if* they are held on the original files system. You can see how these map in the manifest. + +Note that currently it is disabled to access any new source files - they will be determined as `not found`. This behaviour could be changed such that the regular file system was used, or the ISlangFilesystem set on the API is used as a fallback. + +There currently isn't a mechanism to alter the options of a repro from the command line (other than altering the contents of the source). The reason for this is because of how command lines are processed currently in Slang. A future update could enable specifying a repro and then altering the command line options used. It can be achieved through the API though. Once the repro is loaded via the `spLoadRepro` function, options can be changed as normal. The two major places where option alteration may have surprising behavior are... + +1) Altering the include paths - unless this may break the mechanism used to map paths to files stored in the repro file +2) Altering the ISlangFileSystem. That to make the contents of the file system appear to be that of the repro, slang uses a ISlangFileSystemExt that uses the contents of the repro file and/or the `repro directory`. If you replace the file system this mechanism will no longer work. + +There are currently several API calls for using the repro functionality + +``` +SLANG_API SlangResult spEnableReproCapture( + SlangCompileRequest* request); + +SLANG_API SlangResult spLoadRepro( + SlangCompileRequest* request, + ISlangFileSystem* fileSystem, + const void* data, + size_t size); + +SLANG_API SlangResult spSaveRepro( + SlangCompileRequest* request, + ISlangBlob** outBlob + ); + +SLANG_API SlangResult spExtractRepro( + SlangSession* session, + const void* reproData, + size_t reproDataSize, + ISlangFileSystemExt* fileSystem); + +SLANG_API SlangResult spLoadReproAsFileSystem( + SlangSession* session, + const void* reproData, + size_t reproDataSize, + ISlangFileSystem* replaceFileSystem, + ISlangFileSystemExt** outFileSystem); + +``` + +The fileSystem parameter passed to `spLoadRepro` provides the mechanism for client code to replace the files that are held within the repro. NOTE! That the files will be loaded from this file system with their `unique names` as if they are part of the flat file system. If an attempt to load a file fails, the file within the repro is used. That `spLoadRepro` is typically performed on a new 'unused' SlangCompileRequest. After a call to `spLoadRepro` normal functions to alter the state of the SlangCompileRequest are available. + +The function `spEnableReproCapture` should be set after any ISlangFileSystem has been set (if any), 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 a request will automatically be set up to record everything appropriate and a call to this function isn't strictly required. + +The function `spExtractRepro` allows for extracting the files used in a request (along with the associated manifest). They files and manifest are stored under the 'unique names' in the root of the user provided ISlangFileSystemExt. + +The function `spLoadReproAsFileSystem` creates a file system that can access the contents of the repro with the same paths that were used on the originating system. The ISlangFileSystemExt produced can be set on a request and used for compilation. + +Repro files are currently stored in a binary format. This format is sensitive to changes in the API, as well as internal state within a SlangCompileRequest. This means that the functionality can only be guaranteed to work with exactly the same version of Slang on the same version of compiler. In practice things are typically not so draconian, and future versions will aim to provide a more clear slang repro versioning system, and work will be performed to make more generally usable. + +Finally this version of the repo system does not take into account endianness at all. The system the repro is saved from must have the same endianness as the system loaded on. diff --git a/lib/All/slang/share/doc/slang/scripts/Program.cs b/lib/All/slang/share/doc/slang/scripts/Program.cs new file mode 100644 index 0000000..8a87f15 --- /dev/null +++ b/lib/All/slang/share/doc/slang/scripts/Program.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +namespace toc +{ + public class Builder + { + public static string getAnchorId(string title) + { + StringBuilder sb = new StringBuilder(); + title = title.Trim().ToLower(); + + foreach (var ch in title) + { + if (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' + || ch == '-'|| ch =='_') + sb.Append(ch); + else if (ch == ' ' ) + sb.Append('-'); + } + return sb.ToString(); + } + + public class Node + { + public List fileNamePrefix = new List(); + public string title; + public string shortTitle; + public string fileID; + public List sections = new List(); + public List sectionShortTitles = new List(); + public List children = new List(); + } + + public static void buildTOC(StringBuilder sb, Node n) + { + sb.AppendFormat("
  • {1}\n", n.fileID, n.shortTitle); + if (n.children.Count != 0) + { + sb.AppendLine("
      "); + foreach(var c in n.children) + buildTOC(sb, c); + sb.AppendLine("
    "); + } + else if (n.sections.Count != 0) + { + sb.AppendLine("
      "); + for (int i = 0; i < n.sections.Count; i++) + { + var s = n.sections[i]; + var shortTitle = n.sectionShortTitles[i]; + sb.AppendFormat("
    • {2}
    • \n", n.fileID, getAnchorId(s), shortTitle); + } + sb.AppendLine("
    "); + } + sb.AppendLine("
  • "); + } + public static string buildTOC(Node n) + { + StringBuilder sb = new StringBuilder(); + sb.Append(@"
      "); + buildTOC(sb, n); + sb.Append(@"
    "); + return sb.ToString(); + } + + public static bool isChild(Node parent, Node child) + { + if (parent.fileNamePrefix.Count < child.fileNamePrefix.Count) + { + bool equal = true; + for (int k = 0; k < parent.fileNamePrefix.Count; k++) + { + if (parent.fileNamePrefix[k] != child.fileNamePrefix[k]) + { + equal = false; + break; + } + } + return equal; + } + return false; + } + + public static string getNextNonEmptyLine(string[] lines, int i) + { + i++; + while (i < lines.Length) + { + if (lines[i].Trim().Length != 0) + return lines[i]; + i++; + } + return ""; + } + const string shortTitlePrefix = "[//]: # (ShortTitle: "; + + public static string maybeGetShortTitleImpl(string originalTitle, string[] lines, int line) + { + string nextLine = getNextNonEmptyLine(lines, line); + if (nextLine.StartsWith(shortTitlePrefix)) + { + return nextLine.Substring(shortTitlePrefix.Length, nextLine.Length - shortTitlePrefix.Length - 1).Trim(); + } + return originalTitle; + } + + public static string escapeString(string input) + { + StringBuilder sb = new StringBuilder(); + foreach (var ch in input) + { + if (ch == '<') + sb.Append("<"); + else if (ch == '>') + sb.Append(">"); + else + sb.Append(ch); + } + return sb.ToString(); + } + public static string maybeGetShortTitle(string originalTitle, string[] lines, int line) + { + string title = maybeGetShortTitleImpl(originalTitle, lines, line); + return escapeString(title); + } + public static string Run(string path) + { + StringBuilder outputSB = new StringBuilder(); + outputSB.AppendFormat("Building table of contents from {0}...\n", path); + var files = System.IO.Directory.EnumerateFiles(path, "*.md").OrderBy(f => System.IO.Path.GetFileName(f)); + List nodes = new List(); + foreach (var f in files) + { + var content = File.ReadAllLines(f); + Node node = new Node(); + node.fileID = Path.GetFileNameWithoutExtension(f); + outputSB.AppendFormat(" {0}.md\n", node.fileID); + bool mainTitleFound = false; + for (int i = 1; i < content.Length; i++) + { + if (content[i].StartsWith("===")) + { + mainTitleFound = true; + node.title = content[i-1]; + node.shortTitle = maybeGetShortTitle(node.title, content, i); + } + if (content[i].StartsWith("---")) + { + if (!mainTitleFound) continue; + node.sections.Add(content[i-1]); + node.sectionShortTitles.Add(maybeGetShortTitle(content[i - 1], content, i)); + } + if (content[i].StartsWith("#") && !content[i].StartsWith("##") && node.title == null) + { + mainTitleFound = true; + node.title = content[i].Substring(1, content[i].Length - 1).Trim(); + node.shortTitle = maybeGetShortTitle(node.title, content, i); + } + if (content[i].StartsWith("##") && !content[i].StartsWith("###")) + { + if (!mainTitleFound) continue; + var sectionStr = content[i].Substring(2, content[i].Length - 2).Trim(); + node.sections.Add(sectionStr); + node.sectionShortTitles.Add(maybeGetShortTitle(sectionStr, content, i)); + } + if (content[i].StartsWith("permalink:")) + { + var prefixLength = ("permalink:").Length; + var permaPath = content[i].Substring(prefixLength, content[i].Length - prefixLength).Trim(); + node.fileID = Path.GetFileName(permaPath); + } + } + if (node.title == null) + { + outputSB.AppendFormat("Error: {0} does not define a title.", f); + node.title = "Untitiled"; + } + var titleSecs = Path.GetFileName(f).Split('-'); + foreach (var s in titleSecs) + { + if (s.Length == 2 && s[1]>='0' && s[1] <= '9') + { + node.fileNamePrefix.Add(s); + } + else + { + break; + } + } + // Find parent node. + Node parent=null; + for (int l = nodes.Count-1; l>=0; l--) + { + var n = nodes[l]; + if (isChild(n, node)) + { + parent = n; + break; + } + } + if (parent != null) + parent.children.Add(node); + else + { + // find child + foreach (var other in nodes) + { + if (isChild(node, other)) + { + node.children.Add(other); + } + } + foreach (var c in node.children) + { + nodes.Remove(c); + + } + nodes.Add(node); + } + } + var root = nodes.Find(x=>x.fileID=="index"); + if (root != null) + { + var html = buildTOC(root); + var outPath = Path.Combine(path, "toc.html"); + File.WriteAllText(outPath, html); + outputSB.AppendFormat("Output written to: {0}\n", outPath); + } + return outputSB.ToString(); + } + } +} diff --git a/lib/All/slang/share/doc/slang/scripts/release-note.sh b/lib/All/slang/share/doc/slang/scripts/release-note.sh new file mode 100644 index 0000000..ed910c1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/scripts/release-note.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# This script generates a release note. +# It prints information about breaking-changes first and the rest. +# The content is mostly based on `git log --oneline --since 202X-YY-ZZ`. + +# Usage: the script takes command-line arguments to specify the range of commits to include. +# You can use either: +# 1. Date-based range with --since: docs/scripts/release-note.sh --since 2025-08-06 +# 2. Hash-based range with --previous-hash: docs/scripts/release-note.sh --previous-hash abc123 +# 3. Legacy positional argument (deprecated): docs/scripts/release-note.sh 2024-07-01 + +# This script is supposed to work on all Windows based shell systems including WSL and git-bash. +# If you make any modifications, please test them, because CI doesn't test this script. + +verbose=true +$verbose && echo "Reminder: PLEASE make sure your local repo is up-to-date before running the script." >&2 + +gh="" +for candidate in \ + "$(which gh)" \ + "$(which gh.exe)" \ + "/mnt/c/Program Files/GitHub CLI/gh.exe" \ + "/c/Program Files/GitHub CLI/gh.exe" \ + "/cygdrive/c/Program Files/GitHub CLI/gh.exe"; do + if [ -x "$candidate" ]; then + gh="$candidate" + break + fi +done +if [ "$gh" = "" ] || ! [ -x "$gh" ]; then + echo "File not found: gh or gh.exe" + echo "GitHub CLI can be downloaded from https://cli.github.com" + exit 1 +fi +$verbose && echo "gh is found from: $gh" >&2 + +# Parse command-line arguments +use_hash=false +since="" +previous_hash="" + +while [[ $# -gt 0 ]]; do + case $1 in + --since) + since="$2" + use_hash=false + shift 2 + ;; + --previous-hash) + previous_hash="$2" + use_hash=true + shift 2 + ;; + *) + # Legacy positional argument support + if [ "$since" = "" ] && [ "$previous_hash" = "" ]; then + since="$1" + use_hash=false + else + echo "Too many arguments or mixed argument styles" + exit 1 + fi + shift + ;; + esac +done + +# Validate arguments +if [ "$since" = "" ] && [ "$previous_hash" = "" ]; then + echo "This script requires either --since or --previous-hash option." + echo "Usage: $0 [--since DATE | --previous-hash HASH]" + echo " --since DATE Generate notes since the given date (e.g., 2025-08-06)" + echo " --previous-hash HASH Generate notes since the given commit hash" + echo "" + echo "Legacy usage (deprecated): $0 DATE" + exit 1 +fi + +# Get commits based on the specified range +if [ "$use_hash" = true ]; then + commits="$(git log --oneline "$previous_hash"..HEAD)" +else + commits="$(git log --oneline --since "$since")" +fi +commitsCount="$(echo "$commits" | wc -l)" + +echo "=== Breaking changes ===" +breakingChanges="" +for i in $(seq "$commitsCount"); do + line="$(echo "$commits" | head -n "$i" | tail -1)" + + # Get PR number from the git commit title + pr="$(echo "$line" | grep '#[1-9][0-9][0-9][0-9][0-9]*' | sed 's|.* (\#\([1-9][0-9][0-9][0-9][0-9]*\))|\1|')" + [ "$pr" = "" ] && continue + + # Check if the PR is marked as a breaking change + if "$gh" issue view "$pr" --json labels | grep -q 'pr: breaking change'; then + breakingChanges+="$line"$'\n' + fi +done +if [ "$breakingChanges" = "" ]; then + echo "No breaking changes" +else + echo "$breakingChanges" +fi + +echo "=== All changes for this release ===" +for i in $(seq "$commitsCount"); do + line="$(echo "$commits" | head -n "$i" | tail -1)" + + result="$line" + # Get PR number from the git commit title + pr="$(echo "$line" | grep '#[1-9][0-9][0-9][0-9][0-9]*' | sed 's|.* (\#\([1-9][0-9][0-9][0-9][0-9]*\))|\1|')" + if [ "$pr" != "" ]; then + # Mark breaking changes with "[BREAKING]" + if "$gh" issue view "$pr" --json labels | grep -q 'pr: breaking change'; then + result="[BREAKING] $line" + fi + fi + echo "$result" +done diff --git a/lib/All/slang/share/doc/slang/shader-execution-reordering.md b/lib/All/slang/share/doc/slang/shader-execution-reordering.md new file mode 100644 index 0000000..e983dde --- /dev/null +++ b/lib/All/slang/share/doc/slang/shader-execution-reordering.md @@ -0,0 +1,896 @@ +Shader Execution Reordering (SER) +================================= + +Slang provides support for Shader Execution Reordering (SER) across multiple backends: + +- **D3D12**: Via [NVAPI](nvapi-support.md) or native DXR 1.3 (SM 6.9) +- **Vulkan/SPIR-V**: Via [GL_NV_shader_invocation_reorder](https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_shader_invocation_reorder.txt) (NV) or [GL_EXT_shader_invocation_reorder](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GLSL_EXT_shader_invocation_reorder.txt) (cross-vendor EXT) +- **CUDA**: Via OptiX + +## Platform Notes + +### Vulkan (NV Extension) + +With `GL_NV_shader_invocation_reorder`, `HitObject` variables have special allocation semantics with limitations around flow control and assignment. + +### Vulkan (EXT Extension) + +The cross-vendor `GL_EXT_shader_invocation_reorder` extension provides broader compatibility. Note that `MakeHit` and `MakeMotionHit` are **NV-only** and not available with the EXT extension. + +### D3D12 (DXR 1.3) + +Native DXR 1.3 support (SM 6.9) provides `HitObject` without requiring NVAPI. + +## Links + +* [SER white paper for NVAPI](https://developer.nvidia.com/sites/default/files/akamai/gameworks/ser-whitepaper.pdf) + +# API Reference + +The HitObject API provides cross-platform SER functionality. The API is based on the NvAPI/DXR 1.3 interface. + +## Free Functions + +* [ReorderThread](#reorder-thread) + +## Fused Functions (Vulkan EXT only) + +* [ReorderExecute](#reorder-execute) +* [TraceReorderExecute](#trace-reorder-execute) +* [TraceMotionReorderExecute](#trace-motion-reorder-execute) + +-------------------------------------------------------------------------------- +# `struct HitObject` + +## Description + +Immutable data type representing a ray hit or a miss. Can be used to invoke hit or miss shading, +or as a key in ReorderThread. Created by one of several methods described below. HitObject +and its related functions are available in raytracing shader types only. + +## Methods + +* [TraceRay](#trace-ray) +* [TraceMotionRay](#trace-motion-ray) +* [MakeMiss](#make-miss) +* [MakeHit](#make-hit) +* [MakeMotionHit](#make-motion-hit) +* [MakeMotionMiss](#make-motion-miss) +* [MakeNop](#make-nop) +* [FromRayQuery](#from-ray-query) +* [Invoke](#invoke) +* [IsMiss](#is-miss) +* [IsHit](#is-hit) +* [IsNop](#is-nop) +* [GetRayDesc](#get-ray-desc) +* [GetRayFlags](#get-ray-flags) +* [GetRayTMin](#get-ray-tmin) +* [GetRayTCurrent](#get-ray-tcurrent) +* [GetWorldRayOrigin](#get-world-ray-origin) +* [GetWorldRayDirection](#get-world-ray-direction) +* [GetShaderTableIndex](#get-shader-table-index) +* [SetShaderTableIndex](#set-shader-table-index) +* [GetInstanceIndex](#get-instance-index) +* [GetInstanceID](#get-instance-id) +* [GetGeometryIndex](#get-geometry-index) +* [GetPrimitiveIndex](#get-primitive-index) +* [GetHitKind](#get-hit-kind) +* [GetAttributes](#get-attributes) +* [GetTriangleVertexPositions](#get-triangle-vertex-positions) +* [GetWorldToObject](#get-world-to-object) +* [GetObjectToWorld](#get-object-to-world) +* [GetCurrentTime](#get-current-time) +* [GetObjectRayOrigin](#get-object-ray-origin) +* [GetObjectRayDirection](#get-object-ray-direction) +* [GetShaderRecordBufferHandle](#get-shader-record-buffer-handle) +* [GetClusterID](#get-cluster-id) +* [GetSpherePositionAndRadius](#get-sphere-position-and-radius) +* [GetLssPositionsAndRadii](#get-lss-positions-and-radii) +* [IsSphereHit](#is-sphere-hit) +* [IsLssHit](#is-lss-hit) +* [LoadLocalRootTableConstant](#load-local-root-table-constant) + +-------------------------------------------------------------------------------- + +# `HitObject.TraceRay` + +## Description + +Executes ray traversal (including anyhit and intersection shaders) like TraceRay, but returns the +resulting hit information as a HitObject and does not trigger closesthit or miss shaders. + +## Signature + +``` +static HitObject HitObject.TraceRay( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + inout payload_t Payload); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.TraceMotionRay` + +## Description + +Executes motion ray traversal (including anyhit and intersection shaders) like TraceRay, but returns the +resulting hit information as a HitObject and does not trigger closesthit or miss shaders. + +**Note**: Requires motion blur support. Available on Vulkan (NV/EXT) and CUDA. + +## Signature + +``` +static HitObject HitObject.TraceMotionRay( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime, + inout payload_t Payload); +``` + + +-------------------------------------------------------------------------------- + +# `HitObject.MakeHit` + +## Description + +Creates a HitObject representing a hit based on values explicitly passed as arguments, without +tracing a ray. The primitive specified by AccelerationStructure, InstanceIndex, GeometryIndex, +and PrimitiveIndex must exist. The shader table index is computed using the formula used with +TraceRay. The computed index must reference a valid hit group record in the shader table. The +Attributes parameter must either be an attribute struct, such as +BuiltInTriangleIntersectionAttributes, or another HitObject to copy the attributes from. + +**Note**: This function is **NV-only** and not available with the cross-vendor EXT extension. + +## Signature + +``` +static HitObject HitObject.MakeHit( + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + attr_t attributes); +static HitObject HitObject.MakeHit( + uint HitGroupRecordIndex, + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + attr_t attributes); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.MakeMotionHit` + +## Description + +See MakeHit but handles Motion. + +**Note**: This function is **NV-only** and not available with the cross-vendor EXT extension. + +## Signature + +``` +static HitObject HitObject.MakeMotionHit( + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + RayDesc Ray, + float CurrentTime, + attr_t attributes); +static HitObject HitObject.MakeMotionHit( + uint HitGroupRecordIndex, + RaytracingAccelerationStructure AccelerationStructure, + uint InstanceIndex, + uint GeometryIndex, + uint PrimitiveIndex, + uint HitKind, + RayDesc Ray, + float CurrentTime, + attr_t attributes); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.MakeMiss` + +## Description + +Creates a HitObject representing a miss based on values explicitly passed as arguments, without +tracing a ray. The provided shader table index must reference a valid miss record in the shader +table. + +## Signature + +``` +static HitObject HitObject.MakeMiss( + uint MissShaderIndex, + RayDesc Ray); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.MakeMotionMiss` + +## Description + +See MakeMiss but handles Motion. Available on Vulkan (NV and EXT extensions). + +## Signature + +``` +static HitObject HitObject.MakeMotionMiss( + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.MakeNop` + +## Description + +Creates a HitObject representing “NOP” (no operation) which is neither a hit nor a miss. Invoking a +NOP hit object using HitObject::Invoke has no effect. Reordering by hit objects using +ReorderThread will group NOP hit objects together. This can be useful in some reordering +scenarios where future control flow for some threads is known to process neither a hit nor a +miss. + +## Signature + +``` +static HitObject HitObject.MakeNop(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.FromRayQuery` + +## Description + +Creates a HitObject from a committed RayQuery hit. The RayQuery must have a committed hit +(either triangle or procedural). If the RayQuery has no committed hit, the resulting HitObject +will represent a miss or NOP depending on the query state. + +**Note**: **DXR 1.3 only**. Also available on Vulkan EXT via `hitObjectRecordFromQueryEXT`. + +## Signature + +``` +static HitObject HitObject.FromRayQuery( + RayQuery_t Query); +static HitObject HitObject.FromRayQuery( + RayQuery_t Query, + uint CommittedCustomHitKind, + attr_t CommittedCustomAttribs); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.Invoke` + +## Description + +Invokes closesthit or miss shading for the specified hit object. In case of a NOP HitObject, no +shader is invoked. + +## Signature + +``` +static void HitObject.Invoke( + RaytracingAccelerationStructure AccelerationStructure, + HitObject HitOrMiss, + inout payload_t Payload); + +// DXR 1.3 overload (without AccelerationStructure) +static void HitObject.Invoke( + HitObject HitOrMiss, + inout payload_t Payload); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.IsMiss` + +## Description + +Returns true if the HitObject encodes a miss, otherwise returns false. + +## Signature + +``` +bool HitObject.IsMiss(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.IsHit` + +## Description + +Returns true if the HitObject encodes a hit, otherwise returns false. + +## Signature + +``` +bool HitObject.IsHit(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.IsNop` + +## Description + +Returns true if the HitObject encodes a nop, otherwise returns false. + +## Signature + +``` +bool HitObject.IsNop(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetRayDesc` + +## Description + +Queries ray properties from HitObject. Valid if the hit object represents a hit or a miss. + +## Signature + +``` +RayDesc HitObject.GetRayDesc(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetRayFlags` + +## Description + +Returns the ray flags used when tracing the ray. Valid if the hit object represents a hit or a miss. + +**Note**: **DXR 1.3 and Vulkan EXT**. + +## Signature + +``` +uint HitObject.GetRayFlags(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetRayTMin` + +## Description + +Returns the minimum T value of the ray. Valid if the hit object represents a hit or a miss. + +**Note**: **DXR 1.3 and Vulkan EXT**. + +## Signature + +``` +float HitObject.GetRayTMin(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetRayTCurrent` + +## Description + +Returns the current T value (hit distance) of the ray. Valid if the hit object represents a hit or a miss. + +**Note**: **DXR 1.3 and Vulkan EXT** (called `GetRayTMax` in GLSL/SPIR-V). + +## Signature + +``` +float HitObject.GetRayTCurrent(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetWorldRayOrigin` + +## Description + +Returns the ray origin in world space. Valid if the hit object represents a hit or a miss. + +**Note**: **DXR 1.3 and Vulkan EXT**. + +## Signature + +``` +float3 HitObject.GetWorldRayOrigin(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetWorldRayDirection` + +## Description + +Returns the ray direction in world space. Valid if the hit object represents a hit or a miss. + +**Note**: **DXR 1.3 and Vulkan EXT**. + +## Signature + +``` +float3 HitObject.GetWorldRayDirection(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetShaderTableIndex` + +## Description + +Queries shader table index from HitObject. Valid if the hit object represents a hit or a miss. + +## Signature + +``` +uint HitObject.GetShaderTableIndex(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetInstanceIndex` + +## Description + +Returns the instance index of a hit. Valid if the hit object represents a hit. + +## Signature + +``` +uint HitObject.GetInstanceIndex(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetInstanceID` + +## Description + +Returns the instance ID of a hit. Valid if the hit object represents a hit. + +## Signature + +``` +uint HitObject.GetInstanceID(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetGeometryIndex` + +## Description + +Returns the geometry index of a hit. Valid if the hit object represents a hit. + +## Signature + +``` +uint HitObject.GetGeometryIndex(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetPrimitiveIndex` + +## Description + +Returns the primitive index of a hit. Valid if the hit object represents a hit. + +## Signature + +``` +uint HitObject.GetPrimitiveIndex(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetHitKind` + +## Description + +Returns the hit kind. Valid if the hit object represents a hit. + +## Signature + +``` +uint HitObject.GetHitKind(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetAttributes` + +## Description + +Returns the attributes of a hit. Valid if the hit object represents a hit or a miss. + +## Signature + +``` +attr_t HitObject.GetAttributes(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetTriangleVertexPositions` + +## Description + +Returns the world-space vertex positions of the triangle that was hit. Valid if the hit object represents a triangle hit. + +**Note**: **Vulkan EXT only**. Requires `SPV_KHR_ray_tracing_position_fetch` capability. + +## Signature + +``` +void HitObject.GetTriangleVertexPositions(out float3 positions[3]); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.LoadLocalRootTableConstant` + +## Description + +Loads a root constant from the local root table referenced by the hit object. Valid if the hit object +represents a hit or a miss. RootConstantOffsetInBytes must be a multiple of 4. + +**Note**: **D3D12/HLSL only**. + +## Signature + +``` +uint HitObject.LoadLocalRootTableConstant(uint RootConstantOffsetInBytes); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.SetShaderTableIndex` + +## Description + +Sets the shader table index of the hit object. Used to modify which shader gets invoked during HitObject.Invoke. **EXT extension only** (not available with NV extension). + +## Signature + +``` +void HitObject.SetShaderTableIndex(uint RecordIndex); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetWorldToObject` + +## Description + +Returns the world-to-object transformation matrix. Valid if the hit object represents a hit. + +## Signature + +``` +float4x3 HitObject.GetWorldToObject(); + +// DXR 1.3 layout variants +float3x4 HitObject.GetWorldToObject3x4(); +float4x3 HitObject.GetWorldToObject4x3(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetObjectToWorld` + +## Description + +Returns the object-to-world transformation matrix. Valid if the hit object represents a hit. + +## Signature + +``` +float4x3 HitObject.GetObjectToWorld(); + +// DXR 1.3 layout variants +float3x4 HitObject.GetObjectToWorld3x4(); +float4x3 HitObject.GetObjectToWorld4x3(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetCurrentTime` + +## Description + +Returns the current time for motion blur. Valid if the hit object represents a motion hit or miss. + +**Note**: Requires motion blur support. Available on Vulkan (NV/EXT). + +## Signature + +``` +float HitObject.GetCurrentTime(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetObjectRayOrigin` + +## Description + +Returns the ray origin in object space. Valid if the hit object represents a hit. + +## Signature + +``` +float3 HitObject.GetObjectRayOrigin(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetObjectRayDirection` + +## Description + +Returns the ray direction in object space. Valid if the hit object represents a hit. + +## Signature + +``` +float3 HitObject.GetObjectRayDirection(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetShaderRecordBufferHandle` + +## Description + +Returns the shader record buffer handle. Valid if the hit object represents a hit or a miss. + +## Signature + +``` +uint2 HitObject.GetShaderRecordBufferHandle(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetClusterID` + +## Description + +Returns the cluster ID for cluster acceleration structures. Valid if the hit object represents a hit. + +**Note**: **NV-only** (requires `GL_NV_cluster_acceleration_structure`). + +## Signature + +``` +int HitObject.GetClusterID(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetSpherePositionAndRadius` + +## Description + +Returns the position and radius of a sphere primitive. Valid if the hit object represents a sphere hit. + +**Note**: **NV-only**. + +## Signature + +``` +float4 HitObject.GetSpherePositionAndRadius(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.GetLssPositionsAndRadii` + +## Description + +Returns the positions and radii of a linear swept sphere primitive. Valid if the hit object represents an LSS hit. + +**Note**: **NV-only**. + +## Signature + +``` +float2x4 HitObject.GetLssPositionsAndRadii(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.IsSphereHit` + +## Description + +Returns true if the HitObject represents a hit on a sphere primitive, otherwise returns false. + +**Note**: **NV-only**. + +## Signature + +``` +bool HitObject.IsSphereHit(); +``` + +-------------------------------------------------------------------------------- + +# `HitObject.IsLssHit` + +## Description + +Returns true if the HitObject represents a hit on a linear swept sphere primitive, otherwise returns false. + +**Note**: **NV-only**. + +## Signature + +``` +bool HitObject.IsLssHit(); +``` + +-------------------------------------------------------------------------------- + +# `ReorderThread` + +## Description + +Reorders threads based on a coherence hint value. NumCoherenceHintBits indicates how many of +the least significant bits of CoherenceHint should be considered during reordering (max: 16). +Applications should set this to the lowest value required to represent all possible values in +CoherenceHint. For best performance, all threads should provide the same value for +NumCoherenceHintBits. +Where possible, reordering will also attempt to retain locality in the thread’s launch indices +(DispatchRaysIndex in DXR). + +`ReorderThread(HitOrMiss)` is equivalent to + +``` +void ReorderThread( HitObject HitOrMiss, uint CoherenceHint, uint NumCoherenceHintBitsFromLSB ); +``` + +With CoherenceHint and NumCoherenceHintBitsFromLSB as 0, meaning they are ignored. + +## Signature + +``` +void ReorderThread( + uint CoherenceHint, + uint NumCoherenceHintBitsFromLSB); +void ReorderThread( + HitObject HitOrMiss, + uint CoherenceHint, + uint NumCoherenceHintBitsFromLSB); +void ReorderThread(HitObject HitOrMiss); +``` + +-------------------------------------------------------------------------------- + +# `ReorderExecute` + +## Description + +Fused operation that reorders threads by HitObject and then executes the shader. Equivalent to calling `ReorderThread` followed by `HitObject.Invoke`. + +**Note**: **Vulkan EXT only**. Available via `hitObjectReorderExecuteEXT` in GLSL. + +## Signature + +``` +// GLSL: hitObjectReorderExecuteEXT(hitObject, payload) +void ReorderExecute( + HitObject HitOrMiss, + inout payload_t Payload); + +// GLSL: hitObjectReorderExecuteEXT(hitObject, hint, bits, payload) +void ReorderExecute( + HitObject HitOrMiss, + uint CoherenceHint, + uint NumCoherenceHintBitsFromLSB, + inout payload_t Payload); +``` + +-------------------------------------------------------------------------------- + +# `TraceReorderExecute` + +## Description + +Fused operation that traces a ray, reorders threads by the resulting HitObject, and executes the shader. Equivalent to calling `HitObject.TraceRay`, `ReorderThread`, and `HitObject.Invoke` in sequence. + +**Note**: **Vulkan EXT only**. Available via `hitObjectTraceReorderExecuteEXT` in GLSL. + +## Signature + +``` +// GLSL: hitObjectTraceReorderExecuteEXT(...) +void TraceReorderExecute( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + inout payload_t Payload); + +// With coherence hint +void TraceReorderExecute( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + uint CoherenceHint, + uint NumCoherenceHintBitsFromLSB, + inout payload_t Payload); +``` + +-------------------------------------------------------------------------------- + +# `TraceMotionReorderExecute` + +## Description + +Fused operation for motion blur that traces a motion ray, reorders threads, and executes the shader. + +**Note**: **Vulkan EXT only**. Available via `hitObjectTraceMotionReorderExecuteEXT` in GLSL. Requires motion blur support. + +## Signature + +``` +void TraceMotionReorderExecute( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime, + uint CoherenceHint, + uint NumCoherenceHintBitsFromLSB, + inout payload_t Payload); +``` diff --git a/lib/All/slang/share/doc/slang/shader-playground.md b/lib/All/slang/share/doc/slang/shader-playground.md new file mode 100644 index 0000000..e118795 --- /dev/null +++ b/lib/All/slang/share/doc/slang/shader-playground.md @@ -0,0 +1,25 @@ +Using Slang on Shader Playground +================================ + +A fast and simple way to try out Slang is by using the [Shader Playground](http://shader-playground.timjones.io/) website. This site allows easy and interactive testing of shader code across several compilers including Slang without having to install anything on your local machine. + +Using the Slang compiler is as simple as selecting 'Slang' from the box in the top left corner from the [Shader Playground](http://shader-playground.timjones.io/). This selects the Slang language for input, and the Slang compiler for compilation. The output of the compilation is shown in the right hand panel. + +The default 'Output format' is HLSL. For graphics shaders the 'Output format' can be changed to + +* DXIL +* SPIR-V +* DXBC +* HLSL +* GLSL + +Additionally for compute based shaders it can be set to + +* C++ +* CUDA +* PTX + +For binary formats (such as DXIL/SPIR-V/DXBC) the output will be displayed as the applicable disassembly. + +Note that C++ and CUDA output include a 'prelude'. The prelude remains the same across compilations, with the code generated for the input Slang source placed at the very end of the output. + diff --git a/lib/All/slang/share/doc/slang/stdlib-doc.md b/lib/All/slang/share/doc/slang/stdlib-doc.md new file mode 100644 index 0000000..a3b69cb --- /dev/null +++ b/lib/All/slang/share/doc/slang/stdlib-doc.md @@ -0,0 +1,65429 @@ +-------------------------------------------------------------------------------- +# `__BuiltinArithmeticType.init` + +## Signature + +``` +__BuiltinArithmeticType.init(int value); +``` + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `__BuiltinFloatingPointType.init` + +## Signature + +``` +__BuiltinFloatingPointType.init(float value); +``` + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `__BuiltinFloatingPointType.getPi` + +## Description + +Get the value of the mathematical constant pi in this type. + +## Signature + +``` +__BuiltinFloatingPointType.This __BuiltinFloatingPointType.getPi(); +``` + +-------------------------------------------------------------------------------- +# `struct ConstantBuffer` + +## Generic Parameters + +* `T` + +-------------------------------------------------------------------------------- +# `struct TextureBuffer` + +## Generic Parameters + +* `T` + +-------------------------------------------------------------------------------- +# `struct ParameterBlock` + +## Generic Parameters + +* `T` + +-------------------------------------------------------------------------------- +# `struct SamplerState` + +## Description + +Sampling state for filtered texture fetches. + +-------------------------------------------------------------------------------- +# `struct SamplerComparisonState` + +## Description + +Sampling state for filtered texture fetches that include a comparison operation before filtering. + +-------------------------------------------------------------------------------- +# `struct Texture1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Texture1D.CalculateLevelOfDetail` + +## Signature + +``` +float Texture1D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Texture1D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture1D.GetDimensions` + +## Signature + +``` +void Texture1D.GetDimensions(out uint width); +void Texture1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void Texture1D.GetDimensions(out float width); +void Texture1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture1D.Load` + +## Signature + +``` +/// See Availability 1 +T Texture1D.Load(vector location); +/// See Availability 2 +T Texture1D.Load( + vector location, + vector offset); +/// See Availability 3 +T Texture1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1D.subscript` + +## Signature + +``` +T Texture1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Texture1D.Sample` + +## Signature + +``` +/// See Availability 1 +T Texture1D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T Texture1D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T Texture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T Texture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1D.SampleBias` + +## Signature + +``` +T Texture1D.SampleBias( + SamplerState s, + vector location, + float bias); +T Texture1D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1D.SampleCmp` + +## Signature + +``` +float Texture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Texture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Texture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Texture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Texture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T Texture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Texture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Texture1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Texture1D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T Texture1D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Texture1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location); +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location); +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location); +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location); +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location); +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location); +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location); +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location); +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location); +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location); +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location); +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location); +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location); +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location); +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location); +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location); +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location); +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location); +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location); +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location); +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWTexture1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWTexture1D.CalculateLevelOfDetail` + +## Signature + +``` +float RWTexture1D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWTexture1D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GetDimensions` + +## Signature + +``` +void RWTexture1D.GetDimensions(out uint width); +void RWTexture1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void RWTexture1D.GetDimensions(out float width); +void RWTexture1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture1D.Load(vector location); +/// See Availability 2 +T RWTexture1D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWTexture1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1D.subscript` + +## Signature + +``` +T RWTexture1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWTexture1D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RWTexture1D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RWTexture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RWTexture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1D.SampleBias` + +## Signature + +``` +T RWTexture1D.SampleBias( + SamplerState s, + vector location, + float bias); +T RWTexture1D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1D.SampleCmp` + +## Signature + +``` +float RWTexture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWTexture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWTexture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWTexture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RWTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWTexture1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWTexture1D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RWTexture1D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWTexture1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location); +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location); +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location); +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location); +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location); +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location); +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location); +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location); +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTexture1D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTexture1D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture1D.GetDimensions(out uint width); +void RasterizerOrderedTexture1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void RasterizerOrderedTexture1D.GetDimensions(out float width); +void RasterizerOrderedTexture1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1D.Load(vector location); +T RasterizerOrderedTexture1D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.subscript` + +## Signature + +``` +T RasterizerOrderedTexture1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTexture1D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedTexture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RasterizerOrderedTexture1D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.SampleBias` + +## Signature + +``` +T RasterizerOrderedTexture1D.SampleBias( + SamplerState s, + vector location, + float bias); +T RasterizerOrderedTexture1D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTexture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedTexture1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedTexture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedTexture1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedTexture1D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Texture1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Texture1DMS.GetDimensions` + +## Signature + +``` +void Texture1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void Texture1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void Texture1DMS.GetDimensions( + out float width, + out float sampleCount); +void Texture1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture1DMS.GetSamplePosition` + +## Signature + +``` +vector Texture1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Texture1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Texture1DMS.Load( + vector location, + int sampleIndex); +T Texture1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Texture1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1DMS.subscript` + +## Signature + +``` +T Texture1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWTexture1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWTexture1DMS.GetDimensions` + +## Signature + +``` +void RWTexture1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void RWTexture1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void RWTexture1DMS.GetDimensions( + out float width, + out float sampleCount); +void RWTexture1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture1DMS.GetSamplePosition` + +## Signature + +``` +vector RWTexture1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWTexture1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DMS.Load( + vector location, + int sampleIndex); +T RWTexture1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWTexture1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1DMS.subscript` + +## Signature + +``` +T RWTexture1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void RasterizerOrderedTexture1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTexture1DMS.GetDimensions( + out float width, + out float sampleCount); +void RasterizerOrderedTexture1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTexture1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTexture1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMS.subscript` + +## Signature + +``` +T RasterizerOrderedTexture1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Texture1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Texture1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float Texture1DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Texture1DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GetDimensions` + +## Signature + +``` +void Texture1DArray.GetDimensions( + out uint width, + out uint elements); +void Texture1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void Texture1DArray.GetDimensions( + out float width, + out float elements); +void Texture1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T Texture1DArray.Load(vector location); +T Texture1DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T Texture1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1DArray.subscript` + +## Signature + +``` +T Texture1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T Texture1DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T Texture1DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T Texture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T Texture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1DArray.SampleBias` + +## Signature + +``` +T Texture1DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T Texture1DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1DArray.SampleCmp` + +## Signature + +``` +float Texture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Texture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Texture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Texture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Texture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T Texture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Texture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Texture1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Texture1DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T Texture1DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Texture1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location); +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location); +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location); +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location); +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location); +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location); +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location); +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location); +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location); +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location); +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location); +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location); +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location); +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location); +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location); +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location); +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWTexture1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RWTexture1DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWTexture1DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GetDimensions` + +## Signature + +``` +void RWTexture1DArray.GetDimensions( + out uint width, + out uint elements); +void RWTexture1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void RWTexture1DArray.GetDimensions( + out float width, + out float elements); +void RWTexture1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DArray.Load(vector location); +/// See Availability 2 +T RWTexture1DArray.Load( + vector location, + vector offset); +/// See Availability 3 +T RWTexture1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.subscript` + +## Signature + +``` +T RWTexture1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RWTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RWTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RWTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.SampleBias` + +## Signature + +``` +T RWTexture1DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T RWTexture1DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.SampleCmp` + +## Signature + +``` +float RWTexture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWTexture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWTexture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWTexture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RWTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RWTexture1DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWTexture1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location); +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location); +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location); +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location); +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTexture1DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTexture1DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture1DArray.GetDimensions( + out uint width, + out uint elements); +void RasterizerOrderedTexture1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedTexture1DArray.GetDimensions( + out float width, + out float elements); +void RasterizerOrderedTexture1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DArray.Load(vector location); +T RasterizerOrderedTexture1DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.subscript` + +## Signature + +``` +T RasterizerOrderedTexture1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RasterizerOrderedTexture1DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedTexture1DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T RasterizerOrderedTexture1DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTexture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedTexture1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedTexture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedTexture1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedTexture1DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture1DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Texture1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Texture1DMSArray.GetDimensions` + +## Signature + +``` +void Texture1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void Texture1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void Texture1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void Texture1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture1DMSArray.GetSamplePosition` + +## Signature + +``` +vector Texture1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Texture1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T Texture1DMSArray.Load( + vector location, + int sampleIndex); +T Texture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Texture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture1DMSArray.subscript` + +## Signature + +``` +T Texture1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWTexture1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWTexture1DMSArray.GetDimensions` + +## Signature + +``` +void RWTexture1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void RWTexture1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RWTexture1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void RWTexture1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture1DMSArray.GetSamplePosition` + +## Signature + +``` +vector RWTexture1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWTexture1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture1DMSArray.Load( + vector location, + int sampleIndex); +T RWTexture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWTexture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture1DMSArray.subscript` + +## Signature + +``` +T RWTexture1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void RasterizerOrderedTexture1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTexture1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void RasterizerOrderedTexture1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTexture1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture1DMSArray.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTexture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture1DMSArray.subscript` + +## Signature + +``` +T RasterizerOrderedTexture1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Texture2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Texture2D.CalculateLevelOfDetail` + +## Signature + +``` +float Texture2D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Texture2D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture2D.GetDimensions` + +## Signature + +``` +void Texture2D.GetDimensions( + out uint width, + out uint height); +void Texture2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void Texture2D.GetDimensions( + out float width, + out float height); +void Texture2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture2D.Load` + +## Signature + +``` +/// See Availability 1 +T Texture2D.Load(vector location); +T Texture2D.Load( + vector location, + vector offset); +/// See Availability 2 +T Texture2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2D.subscript` + +## Signature + +``` +T Texture2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Texture2D.Sample` + +## Signature + +``` +/// See Availability 1 +T Texture2D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T Texture2D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T Texture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T Texture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2D.SampleBias` + +## Signature + +``` +T Texture2D.SampleBias( + SamplerState s, + vector location, + float bias); +T Texture2D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2D.SampleCmp` + +## Signature + +``` +float Texture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Texture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Texture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Texture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Texture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T Texture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Texture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Texture2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Texture2D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T Texture2D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Texture2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWTexture2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWTexture2D.CalculateLevelOfDetail` + +## Signature + +``` +float RWTexture2D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWTexture2D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GetDimensions` + +## Signature + +``` +void RWTexture2D.GetDimensions( + out uint width, + out uint height); +void RWTexture2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RWTexture2D.GetDimensions( + out float width, + out float height); +void RWTexture2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture2D.Load(vector location); +/// See Availability 2 +T RWTexture2D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWTexture2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2D.subscript` + +## Signature + +``` +T RWTexture2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWTexture2D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RWTexture2D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RWTexture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RWTexture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2D.SampleBias` + +## Signature + +``` +T RWTexture2D.SampleBias( + SamplerState s, + vector location, + float bias); +T RWTexture2D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2D.SampleCmp` + +## Signature + +``` +float RWTexture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWTexture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWTexture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWTexture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RWTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWTexture2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWTexture2D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RWTexture2D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWTexture2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTexture2D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTexture2D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture2D.GetDimensions( + out uint width, + out uint height); +void RasterizerOrderedTexture2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RasterizerOrderedTexture2D.GetDimensions( + out float width, + out float height); +void RasterizerOrderedTexture2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2D.Load(vector location); +T RasterizerOrderedTexture2D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.subscript` + +## Signature + +``` +T RasterizerOrderedTexture2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTexture2D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedTexture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RasterizerOrderedTexture2D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.SampleBias` + +## Signature + +``` +T RasterizerOrderedTexture2D.SampleBias( + SamplerState s, + vector location, + float bias); +T RasterizerOrderedTexture2D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTexture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedTexture2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedTexture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedTexture2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedTexture2D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Texture2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Texture2DMS.GetDimensions` + +## Signature + +``` +void Texture2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void Texture2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void Texture2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void Texture2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture2DMS.GetSamplePosition` + +## Signature + +``` +vector Texture2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Texture2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Texture2DMS.Load( + vector location, + int sampleIndex); +T Texture2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Texture2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2DMS.subscript` + +## Signature + +``` +T Texture2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWTexture2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWTexture2DMS.GetDimensions` + +## Signature + +``` +void RWTexture2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RWTexture2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RWTexture2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RWTexture2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture2DMS.GetSamplePosition` + +## Signature + +``` +vector RWTexture2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWTexture2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DMS.Load( + vector location, + int sampleIndex); +T RWTexture2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWTexture2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2DMS.subscript` + +## Signature + +``` +T RWTexture2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RasterizerOrderedTexture2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTexture2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RasterizerOrderedTexture2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTexture2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTexture2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMS.subscript` + +## Signature + +``` +T RasterizerOrderedTexture2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Texture2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Texture2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float Texture2DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Texture2DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GetDimensions` + +## Signature + +``` +void Texture2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void Texture2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void Texture2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void Texture2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T Texture2DArray.Load(vector location); +T Texture2DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T Texture2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2DArray.subscript` + +## Signature + +``` +T Texture2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T Texture2DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T Texture2DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T Texture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T Texture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2DArray.SampleBias` + +## Signature + +``` +T Texture2DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T Texture2DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2DArray.SampleCmp` + +## Signature + +``` +float Texture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Texture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Texture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Texture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Texture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T Texture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Texture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Texture2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Texture2DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T Texture2DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Texture2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Texture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWTexture2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RWTexture2DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWTexture2DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GetDimensions` + +## Signature + +``` +void RWTexture2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RWTexture2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RWTexture2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void RWTexture2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DArray.Load(vector location); +/// See Availability 2 +T RWTexture2DArray.Load( + vector location, + vector offset); +/// See Availability 3 +T RWTexture2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.subscript` + +## Signature + +``` +T RWTexture2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RWTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RWTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RWTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.SampleBias` + +## Signature + +``` +T RWTexture2DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T RWTexture2DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.SampleCmp` + +## Signature + +``` +float RWTexture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWTexture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWTexture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWTexture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RWTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RWTexture2DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWTexture2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTexture2DArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTexture2DArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RasterizerOrderedTexture2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedTexture2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void RasterizerOrderedTexture2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DArray.Load(vector location); +T RasterizerOrderedTexture2DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.subscript` + +## Signature + +``` +T RasterizerOrderedTexture2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RasterizerOrderedTexture2DArray.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedTexture2DArray.SampleBias( + SamplerState s, + vector location, + float bias); +T RasterizerOrderedTexture2DArray.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTexture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedTexture2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedTexture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedTexture2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2DArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DArray.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedTexture2DArray.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedTexture2DArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Texture2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Texture2DMSArray.GetDimensions` + +## Signature + +``` +void Texture2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void Texture2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void Texture2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void Texture2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture2DMSArray.GetSamplePosition` + +## Signature + +``` +vector Texture2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Texture2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T Texture2DMSArray.Load( + vector location, + int sampleIndex); +T Texture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Texture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture2DMSArray.subscript` + +## Signature + +``` +T Texture2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWTexture2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWTexture2DMSArray.GetDimensions` + +## Signature + +``` +void RWTexture2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RWTexture2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RWTexture2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RWTexture2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture2DMSArray.GetSamplePosition` + +## Signature + +``` +vector RWTexture2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWTexture2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture2DMSArray.Load( + vector location, + int sampleIndex); +T RWTexture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWTexture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture2DMSArray.subscript` + +## Signature + +``` +T RWTexture2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RasterizerOrderedTexture2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTexture2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RasterizerOrderedTexture2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTexture2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture2DMSArray.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTexture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture2DMSArray.subscript` + +## Signature + +``` +T RasterizerOrderedTexture2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Texture3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Texture3D.CalculateLevelOfDetail` + +## Signature + +``` +float Texture3D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Texture3D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `Texture3D.GetDimensions` + +## Signature + +``` +void Texture3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void Texture3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void Texture3D.GetDimensions( + out float width, + out float height, + out float depth); +void Texture3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture3D.Load` + +## Signature + +``` +/// See Availability 1 +T Texture3D.Load(vector location); +T Texture3D.Load( + vector location, + vector offset); +/// See Availability 2 +T Texture3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture3D.subscript` + +## Signature + +``` +T Texture3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Texture3D.Sample` + +## Signature + +``` +/// See Availability 1 +T Texture3D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T Texture3D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T Texture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T Texture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Texture3D.SampleBias` + +## Signature + +``` +T Texture3D.SampleBias( + SamplerState s, + vector location, + float bias); +T Texture3D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture3D.SampleCmp` + +## Signature + +``` +float Texture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Texture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Texture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Texture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Texture3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Texture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T Texture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Texture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Texture3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Texture3D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T Texture3D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Texture3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location); +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location); +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location); +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location); +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location); +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location); +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location); +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location); +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location); +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location); +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location); +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location); +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location); +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location); +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location); +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Texture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Texture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location); +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location); +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location); +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location); +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Texture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location); +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Texture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWTexture3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWTexture3D.CalculateLevelOfDetail` + +## Signature + +``` +float RWTexture3D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWTexture3D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GetDimensions` + +## Signature + +``` +void RWTexture3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void RWTexture3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void RWTexture3D.GetDimensions( + out float width, + out float height, + out float depth); +void RWTexture3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture3D.Load(vector location); +/// See Availability 2 +T RWTexture3D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWTexture3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture3D.subscript` + +## Signature + +``` +T RWTexture3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWTexture3D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RWTexture3D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RWTexture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RWTexture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture3D.SampleBias` + +## Signature + +``` +T RWTexture3D.SampleBias( + SamplerState s, + vector location, + float bias); +T RWTexture3D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture3D.SampleCmp` + +## Signature + +``` +float RWTexture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWTexture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWTexture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWTexture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWTexture3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RWTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWTexture3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWTexture3D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RWTexture3D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWTexture3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location); +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location); +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location); +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location); +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location); +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location); +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location); +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location); +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTexture3D.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTexture3D.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void RasterizerOrderedTexture3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void RasterizerOrderedTexture3D.GetDimensions( + out float width, + out float height, + out float depth); +void RasterizerOrderedTexture3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture3D.Load(vector location); +T RasterizerOrderedTexture3D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.subscript` + +## Signature + +``` +T RasterizerOrderedTexture3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture3D.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTexture3D.Sample( + SamplerState s, + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedTexture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp); +T RasterizerOrderedTexture3D.Sample( + SamplerState s, + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.SampleBias` + +## Signature + +``` +T RasterizerOrderedTexture3D.SampleBias( + SamplerState s, + vector location, + float bias); +T RasterizerOrderedTexture3D.SampleBias( + SamplerState s, + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTexture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedTexture3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedTexture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedTexture3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture3D.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture3D.SampleLevel( + SamplerState s, + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedTexture3D.SampleLevel( + SamplerState s, + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTexture3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTexture3D.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Texture3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Texture3DMS.GetDimensions` + +## Signature + +``` +void Texture3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void Texture3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void Texture3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void Texture3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Texture3DMS.GetSamplePosition` + +## Signature + +``` +vector Texture3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Texture3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Texture3DMS.Load( + vector location, + int sampleIndex); +T Texture3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Texture3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Texture3DMS.subscript` + +## Signature + +``` +T Texture3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWTexture3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWTexture3DMS.GetDimensions` + +## Signature + +``` +void RWTexture3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void RWTexture3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void RWTexture3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void RWTexture3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWTexture3DMS.GetSamplePosition` + +## Signature + +``` +vector RWTexture3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWTexture3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWTexture3DMS.Load( + vector location, + int sampleIndex); +T RWTexture3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWTexture3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWTexture3DMS.subscript` + +## Signature + +``` +T RWTexture3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTexture3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTexture3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void RasterizerOrderedTexture3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTexture3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void RasterizerOrderedTexture3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTexture3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTexture3DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTexture3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTexture3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTexture3DMS.subscript` + +## Signature + +``` +T RasterizerOrderedTexture3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct TextureCube` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `TextureCube.CalculateLevelOfDetail` + +## Signature + +``` +float TextureCube.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `TextureCube.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float TextureCube.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `TextureCube.GetDimensions` + +## Signature + +``` +void TextureCube.GetDimensions( + out uint width, + out uint height); +void TextureCube.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void TextureCube.GetDimensions( + out float width, + out float height); +void TextureCube.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `TextureCube.Load` + +## Signature + +``` +/// See Availability 1 +T TextureCube.Load(vector location); +T TextureCube.Load( + vector location, + vector offset); +/// See Availability 2 +T TextureCube.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `TextureCube.Sample` + +## Signature + +``` +/// See Availability 1 +T TextureCube.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T TextureCube.Sample( + SamplerState s, + vector location, + float clamp); +T TextureCube.Sample( + SamplerState s, + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `TextureCube.SampleBias` + +## Signature + +``` +T TextureCube.SampleBias( + SamplerState s, + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `TextureCube.SampleCmp` + +## Signature + +``` +float TextureCube.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `TextureCube.SampleCmpLevelZero` + +## Signature + +``` +float TextureCube.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `TextureCube.SampleGrad` + +## Signature + +``` +T TextureCube.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `TextureCube.SampleLevel` + +## Signature + +``` +T TextureCube.SampleLevel( + SamplerState s, + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `s` +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension TextureCube` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location); +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location); +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location); +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location); +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location); +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location); +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location); +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location); +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location); +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location); +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location); +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location); +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location); +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location); +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location); +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location); +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location); +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location); +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location); +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location); +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTextureCube` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTextureCube.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTextureCube.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTextureCube.GetDimensions( + out uint width, + out uint height); +void RasterizerOrderedTextureCube.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RasterizerOrderedTextureCube.GetDimensions( + out float width, + out float height); +void RasterizerOrderedTextureCube.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTextureCube.Load(vector location); +T RasterizerOrderedTextureCube.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedTextureCube.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTextureCube.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTextureCube.Sample( + SamplerState s, + vector location, + float clamp); +T RasterizerOrderedTextureCube.Sample( + SamplerState s, + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.SampleBias` + +## Signature + +``` +T RasterizerOrderedTextureCube.SampleBias( + SamplerState s, + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.SampleCmp` + +## Signature + +``` +float RasterizerOrderedTextureCube.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.SampleCmpLevelZero` + +## Signature + +``` +float RasterizerOrderedTextureCube.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.SampleGrad` + +## Signature + +``` +T RasterizerOrderedTextureCube.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.SampleLevel` + +## Signature + +``` +T RasterizerOrderedTextureCube.SampleLevel( + SamplerState s, + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `s` +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCube` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCube.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct TextureCubeMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` + +-------------------------------------------------------------------------------- +# `TextureCubeMS.GetDimensions` + +## Signature + +``` +void TextureCubeMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void TextureCubeMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void TextureCubeMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void TextureCubeMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `TextureCubeMS.GetSamplePosition` + +## Signature + +``` +vector TextureCubeMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `TextureCubeMS.Load` + +## Signature + +``` +/// See Availability 1 +T TextureCubeMS.Load( + vector location, + int sampleIndex); +T TextureCubeMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T TextureCubeMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTextureCubeMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTextureCubeMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RasterizerOrderedTextureCubeMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTextureCubeMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RasterizerOrderedTextureCubeMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTextureCubeMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTextureCubeMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedTextureCubeMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedTextureCubeMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `struct TextureCubeArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Sample` +* `SampleBias` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.CalculateLevelOfDetail` + +## Signature + +``` +float TextureCubeArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float TextureCubeArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GetDimensions` + +## Signature + +``` +void TextureCubeArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void TextureCubeArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void TextureCubeArray.GetDimensions( + out float width, + out float height, + out float elements); +void TextureCubeArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.Sample` + +## Signature + +``` +/// See Availability 1 +T TextureCubeArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T TextureCubeArray.Sample( + SamplerState s, + vector location, + float clamp); +T TextureCubeArray.Sample( + SamplerState s, + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.SampleBias` + +## Signature + +``` +T TextureCubeArray.SampleBias( + SamplerState s, + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.SampleGrad` + +## Signature + +``` +T TextureCubeArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.SampleLevel` + +## Signature + +``` +T TextureCubeArray.SampleLevel( + SamplerState s, + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `s` +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension TextureCubeArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location); +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location); +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location); +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension TextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location); +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `TextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector TextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTextureCubeArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Sample` +* `SampleBias` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedTextureCubeArray.CalculateLevelOfDetail( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedTextureCubeArray.CalculateLevelOfDetailUnclamped( + SamplerState s, + vector location); +``` + +## Parameters + +* `s` +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTextureCubeArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RasterizerOrderedTextureCubeArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedTextureCubeArray.GetDimensions( + out float width, + out float height, + out float elements); +void RasterizerOrderedTextureCubeArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedTextureCubeArray.Sample( + SamplerState s, + vector location); +/// See Availability 2 +T RasterizerOrderedTextureCubeArray.Sample( + SamplerState s, + vector location, + float clamp); +T RasterizerOrderedTextureCubeArray.Sample( + SamplerState s, + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedTextureCubeArray.SampleBias( + SamplerState s, + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.SampleGrad` + +## Signature + +``` +T RasterizerOrderedTextureCubeArray.SampleGrad( + SamplerState s, + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.SampleLevel` + +## Signature + +``` +T RasterizerOrderedTextureCubeArray.SampleLevel( + SamplerState s, + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `s` +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCubeArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedTextureCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.Gather( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherRed( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherGreen( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherBlue( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location); +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedTextureCubeArray.GatherAlpha( + SamplerState s, + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct TextureCubeMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` + +-------------------------------------------------------------------------------- +# `TextureCubeMSArray.GetDimensions` + +## Signature + +``` +void TextureCubeMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void TextureCubeMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void TextureCubeMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void TextureCubeMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `TextureCubeMSArray.GetSamplePosition` + +## Signature + +``` +vector TextureCubeMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedTextureCubeMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedTextureCubeMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RasterizerOrderedTextureCubeMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedTextureCubeMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RasterizerOrderedTextureCubeMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedTextureCubeMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedTextureCubeMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `struct Sampler1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Sampler1D.CalculateLevelOfDetail` + +## Signature + +``` +float Sampler1D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Sampler1D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1D.GetDimensions` + +## Signature + +``` +void Sampler1D.GetDimensions(out uint width); +void Sampler1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void Sampler1D.GetDimensions(out float width); +void Sampler1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler1D.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler1D.Load(vector location); +/// See Availability 2 +T Sampler1D.Load( + vector location, + vector offset); +/// See Availability 3 +T Sampler1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1D.subscript` + +## Signature + +``` +T Sampler1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1D.Sample` + +## Signature + +``` +/// See Availability 1 +T Sampler1D.Sample(vector location); +/// See Availability 2 +T Sampler1D.Sample( + vector location, + vector offset); +/// See Availability 3 +T Sampler1D.Sample( + vector location, + vector offset, + float clamp); +T Sampler1D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1D.SampleBias` + +## Signature + +``` +T Sampler1D.SampleBias( + vector location, + float bias); +T Sampler1D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1D.SampleCmp` + +## Signature + +``` +float Sampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Sampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Sampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Sampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Sampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T Sampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Sampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Sampler1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Sampler1D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T Sampler1D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Sampler1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.Gather(vector location); +vector Sampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherRed(vector location); +vector Sampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherGreen(vector location); +vector Sampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherBlue(vector location); +vector Sampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherAlpha(vector location); +vector Sampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.Gather(vector location); +vector Sampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherRed(vector location); +vector Sampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherGreen(vector location); +vector Sampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherBlue(vector location); +vector Sampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherAlpha(vector location); +vector Sampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.Gather(vector location); +vector Sampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherRed(vector location); +vector Sampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherGreen(vector location); +vector Sampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherBlue(vector location); +vector Sampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherAlpha(vector location); +vector Sampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.Gather(vector location); +vector Sampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherRed(vector location); +vector Sampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherGreen(vector location); +vector Sampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherBlue(vector location); +vector Sampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1D.GatherAlpha(vector location); +vector Sampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWSampler1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWSampler1D.CalculateLevelOfDetail` + +## Signature + +``` +float RWSampler1D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWSampler1D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GetDimensions` + +## Signature + +``` +void RWSampler1D.GetDimensions(out uint width); +void RWSampler1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void RWSampler1D.GetDimensions(out float width); +void RWSampler1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler1D.Load(vector location); +/// See Availability 2 +T RWSampler1D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWSampler1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1D.subscript` + +## Signature + +``` +T RWSampler1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWSampler1D.Sample(vector location); +/// See Availability 2 +T RWSampler1D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RWSampler1D.Sample( + vector location, + vector offset, + float clamp); +T RWSampler1D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1D.SampleBias` + +## Signature + +``` +T RWSampler1D.SampleBias( + vector location, + float bias); +T RWSampler1D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1D.SampleCmp` + +## Signature + +``` +float RWSampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWSampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWSampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWSampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RWSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWSampler1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWSampler1D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RWSampler1D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWSampler1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.Gather(vector location); +vector RWSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherRed(vector location); +vector RWSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherGreen(vector location); +vector RWSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherBlue(vector location); +vector RWSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherAlpha(vector location); +vector RWSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.Gather(vector location); +vector RWSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherRed(vector location); +vector RWSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherGreen(vector location); +vector RWSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherBlue(vector location); +vector RWSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherAlpha(vector location); +vector RWSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.Gather(vector location); +vector RWSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherRed(vector location); +vector RWSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherGreen(vector location); +vector RWSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherBlue(vector location); +vector RWSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherAlpha(vector location); +vector RWSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.Gather(vector location); +vector RWSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherRed(vector location); +vector RWSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherGreen(vector location); +vector RWSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherBlue(vector location); +vector RWSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1D.GatherAlpha(vector location); +vector RWSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler1D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSampler1D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSampler1D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler1D.GetDimensions(out uint width); +void RasterizerOrderedSampler1D.GetDimensions( + uint mipLevel, + out uint width, + out uint numberOfLevels); +void RasterizerOrderedSampler1D.GetDimensions(out float width); +void RasterizerOrderedSampler1D.GetDimensions( + uint mipLevel, + out float width, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1D.Load(vector location); +T RasterizerOrderedSampler1D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.subscript` + +## Signature + +``` +T RasterizerOrderedSampler1D.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1D.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSampler1D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedSampler1D.Sample( + vector location, + vector offset, + float clamp); +T RasterizerOrderedSampler1D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.SampleBias` + +## Signature + +``` +T RasterizerOrderedSampler1D.SampleBias( + vector location, + float bias); +T RasterizerOrderedSampler1D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedSampler1D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedSampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedSampler1D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedSampler1D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather(vector location); +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed(vector location); +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen(vector location); +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue(vector location); +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha(vector location); +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather(vector location); +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed(vector location); +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen(vector location); +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue(vector location); +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha(vector location); +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather(vector location); +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed(vector location); +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen(vector location); +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue(vector location); +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha(vector location); +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather(vector location); +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed(vector location); +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen(vector location); +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue(vector location); +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha(vector location); +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Sampler1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Sampler1DMS.GetDimensions` + +## Signature + +``` +void Sampler1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void Sampler1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void Sampler1DMS.GetDimensions( + out float width, + out float sampleCount); +void Sampler1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler1DMS.GetSamplePosition` + +## Signature + +``` +vector Sampler1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Sampler1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler1DMS.Load( + vector location, + int sampleIndex); +T Sampler1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Sampler1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1DMS.subscript` + +## Signature + +``` +T Sampler1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWSampler1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWSampler1DMS.GetDimensions` + +## Signature + +``` +void RWSampler1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void RWSampler1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void RWSampler1DMS.GetDimensions( + out float width, + out float sampleCount); +void RWSampler1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler1DMS.GetSamplePosition` + +## Signature + +``` +vector RWSampler1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWSampler1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DMS.Load( + vector location, + int sampleIndex); +T RWSampler1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWSampler1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1DMS.subscript` + +## Signature + +``` +T RWSampler1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler1DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler1DMS.GetDimensions( + out uint width, + out uint sampleCount); +void RasterizerOrderedSampler1DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSampler1DMS.GetDimensions( + out float width, + out float sampleCount); +void RasterizerOrderedSampler1DMS.GetDimensions( + uint mipLevel, + out float width, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSampler1DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSampler1DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMS.subscript` + +## Signature + +``` +T RasterizerOrderedSampler1DMS.subscript(uint location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Sampler1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float Sampler1DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Sampler1DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GetDimensions` + +## Signature + +``` +void Sampler1DArray.GetDimensions( + out uint width, + out uint elements); +void Sampler1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void Sampler1DArray.GetDimensions( + out float width, + out float elements); +void Sampler1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler1DArray.Load(vector location); +T Sampler1DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T Sampler1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.subscript` + +## Signature + +``` +T Sampler1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T Sampler1DArray.Sample(vector location); +/// See Availability 2 +T Sampler1DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T Sampler1DArray.Sample( + vector location, + vector offset, + float clamp); +T Sampler1DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.SampleBias` + +## Signature + +``` +T Sampler1DArray.SampleBias( + vector location, + float bias); +T Sampler1DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.SampleCmp` + +## Signature + +``` +float Sampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Sampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Sampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Sampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Sampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T Sampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Sampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Sampler1DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T Sampler1DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Sampler1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.Gather(vector location); +vector Sampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherRed(vector location); +vector Sampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherGreen(vector location); +vector Sampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherBlue(vector location); +vector Sampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherAlpha(vector location); +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.Gather(vector location); +vector Sampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherRed(vector location); +vector Sampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherGreen(vector location); +vector Sampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherBlue(vector location); +vector Sampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherAlpha(vector location); +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.Gather(vector location); +vector Sampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherRed(vector location); +vector Sampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherGreen(vector location); +vector Sampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherBlue(vector location); +vector Sampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherAlpha(vector location); +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.Gather(vector location); +vector Sampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherRed(vector location); +vector Sampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherGreen(vector location); +vector Sampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherBlue(vector location); +vector Sampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler1DArray.GatherAlpha(vector location); +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWSampler1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RWSampler1DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWSampler1DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GetDimensions` + +## Signature + +``` +void RWSampler1DArray.GetDimensions( + out uint width, + out uint elements); +void RWSampler1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void RWSampler1DArray.GetDimensions( + out float width, + out float elements); +void RWSampler1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DArray.Load(vector location); +/// See Availability 2 +T RWSampler1DArray.Load( + vector location, + vector offset); +/// See Availability 3 +T RWSampler1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.subscript` + +## Signature + +``` +T RWSampler1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DArray.Sample(vector location); +/// See Availability 2 +T RWSampler1DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T RWSampler1DArray.Sample( + vector location, + vector offset, + float clamp); +T RWSampler1DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.SampleBias` + +## Signature + +``` +T RWSampler1DArray.SampleBias( + vector location, + float bias); +T RWSampler1DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.SampleCmp` + +## Signature + +``` +float RWSampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWSampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWSampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWSampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RWSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RWSampler1DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWSampler1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.Gather(vector location); +vector RWSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherRed(vector location); +vector RWSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherGreen(vector location); +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherBlue(vector location); +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha(vector location); +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.Gather(vector location); +vector RWSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherRed(vector location); +vector RWSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherGreen(vector location); +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherBlue(vector location); +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha(vector location); +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.Gather(vector location); +vector RWSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherRed(vector location); +vector RWSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherGreen(vector location); +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherBlue(vector location); +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha(vector location); +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.Gather(vector location); +vector RWSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherRed(vector location); +vector RWSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherGreen(vector location); +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherBlue(vector location); +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha(vector location); +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler1DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSampler1DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSampler1DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler1DArray.GetDimensions( + out uint width, + out uint elements); +void RasterizerOrderedSampler1DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedSampler1DArray.GetDimensions( + out float width, + out float elements); +void RasterizerOrderedSampler1DArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DArray.Load(vector location); +T RasterizerOrderedSampler1DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.subscript` + +## Signature + +``` +T RasterizerOrderedSampler1DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DArray.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSampler1DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedSampler1DArray.Sample( + vector location, + vector offset, + float clamp); +T RasterizerOrderedSampler1DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedSampler1DArray.SampleBias( + vector location, + float bias); +T RasterizerOrderedSampler1DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedSampler1DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedSampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedSampler1DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedSampler1DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather(vector location); +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed(vector location); +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen(vector location); +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue(vector location); +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha(vector location); +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather(vector location); +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed(vector location); +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen(vector location); +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue(vector location); +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha(vector location); +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather(vector location); +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed(vector location); +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen(vector location); +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue(vector location); +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha(vector location); +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler1DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather(vector location); +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed(vector location); +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen(vector location); +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue(vector location); +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha(vector location); +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler1DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Sampler1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Sampler1DMSArray.GetDimensions` + +## Signature + +``` +void Sampler1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void Sampler1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void Sampler1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void Sampler1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler1DMSArray.GetSamplePosition` + +## Signature + +``` +vector Sampler1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Sampler1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler1DMSArray.Load( + vector location, + int sampleIndex); +T Sampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Sampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler1DMSArray.subscript` + +## Signature + +``` +T Sampler1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWSampler1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWSampler1DMSArray.GetDimensions` + +## Signature + +``` +void RWSampler1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void RWSampler1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RWSampler1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void RWSampler1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler1DMSArray.GetSamplePosition` + +## Signature + +``` +vector RWSampler1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWSampler1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler1DMSArray.Load( + vector location, + int sampleIndex); +T RWSampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWSampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler1DMSArray.subscript` + +## Signature + +``` +T RWSampler1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler1DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler1DMSArray.GetDimensions( + out uint width, + out uint elements, + out uint sampleCount); +void RasterizerOrderedSampler1DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSampler1DMSArray.GetDimensions( + out float width, + out float elements, + out float sampleCount); +void RasterizerOrderedSampler1DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSampler1DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler1DMSArray.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler1DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler1DMSArray.subscript` + +## Signature + +``` +T RasterizerOrderedSampler1DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Sampler2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Sampler2D.CalculateLevelOfDetail` + +## Signature + +``` +float Sampler2D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Sampler2D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2D.GetDimensions` + +## Signature + +``` +void Sampler2D.GetDimensions( + out uint width, + out uint height); +void Sampler2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void Sampler2D.GetDimensions( + out float width, + out float height); +void Sampler2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler2D.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler2D.Load(vector location); +T Sampler2D.Load( + vector location, + vector offset); +/// See Availability 2 +T Sampler2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2D.subscript` + +## Signature + +``` +T Sampler2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2D.Sample` + +## Signature + +``` +/// See Availability 1 +T Sampler2D.Sample(vector location); +/// See Availability 2 +T Sampler2D.Sample( + vector location, + vector offset); +/// See Availability 3 +T Sampler2D.Sample( + vector location, + vector offset, + float clamp); +T Sampler2D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2D.SampleBias` + +## Signature + +``` +T Sampler2D.SampleBias( + vector location, + float bias); +T Sampler2D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2D.SampleCmp` + +## Signature + +``` +float Sampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Sampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Sampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Sampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Sampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T Sampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Sampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Sampler2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Sampler2D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T Sampler2D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Sampler2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.Gather(vector location); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherRed(vector location); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.Gather(vector location); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherRed(vector location); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.Gather(vector location); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherRed(vector location); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.Gather(vector location); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherRed(vector location); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWSampler2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWSampler2D.CalculateLevelOfDetail` + +## Signature + +``` +float RWSampler2D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWSampler2D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GetDimensions` + +## Signature + +``` +void RWSampler2D.GetDimensions( + out uint width, + out uint height); +void RWSampler2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RWSampler2D.GetDimensions( + out float width, + out float height); +void RWSampler2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler2D.Load(vector location); +/// See Availability 2 +T RWSampler2D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWSampler2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2D.subscript` + +## Signature + +``` +T RWSampler2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWSampler2D.Sample(vector location); +/// See Availability 2 +T RWSampler2D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RWSampler2D.Sample( + vector location, + vector offset, + float clamp); +T RWSampler2D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2D.SampleBias` + +## Signature + +``` +T RWSampler2D.SampleBias( + vector location, + float bias); +T RWSampler2D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2D.SampleCmp` + +## Signature + +``` +float RWSampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWSampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWSampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWSampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RWSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWSampler2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWSampler2D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RWSampler2D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWSampler2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.Gather(vector location); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.Gather(vector location); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.Gather(vector location); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.Gather(vector location); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler2D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSampler2D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSampler2D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler2D.GetDimensions( + out uint width, + out uint height); +void RasterizerOrderedSampler2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RasterizerOrderedSampler2D.GetDimensions( + out float width, + out float height); +void RasterizerOrderedSampler2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2D.Load(vector location); +T RasterizerOrderedSampler2D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.subscript` + +## Signature + +``` +T RasterizerOrderedSampler2D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2D.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSampler2D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedSampler2D.Sample( + vector location, + vector offset, + float clamp); +T RasterizerOrderedSampler2D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.SampleBias` + +## Signature + +``` +T RasterizerOrderedSampler2D.SampleBias( + vector location, + float bias); +T RasterizerOrderedSampler2D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedSampler2D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedSampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedSampler2D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedSampler2D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2D.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Sampler2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Sampler2DMS.GetDimensions` + +## Signature + +``` +void Sampler2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void Sampler2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void Sampler2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void Sampler2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler2DMS.GetSamplePosition` + +## Signature + +``` +vector Sampler2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Sampler2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler2DMS.Load( + vector location, + int sampleIndex); +T Sampler2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Sampler2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2DMS.subscript` + +## Signature + +``` +T Sampler2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWSampler2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWSampler2DMS.GetDimensions` + +## Signature + +``` +void RWSampler2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RWSampler2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RWSampler2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RWSampler2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler2DMS.GetSamplePosition` + +## Signature + +``` +vector RWSampler2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWSampler2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DMS.Load( + vector location, + int sampleIndex); +T RWSampler2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWSampler2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2DMS.subscript` + +## Signature + +``` +T RWSampler2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler2DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler2DMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RasterizerOrderedSampler2DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSampler2DMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RasterizerOrderedSampler2DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSampler2DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSampler2DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMS.subscript` + +## Signature + +``` +T RasterizerOrderedSampler2DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Sampler2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float Sampler2DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Sampler2DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GetDimensions` + +## Signature + +``` +void Sampler2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void Sampler2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void Sampler2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void Sampler2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler2DArray.Load(vector location); +T Sampler2DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T Sampler2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.subscript` + +## Signature + +``` +T Sampler2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T Sampler2DArray.Sample(vector location); +/// See Availability 2 +T Sampler2DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T Sampler2DArray.Sample( + vector location, + vector offset, + float clamp); +T Sampler2DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.SampleBias` + +## Signature + +``` +T Sampler2DArray.SampleBias( + vector location, + float bias); +T Sampler2DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.SampleCmp` + +## Signature + +``` +float Sampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Sampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Sampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Sampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Sampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T Sampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Sampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Sampler2DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T Sampler2DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Sampler2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.Gather(vector location); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.Gather(vector location); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.Gather(vector location); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.Gather(vector location); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector Sampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWSampler2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RWSampler2DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWSampler2DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GetDimensions` + +## Signature + +``` +void RWSampler2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RWSampler2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RWSampler2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void RWSampler2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DArray.Load(vector location); +/// See Availability 2 +T RWSampler2DArray.Load( + vector location, + vector offset); +/// See Availability 3 +T RWSampler2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.subscript` + +## Signature + +``` +T RWSampler2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DArray.Sample(vector location); +/// See Availability 2 +T RWSampler2DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T RWSampler2DArray.Sample( + vector location, + vector offset, + float clamp); +T RWSampler2DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.SampleBias` + +## Signature + +``` +T RWSampler2DArray.SampleBias( + vector location, + float bias); +T RWSampler2DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.SampleCmp` + +## Signature + +``` +float RWSampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWSampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWSampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWSampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RWSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RWSampler2DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWSampler2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RWSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSampler2DArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSampler2DArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RasterizerOrderedSampler2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedSampler2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void RasterizerOrderedSampler2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DArray.Load(vector location); +T RasterizerOrderedSampler2DArray.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2DArray.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.subscript` + +## Signature + +``` +T RasterizerOrderedSampler2DArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DArray.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSampler2DArray.Sample( + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedSampler2DArray.Sample( + vector location, + vector offset, + float clamp); +T RasterizerOrderedSampler2DArray.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedSampler2DArray.SampleBias( + vector location, + float bias); +T RasterizerOrderedSampler2DArray.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedSampler2DArray.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedSampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedSampler2DArray.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2DArray.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DArray.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedSampler2DArray.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2DArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler2DArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.Gather(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherRed(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherGreen(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherBlue(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler2DArray.GatherAlpha(vector location); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 2 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 3 +vector RasterizerOrderedSampler2DArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Sampler2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Sampler2DMSArray.GetDimensions` + +## Signature + +``` +void Sampler2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void Sampler2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void Sampler2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void Sampler2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler2DMSArray.GetSamplePosition` + +## Signature + +``` +vector Sampler2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Sampler2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler2DMSArray.Load( + vector location, + int sampleIndex); +T Sampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Sampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler2DMSArray.subscript` + +## Signature + +``` +T Sampler2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWSampler2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWSampler2DMSArray.GetDimensions` + +## Signature + +``` +void RWSampler2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RWSampler2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RWSampler2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RWSampler2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler2DMSArray.GetSamplePosition` + +## Signature + +``` +vector RWSampler2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWSampler2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler2DMSArray.Load( + vector location, + int sampleIndex); +T RWSampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWSampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler2DMSArray.subscript` + +## Signature + +``` +T RWSampler2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler2DMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler2DMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RasterizerOrderedSampler2DMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSampler2DMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RasterizerOrderedSampler2DMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSampler2DMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMSArray.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler2DMSArray.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler2DMSArray.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler2DMSArray.subscript` + +## Signature + +``` +T RasterizerOrderedSampler2DMSArray.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct Sampler3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `Sampler3D.CalculateLevelOfDetail` + +## Signature + +``` +float Sampler3D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float Sampler3D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler3D.GetDimensions` + +## Signature + +``` +void Sampler3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void Sampler3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void Sampler3D.GetDimensions( + out float width, + out float height, + out float depth); +void Sampler3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler3D.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler3D.Load(vector location); +T Sampler3D.Load( + vector location, + vector offset); +/// See Availability 2 +T Sampler3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler3D.subscript` + +## Signature + +``` +T Sampler3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `Sampler3D.Sample` + +## Signature + +``` +/// See Availability 1 +T Sampler3D.Sample(vector location); +/// See Availability 2 +T Sampler3D.Sample( + vector location, + vector offset); +/// See Availability 3 +T Sampler3D.Sample( + vector location, + vector offset, + float clamp); +T Sampler3D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler3D.SampleBias` + +## Signature + +``` +T Sampler3D.SampleBias( + vector location, + float bias); +T Sampler3D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler3D.SampleCmp` + +## Signature + +``` +float Sampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float Sampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float Sampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float Sampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `Sampler3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T Sampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T Sampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T Sampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `Sampler3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T Sampler3D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T Sampler3D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension Sampler3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.Gather(vector location); +vector Sampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherRed(vector location); +vector Sampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherGreen(vector location); +vector Sampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherBlue(vector location); +vector Sampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherAlpha(vector location); +vector Sampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.Gather(vector location); +vector Sampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherRed(vector location); +vector Sampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherGreen(vector location); +vector Sampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherBlue(vector location); +vector Sampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherAlpha(vector location); +vector Sampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.Gather(vector location); +vector Sampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherRed(vector location); +vector Sampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherGreen(vector location); +vector Sampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherBlue(vector location); +vector Sampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherAlpha(vector location); +vector Sampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension Sampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `Sampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.Gather(vector location); +vector Sampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherRed(vector location); +vector Sampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherGreen(vector location); +vector Sampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherBlue(vector location); +vector Sampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `Sampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector Sampler3D.GatherAlpha(vector location); +vector Sampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector Sampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RWSampler3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RWSampler3D.CalculateLevelOfDetail` + +## Signature + +``` +float RWSampler3D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RWSampler3D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GetDimensions` + +## Signature + +``` +void RWSampler3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void RWSampler3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void RWSampler3D.GetDimensions( + out float width, + out float height, + out float depth); +void RWSampler3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler3D.Load(vector location); +/// See Availability 2 +T RWSampler3D.Load( + vector location, + vector offset); +/// See Availability 3 +T RWSampler3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** **CUDA** +2. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler3D.subscript` + +## Signature + +``` +T RWSampler3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Sample` + +## Signature + +``` +/// See Availability 1 +T RWSampler3D.Sample(vector location); +/// See Availability 2 +T RWSampler3D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RWSampler3D.Sample( + vector location, + vector offset, + float clamp); +T RWSampler3D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler3D.SampleBias` + +## Signature + +``` +T RWSampler3D.SampleBias( + vector location, + float bias); +T RWSampler3D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler3D.SampleCmp` + +## Signature + +``` +float RWSampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RWSampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RWSampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RWSampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RWSampler3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RWSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RWSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RWSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RWSampler3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RWSampler3D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RWSampler3D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RWSampler3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.Gather(vector location); +vector RWSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherRed(vector location); +vector RWSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherGreen(vector location); +vector RWSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherBlue(vector location); +vector RWSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherAlpha(vector location); +vector RWSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.Gather(vector location); +vector RWSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherRed(vector location); +vector RWSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherGreen(vector location); +vector RWSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherBlue(vector location); +vector RWSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherAlpha(vector location); +vector RWSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.Gather(vector location); +vector RWSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherRed(vector location); +vector RWSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherGreen(vector location); +vector RWSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherBlue(vector location); +vector RWSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherAlpha(vector location); +vector RWSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RWSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RWSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.Gather(vector location); +vector RWSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherRed(vector location); +vector RWSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherGreen(vector location); +vector RWSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherBlue(vector location); +vector RWSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RWSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RWSampler3D.GatherAlpha(vector location); +vector RWSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RWSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler3D` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `subscript` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSampler3D.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSampler3D.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler3D.GetDimensions( + out uint width, + out uint height, + out uint depth); +void RasterizerOrderedSampler3D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint numberOfLevels); +void RasterizerOrderedSampler3D.GetDimensions( + out float width, + out float height, + out float depth); +void RasterizerOrderedSampler3D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler3D.Load(vector location); +T RasterizerOrderedSampler3D.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler3D.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.subscript` + +## Signature + +``` +T RasterizerOrderedSampler3D.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler3D.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSampler3D.Sample( + vector location, + vector offset); +/// See Availability 3 +T RasterizerOrderedSampler3D.Sample( + vector location, + vector offset, + float clamp); +T RasterizerOrderedSampler3D.Sample( + vector location, + vector offset, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `location` +* `offset` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.SampleBias` + +## Signature + +``` +T RasterizerOrderedSampler3D.SampleBias( + vector location, + float bias); +T RasterizerOrderedSampler3D.SampleBias( + vector location, + float bias, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +float RasterizerOrderedSampler3D.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.SampleCmpLevelZero` + +## Signature + +``` +/// See Availability 1 +float RasterizerOrderedSampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +/// See Availability 2 +float RasterizerOrderedSampler3D.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` +* `offset` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.SampleGrad` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY); +T RasterizerOrderedSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler3D.SampleGrad( + vector location, + vector gradX, + vector gradY, + vector offset, + float lodClamp); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **GLSL** `GL_ARB_sparse_texture_clamp` **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` +* `offset` +* `lodClamp` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.SampleLevel` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler3D.SampleLevel( + vector location, + float level); +/// See Availability 2 +T RasterizerOrderedSampler3D.SampleLevel( + vector location, + float level, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `location` +* `level` +* `offset` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler3D` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather(vector location); +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed(vector location); +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen(vector location); +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue(vector location); +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha(vector location); +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather(vector location); +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed(vector location); +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen(vector location); +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue(vector location); +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha(vector location); +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather(vector location); +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed(vector location); +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen(vector location); +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue(vector location); +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha(vector location); +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSampler3D` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather(vector location); +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed(vector location); +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen(vector location); +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue(vector location); +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3D.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha(vector location); +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSampler3D.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct Sampler3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Sampler3DMS.GetDimensions` + +## Signature + +``` +void Sampler3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void Sampler3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void Sampler3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void Sampler3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `Sampler3DMS.GetSamplePosition` + +## Signature + +``` +vector Sampler3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `Sampler3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T Sampler3DMS.Load( + vector location, + int sampleIndex); +T Sampler3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T Sampler3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `Sampler3DMS.subscript` + +## Signature + +``` +T Sampler3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RWSampler3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWSampler3DMS.GetDimensions` + +## Signature + +``` +void RWSampler3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void RWSampler3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void RWSampler3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void RWSampler3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RWSampler3DMS.GetSamplePosition` + +## Signature + +``` +vector RWSampler3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RWSampler3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RWSampler3DMS.Load( + vector location, + int sampleIndex); +T RWSampler3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RWSampler3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RWSampler3DMS.subscript` + +## Signature + +``` +T RWSampler3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSampler3DMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3DMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSampler3DMS.GetDimensions( + out uint width, + out uint height, + out uint depth, + out uint sampleCount); +void RasterizerOrderedSampler3DMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint depth, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSampler3DMS.GetDimensions( + out float width, + out float height, + out float depth, + out float sampleCount); +void RasterizerOrderedSampler3DMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float depth, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `depth` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3DMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSampler3DMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3DMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSampler3DMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSampler3DMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSampler3DMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSampler3DMS.subscript` + +## Signature + +``` +T RasterizerOrderedSampler3DMS.subscript(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `struct SamplerCube` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `SamplerCube.CalculateLevelOfDetail` + +## Signature + +``` +float SamplerCube.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `SamplerCube.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float SamplerCube.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `SamplerCube.GetDimensions` + +## Signature + +``` +void SamplerCube.GetDimensions( + out uint width, + out uint height); +void SamplerCube.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void SamplerCube.GetDimensions( + out float width, + out float height); +void SamplerCube.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `SamplerCube.Load` + +## Signature + +``` +/// See Availability 1 +T SamplerCube.Load(vector location); +T SamplerCube.Load( + vector location, + vector offset); +/// See Availability 2 +T SamplerCube.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `SamplerCube.Sample` + +## Signature + +``` +/// See Availability 1 +T SamplerCube.Sample(vector location); +/// See Availability 2 +T SamplerCube.Sample( + vector location, + float clamp); +T SamplerCube.Sample( + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `SamplerCube.SampleBias` + +## Signature + +``` +T SamplerCube.SampleBias( + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `SamplerCube.SampleCmp` + +## Signature + +``` +float SamplerCube.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `SamplerCube.SampleCmpLevelZero` + +## Signature + +``` +float SamplerCube.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `SamplerCube.SampleGrad` + +## Signature + +``` +T SamplerCube.SampleGrad( + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `SamplerCube.SampleLevel` + +## Signature + +``` +T SamplerCube.SampleLevel( + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension SamplerCube` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.Gather(vector location); +vector SamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherRed(vector location); +vector SamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherGreen(vector location); +vector SamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherBlue(vector location); +vector SamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherAlpha(vector location); +vector SamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.Gather(vector location); +vector SamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherRed(vector location); +vector SamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherGreen(vector location); +vector SamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherBlue(vector location); +vector SamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherAlpha(vector location); +vector SamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.Gather(vector location); +vector SamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherRed(vector location); +vector SamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherGreen(vector location); +vector SamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherBlue(vector location); +vector SamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherAlpha(vector location); +vector SamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.Gather(vector location); +vector SamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherRed(vector location); +vector SamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherGreen(vector location); +vector SamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherBlue(vector location); +vector SamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCube.GatherAlpha(vector location); +vector SamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSamplerCube` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Load` +* `Sample` +* `SampleBias` +* `SampleCmp` +* `SampleCmpLevelZero` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSamplerCube.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSamplerCube.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSamplerCube.GetDimensions( + out uint width, + out uint height); +void RasterizerOrderedSamplerCube.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void RasterizerOrderedSamplerCube.GetDimensions( + out float width, + out float height); +void RasterizerOrderedSamplerCube.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSamplerCube.Load(vector location); +T RasterizerOrderedSamplerCube.Load( + vector location, + vector offset); +/// See Availability 2 +T RasterizerOrderedSamplerCube.Load( + vector location, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSamplerCube.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSamplerCube.Sample( + vector location, + float clamp); +T RasterizerOrderedSamplerCube.Sample( + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.SampleBias` + +## Signature + +``` +T RasterizerOrderedSamplerCube.SampleBias( + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.SampleCmp` + +## Signature + +``` +float RasterizerOrderedSamplerCube.SampleCmp( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.SampleCmpLevelZero` + +## Signature + +``` +float RasterizerOrderedSamplerCube.SampleCmpLevelZero( + SamplerComparisonState s, + vector location, + float compareValue); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `s` +* `location` +* `compareValue` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.SampleGrad` + +## Signature + +``` +T RasterizerOrderedSamplerCube.SampleGrad( + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.SampleLevel` + +## Signature + +``` +T RasterizerOrderedSamplerCube.SampleLevel( + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCube` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather(vector location); +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed(vector location); +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen(vector location); +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue(vector location); +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather(vector location); +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed(vector location); +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen(vector location); +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue(vector location); +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather(vector location); +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed(vector location); +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen(vector location); +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue(vector location); +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCube` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather(vector location); +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed(vector location); +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen(vector location); +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue(vector location); +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCube.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCube.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct SamplerCubeMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` + +-------------------------------------------------------------------------------- +# `SamplerCubeMS.GetDimensions` + +## Signature + +``` +void SamplerCubeMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void SamplerCubeMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void SamplerCubeMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void SamplerCubeMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `SamplerCubeMS.GetSamplePosition` + +## Signature + +``` +vector SamplerCubeMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `SamplerCubeMS.Load` + +## Signature + +``` +/// See Availability 1 +T SamplerCubeMS.Load( + vector location, + int sampleIndex); +T SamplerCubeMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T SamplerCubeMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSamplerCubeMS` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` +* `Load` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeMS.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSamplerCubeMS.GetDimensions( + out uint width, + out uint height, + out uint sampleCount); +void RasterizerOrderedSamplerCubeMS.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSamplerCubeMS.GetDimensions( + out float width, + out float height, + out float sampleCount); +void RasterizerOrderedSamplerCubeMS.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeMS.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSamplerCubeMS.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeMS.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSamplerCubeMS.Load( + vector location, + int sampleIndex); +T RasterizerOrderedSamplerCubeMS.Load( + vector location, + int sampleIndex, + vector offset); +/// See Availability 2 +T RasterizerOrderedSamplerCubeMS.Load( + vector location, + int sampleIndex, + vector offset, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `sampleIndex` +* `offset` +* `status` + +-------------------------------------------------------------------------------- +# `struct SamplerCubeArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Sample` +* `SampleBias` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.CalculateLevelOfDetail` + +## Signature + +``` +float SamplerCubeArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float SamplerCubeArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GetDimensions` + +## Signature + +``` +void SamplerCubeArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void SamplerCubeArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void SamplerCubeArray.GetDimensions( + out float width, + out float height, + out float elements); +void SamplerCubeArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.Sample` + +## Signature + +``` +/// See Availability 1 +T SamplerCubeArray.Sample(vector location); +/// See Availability 2 +T SamplerCubeArray.Sample( + vector location, + float clamp); +T SamplerCubeArray.Sample( + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.SampleBias` + +## Signature + +``` +T SamplerCubeArray.SampleBias( + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.SampleGrad` + +## Signature + +``` +T SamplerCubeArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.SampleLevel` + +## Signature + +``` +T SamplerCubeArray.SampleLevel( + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension SamplerCubeArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.Gather(vector location); +vector SamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherRed(vector location); +vector SamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherGreen(vector location); +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherBlue(vector location); +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha(vector location); +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.Gather(vector location); +vector SamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherRed(vector location); +vector SamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherGreen(vector location); +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherBlue(vector location); +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha(vector location); +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.Gather(vector location); +vector SamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherRed(vector location); +vector SamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherGreen(vector location); +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherBlue(vector location); +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha(vector location); +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension SamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.Gather(vector location); +vector SamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherRed(vector location); +vector SamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherGreen(vector location); +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherBlue(vector location); +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `SamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha(vector location); +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector SamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSamplerCubeArray` + +## Generic Parameters + +* `T` + +## Methods + +* `CalculateLevelOfDetail` +* `CalculateLevelOfDetailUnclamped` +* `GetDimensions` +* `Sample` +* `SampleBias` +* `SampleGrad` +* `SampleLevel` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.CalculateLevelOfDetail` + +## Signature + +``` +float RasterizerOrderedSamplerCubeArray.CalculateLevelOfDetail(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.CalculateLevelOfDetailUnclamped` + +## Signature + +``` +float RasterizerOrderedSamplerCubeArray.CalculateLevelOfDetailUnclamped(vector location); +``` + +## Parameters + +* `location` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSamplerCubeArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void RasterizerOrderedSamplerCubeArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void RasterizerOrderedSamplerCubeArray.GetDimensions( + out float width, + out float height, + out float elements); +void RasterizerOrderedSamplerCubeArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.Sample` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedSamplerCubeArray.Sample(vector location); +/// See Availability 2 +T RasterizerOrderedSamplerCubeArray.Sample( + vector location, + float clamp); +T RasterizerOrderedSamplerCubeArray.Sample( + vector location, + float clamp, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `location` +* `clamp` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.SampleBias` + +## Signature + +``` +T RasterizerOrderedSamplerCubeArray.SampleBias( + vector location, + float bias); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `bias` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.SampleGrad` + +## Signature + +``` +T RasterizerOrderedSamplerCubeArray.SampleGrad( + vector location, + vector gradX, + vector gradY); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `location` +* `gradX` +* `gradY` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.SampleLevel` + +## Signature + +``` +T RasterizerOrderedSamplerCubeArray.SampleLevel( + vector location, + float level); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `location` +* `level` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCubeArray` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather(vector location); +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather(vector location); +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather(vector location); +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `extension RasterizerOrderedSamplerCubeArray` + +## Methods + +* `Gather` +* `GatherRed` +* `GatherGreen` +* `GatherBlue` +* `GatherAlpha` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.Gather` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather(vector location); +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.Gather( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherRed` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherRed( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherGreen` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherGreen( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherBlue` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherBlue( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeArray.GatherAlpha` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha(vector location); +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset, + out uint status); +/// See Availability 1 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4); +/// See Availability 2 +vector RasterizerOrderedSamplerCubeArray.GatherAlpha( + vector location, + vector offset1, + vector offset2, + vector offset3, + vector offset4, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `offset` +* `status` +* `offset1` +* `offset2` +* `offset3` +* `offset4` + +-------------------------------------------------------------------------------- +# `struct SamplerCubeMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` + +-------------------------------------------------------------------------------- +# `SamplerCubeMSArray.GetDimensions` + +## Signature + +``` +void SamplerCubeMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void SamplerCubeMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void SamplerCubeMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void SamplerCubeMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `SamplerCubeMSArray.GetSamplePosition` + +## Signature + +``` +vector SamplerCubeMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedSamplerCubeMSArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `GetSamplePosition` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeMSArray.GetDimensions` + +## Signature + +``` +void RasterizerOrderedSamplerCubeMSArray.GetDimensions( + out uint width, + out uint height, + out uint elements, + out uint sampleCount); +void RasterizerOrderedSamplerCubeMSArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint sampleCount, + out uint numberOfLevels); +void RasterizerOrderedSamplerCubeMSArray.GetDimensions( + out float width, + out float height, + out float elements, + out float sampleCount); +void RasterizerOrderedSamplerCubeMSArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float sampleCount, + out float numberOfLevels); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_EXT_samplerless_texture_functions` **HLSL** + +## Parameters + +* `width` +* `height` +* `elements` +* `sampleCount` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedSamplerCubeMSArray.GetSamplePosition` + +## Signature + +``` +vector RasterizerOrderedSamplerCubeMSArray.GetSamplePosition(int s); +``` + +## Parameters + +* `s` + +-------------------------------------------------------------------------------- +# `bit_cast` + +## Signature + +``` +T bit_cast(U value); +``` + +## Parameters + +* `T` +* `U` +* `value` + +-------------------------------------------------------------------------------- +# `createDynamicObject` + +## Signature + +``` +T createDynamicObject( + uint typeId, + U value); +``` + +## Parameters + +* `T` +* `U` +* `typeId` +* `value` + +-------------------------------------------------------------------------------- +# `reinterpret` + +## Signature + +``` +T reinterpret(U value); +``` + +## Parameters + +* `T` +* `U` +* `value` + +-------------------------------------------------------------------------------- +# `getStringHash` + +## Description + +Given a string returns an integer hash of that string. + +## Signature + +``` +int getStringHash(String string); +``` + +## Parameters + +* `string` + +-------------------------------------------------------------------------------- +# `beginInvocationInterlock` + +## Description + +Mark beginning of "interlocked" operations in a fragment shader. + +## Signature + +``` +void beginInvocationInterlock(); +``` + +## Availability + +**GLSL** `GLSL420`, `GL_ARB_fragment_shader_interlock` **HLSL** + +-------------------------------------------------------------------------------- +# `endInvocationInterlock` + +## Description + +Mark end of "interlocked" operations in a fragment shader. + +## Signature + +``` +void endInvocationInterlock(); +``` + +## Availability + +**GLSL** `GLSL420`, `GL_ARB_fragment_shader_interlock` **HLSL** + +-------------------------------------------------------------------------------- +# enum _AttributeTargets + +## Values + +* _Struct_ +* _Var_ +* _Function_ +-------------------------------------------------------------------------------- +# `struct AppendStructuredBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `Append` +* `GetDimensions` + +-------------------------------------------------------------------------------- +# `AppendStructuredBuffer.Append` + +## Signature + +``` +void AppendStructuredBuffer.Append(T value); +``` + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `AppendStructuredBuffer.GetDimensions` + +## Signature + +``` +void AppendStructuredBuffer.GetDimensions( + out uint numStructs, + out uint stride); +``` + +## Parameters + +* `numStructs` +* `stride` + +-------------------------------------------------------------------------------- +# `struct ByteAddressBuffer` + +## Methods + +* `GetDimensions` +* `Load2` +* `Load3` +* `Load4` + +-------------------------------------------------------------------------------- +# `ByteAddressBuffer.GetDimensions` + +## Signature + +``` +void ByteAddressBuffer.GetDimensions(out uint dim); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `ByteAddressBuffer.Load2` + +## Signature + +``` +/// See Availability 1 +vector ByteAddressBuffer.Load2(int location); +/// See Availability 2 +vector ByteAddressBuffer.Load2( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `ByteAddressBuffer.Load3` + +## Signature + +``` +/// See Availability 1 +vector ByteAddressBuffer.Load3(int location); +/// See Availability 2 +vector ByteAddressBuffer.Load3( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `ByteAddressBuffer.Load4` + +## Signature + +``` +/// See Availability 1 +vector ByteAddressBuffer.Load4(int location); +/// See Availability 2 +vector ByteAddressBuffer.Load4( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `ByteAddressBuffer.Load` + +## Signature + +``` +/// See Availability 1 +uint ByteAddressBuffer.Load(int location); +/// See Availability 2 +uint ByteAddressBuffer.Load( + int location, + out uint status); +T ByteAddressBuffer.Load(int location); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `struct StructuredBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `StructuredBuffer.GetDimensions` + +## Signature + +``` +void StructuredBuffer.GetDimensions( + out uint numStructs, + out uint stride); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `numStructs` +* `stride` + +-------------------------------------------------------------------------------- +# `StructuredBuffer.Load` + +## Signature + +``` +/// See Availability 1 +T StructuredBuffer.Load(int location); +/// See Availability 2 +T StructuredBuffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `StructuredBuffer.subscript` + +## Signature + +``` +T StructuredBuffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct ConsumeStructuredBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `Consume` +* `GetDimensions` + +-------------------------------------------------------------------------------- +# `ConsumeStructuredBuffer.Consume` + +## Signature + +``` +T ConsumeStructuredBuffer.Consume(); +``` + +-------------------------------------------------------------------------------- +# `ConsumeStructuredBuffer.GetDimensions` + +## Signature + +``` +void ConsumeStructuredBuffer.GetDimensions( + out uint numStructs, + out uint stride); +``` + +## Parameters + +* `numStructs` +* `stride` + +-------------------------------------------------------------------------------- +# `struct InputPatch` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `subscript` + +-------------------------------------------------------------------------------- +# `InputPatch.subscript` + +## Signature + +``` +T InputPatch.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct OutputPatch` + +## Generic Parameters + +* `T` +* `N` + +## Methods + +* `subscript` + +-------------------------------------------------------------------------------- +# `OutputPatch.subscript` + +## Signature + +``` +T OutputPatch.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct RWByteAddressBuffer` + +## Methods + +* `GetDimensions` +* `Load2` +* `Load3` +* `Load4` +* `InterlockedAddF32` +* `InterlockedAddI64` +* `InterlockedCompareExchangeU64` +* `InterlockedMaxU64` +* `InterlockedMinU64` +* `InterlockedAndU64` +* `InterlockedOrU64` +* `InterlockedXorU64` +* `InterlockedExchangeU64` +* `InterlockedAdd64` +* `InterlockedCompareExchange64` +* `InterlockedAdd` +* `InterlockedAnd` +* `InterlockedCompareExchange` +* `InterlockedCompareStore` +* `InterlockedExchange` +* `InterlockedMax` +* `InterlockedMin` +* `InterlockedOr` +* `InterlockedXor` +* `Store2` +* `Store3` +* `Store4` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.GetDimensions` + +## Signature + +``` +void RWByteAddressBuffer.GetDimensions(out uint dim); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Load2` + +## Signature + +``` +/// See Availability 1 +vector RWByteAddressBuffer.Load2(int location); +/// See Availability 2 +vector RWByteAddressBuffer.Load2( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Load3` + +## Signature + +``` +/// See Availability 1 +vector RWByteAddressBuffer.Load3(int location); +/// See Availability 2 +vector RWByteAddressBuffer.Load3( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Load4` + +## Signature + +``` +/// See Availability 1 +vector RWByteAddressBuffer.Load4(int location); +/// See Availability 2 +vector RWByteAddressBuffer.Load4( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Load` + +## Signature + +``` +/// See Availability 1 +uint RWByteAddressBuffer.Load(int location); +/// See Availability 2 +uint RWByteAddressBuffer.Load( + int location, + out uint status); +T RWByteAddressBuffer.Load(int location); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAddF32` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedAddF32( + uint byteAddress, + float valueToAdd, + out float originalValue); +void RWByteAddressBuffer.InterlockedAddF32( + uint byteAddress, + float valueToAdd); +``` + +## Availability + +**HLSL** `NVAPI` **CUDA** `SM 2.0` + +## Parameters + +* `byteAddress` +* `valueToAdd` +* `originalValue` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAddI64` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedAddI64( + uint byteAddress, + int64_t valueToAdd, + out int64_t originalValue); +void RWByteAddressBuffer.InterlockedAddI64( + uint byteAddress, + int64_t valueToAdd); +``` + +## Availability + +**HLSL** **CUDA** `SM 6.0` + +## Parameters + +* `byteAddress` +* `valueToAdd` +* `originalValue` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedCompareExchangeU64` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedCompareExchangeU64( + uint byteAddress, + uint64_t compareValue, + uint64_t value, + out uint64_t outOriginalValue); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `byteAddress` +* `compareValue` +* `value` +* `outOriginalValue` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedMaxU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedMaxU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** `SM 3.5` + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedMinU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedMinU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** `SM 3.5` + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAndU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedAndU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedOrU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedOrU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedXorU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedXorU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedExchangeU64` + +## Signature + +``` +uint64_t RWByteAddressBuffer.InterlockedExchangeU64( + uint byteAddress, + uint64_t value); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `byteAddress` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAdd64` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedAdd64( + uint byteAddress, + int64_t valueToAdd, + out int64_t outOriginalValue); +void RWByteAddressBuffer.InterlockedAdd64( + uint byteAddress, + uint64_t valueToAdd, + out uint64_t outOriginalValue); +``` + +## Parameters + +* `byteAddress` +* `valueToAdd` +* `outOriginalValue` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedCompareExchange64` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedCompareExchange64( + uint byteAddress, + int64_t compareValue, + int64_t value, + out int64_t outOriginalValue); +void RWByteAddressBuffer.InterlockedCompareExchange64( + uint byteAddress, + uint64_t compareValue, + uint64_t value, + out uint64_t outOriginalValue); +``` + +## Parameters + +* `byteAddress` +* `compareValue` +* `value` +* `outOriginalValue` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAdd` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedAdd( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedAdd( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedAnd` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedAnd( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedAnd( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedCompareExchange` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedCompareExchange( + uint dest, + uint compare_value, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `compare_value` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedCompareStore` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedCompareStore( + uint dest, + uint compare_value, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `compare_value` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedExchange` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedExchange( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedMax` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedMax( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedMax( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedMin` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedMin( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedMin( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedOr` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedOr( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedOr( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.InterlockedXor` + +## Signature + +``` +void RWByteAddressBuffer.InterlockedXor( + uint dest, + uint value, + out uint original_value); +void RWByteAddressBuffer.InterlockedXor( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Store2` + +## Signature + +``` +void RWByteAddressBuffer.Store2( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Store3` + +## Signature + +``` +void RWByteAddressBuffer.Store3( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Store4` + +## Signature + +``` +void RWByteAddressBuffer.Store4( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RWByteAddressBuffer.Store` + +## Signature + +``` +/// See Availability 1 +void RWByteAddressBuffer.Store( + uint address, + uint value); +/// See Availability 2 +void RWByteAddressBuffer.Store( + int offset, + T value); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `address` +* `value` +* `offset` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedByteAddressBuffer` + +## Methods + +* `GetDimensions` +* `Load2` +* `Load3` +* `Load4` +* `InterlockedAdd` +* `InterlockedAnd` +* `InterlockedCompareExchange` +* `InterlockedCompareStore` +* `InterlockedExchange` +* `InterlockedMax` +* `InterlockedMin` +* `InterlockedOr` +* `InterlockedXor` +* `Store2` +* `Store3` +* `Store4` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.GetDimensions` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.GetDimensions(out uint dim); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Load2` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedByteAddressBuffer.Load2(int location); +/// See Availability 2 +vector RasterizerOrderedByteAddressBuffer.Load2( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Load3` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedByteAddressBuffer.Load3(int location); +/// See Availability 2 +vector RasterizerOrderedByteAddressBuffer.Load3( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Load4` + +## Signature + +``` +/// See Availability 1 +vector RasterizerOrderedByteAddressBuffer.Load4(int location); +/// See Availability 2 +vector RasterizerOrderedByteAddressBuffer.Load4( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Load` + +## Signature + +``` +/// See Availability 1 +uint RasterizerOrderedByteAddressBuffer.Load(int location); +/// See Availability 2 +uint RasterizerOrderedByteAddressBuffer.Load( + int location, + out uint status); +T RasterizerOrderedByteAddressBuffer.Load(int location); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedAdd` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedAdd( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedAdd( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedAnd` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedAnd( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedAnd( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedCompareExchange` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedCompareExchange( + uint dest, + uint compare_value, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `compare_value` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedCompareStore` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedCompareStore( + uint dest, + uint compare_value, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `compare_value` +* `value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedExchange` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedExchange( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedMax` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedMax( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedMax( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedMin` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedMin( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedMin( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedOr` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedOr( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedOr( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.InterlockedXor` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.InterlockedXor( + uint dest, + uint value, + out uint original_value); +void RasterizerOrderedByteAddressBuffer.InterlockedXor( + uint dest, + uint value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Store2` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.Store2( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Store3` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.Store3( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Store4` + +## Signature + +``` +void RasterizerOrderedByteAddressBuffer.Store4( + uint address, + vector value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `address` +* `value` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedByteAddressBuffer.Store` + +## Signature + +``` +/// See Availability 1 +void RasterizerOrderedByteAddressBuffer.Store( + uint address, + uint value); +/// See Availability 2 +void RasterizerOrderedByteAddressBuffer.Store( + int offset, + T value); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `address` +* `value` +* `offset` + +-------------------------------------------------------------------------------- +# `struct RWStructuredBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `DecrementCounter` +* `GetDimensions` +* `IncrementCounter` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWStructuredBuffer.DecrementCounter` + +## Signature + +``` +uint RWStructuredBuffer.DecrementCounter(); +``` + +-------------------------------------------------------------------------------- +# `RWStructuredBuffer.GetDimensions` + +## Signature + +``` +void RWStructuredBuffer.GetDimensions( + out uint numStructs, + out uint stride); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `numStructs` +* `stride` + +-------------------------------------------------------------------------------- +# `RWStructuredBuffer.IncrementCounter` + +## Signature + +``` +uint RWStructuredBuffer.IncrementCounter(); +``` + +-------------------------------------------------------------------------------- +# `RWStructuredBuffer.Load` + +## Signature + +``` +/// See Availability 1 +T RWStructuredBuffer.Load(int location); +/// See Availability 2 +T RWStructuredBuffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWStructuredBuffer.subscript` + +## Signature + +``` +T RWStructuredBuffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedStructuredBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `DecrementCounter` +* `GetDimensions` +* `IncrementCounter` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedStructuredBuffer.DecrementCounter` + +## Signature + +``` +uint RasterizerOrderedStructuredBuffer.DecrementCounter(); +``` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedStructuredBuffer.GetDimensions` + +## Signature + +``` +void RasterizerOrderedStructuredBuffer.GetDimensions( + out uint numStructs, + out uint stride); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `numStructs` +* `stride` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedStructuredBuffer.IncrementCounter` + +## Signature + +``` +uint RasterizerOrderedStructuredBuffer.IncrementCounter(); +``` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedStructuredBuffer.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedStructuredBuffer.Load(int location); +/// See Availability 2 +T RasterizerOrderedStructuredBuffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedStructuredBuffer.subscript` + +## Signature + +``` +T RasterizerOrderedStructuredBuffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct PointStream` + +## Generic Parameters + +* `T` + +## Methods + +* `Append` +* `RestartStrip` + +-------------------------------------------------------------------------------- +# `PointStream.Append` + +## Signature + +``` +void PointStream.Append(T value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `PointStream.RestartStrip` + +## Signature + +``` +void PointStream.RestartStrip(); +``` + +## Availability + +**GLSL** **HLSL** + +-------------------------------------------------------------------------------- +# `struct LineStream` + +## Generic Parameters + +* `T` + +## Methods + +* `Append` +* `RestartStrip` + +-------------------------------------------------------------------------------- +# `LineStream.Append` + +## Signature + +``` +void LineStream.Append(T value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `LineStream.RestartStrip` + +## Signature + +``` +void LineStream.RestartStrip(); +``` + +## Availability + +**GLSL** **HLSL** + +-------------------------------------------------------------------------------- +# `struct TriangleStream` + +## Generic Parameters + +* `T` + +## Methods + +* `Append` +* `RestartStrip` + +-------------------------------------------------------------------------------- +# `TriangleStream.Append` + +## Signature + +``` +void TriangleStream.Append(T value); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `TriangleStream.RestartStrip` + +## Signature + +``` +void TriangleStream.RestartStrip(); +``` + +## Availability + +**GLSL** **HLSL** + +-------------------------------------------------------------------------------- +# `abort` + +## Signature + +``` +void abort(); +``` + +-------------------------------------------------------------------------------- +# `abs` + +## Signature + +``` +/// See Availability 1 +T abs(T x); +/// See Availability 2 +vector abs(vector x); +/// See Availability 3 +matrix abs(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `acos` + +## Signature + +``` +/// See Availability 1 +T acos(T x); +/// See Availability 2 +vector acos(vector x); +/// See Availability 3 +matrix acos(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `all` + +## Signature + +``` +/// See Availability 1 +bool all(T x); +bool all(vector x); +/// See Availability 2 +bool all(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `AllMemoryBarrier` + +## Signature + +``` +void AllMemoryBarrier(); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `AllMemoryBarrierWithGroupSync` + +## Signature + +``` +void AllMemoryBarrierWithGroupSync(); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `any` + +## Signature + +``` +/// See Availability 1 +bool any(T x); +bool any(vector x); +/// See Availability 2 +bool any(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `asdouble` + +## Signature + +``` +double asdouble( + uint lowbits, + uint highbits); +``` + +## Availability + +**GLSL** `GL_ARB_gpu_shader5` **HLSL** **SPIRV** + +## Parameters + +* `lowbits` +* `highbits` + +-------------------------------------------------------------------------------- +# `asfloat` + +## Signature + +``` +/// See Availability 1 +float asfloat(int x); +float asfloat(uint x); +vector asfloat(vector x); +vector asfloat(vector x); +/// See Availability 2 +matrix asfloat(matrix x); +matrix asfloat(matrix x); +float asfloat(float x); +vector asfloat(vector x); +matrix asfloat(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `asin` + +## Signature + +``` +/// See Availability 1 +T asin(T x); +/// See Availability 2 +vector asin(vector x); +/// See Availability 3 +matrix asin(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `asint` + +## Signature + +``` +/// See Availability 1 +int asint(float x); +int asint(uint x); +vector asint(vector x); +vector asint(vector x); +/// See Availability 2 +matrix asint(matrix x); +matrix asint(matrix x); +int asint(int x); +vector asint(vector x); +matrix asint(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `asuint` + +## Signature + +``` +/// See Availability 1 +void asuint( + double value, + out uint lowbits, + out uint highbits); +/// See Availability 2 +uint asuint(float x); +uint asuint(int x); +vector asuint(vector x); +vector asuint(vector x); +/// See Availability 3 +matrix asuint(matrix x); +matrix asuint(matrix x); +uint asuint(uint x); +vector asuint(vector x); +matrix asuint(matrix x); +``` + +## Availability + +1. **GLSL** `GL_ARB_gpu_shader5` **HLSL** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `N` +* `M` +* `value` +* `lowbits` +* `highbits` +* `x` + +-------------------------------------------------------------------------------- +# `asuint16` + +## Signature + +``` +/// See Availability 1 +uint16_t asuint16(uint16_t value); +vector asuint16(vector value); +matrix asuint16(matrix value); +uint16_t asuint16(int16_t value); +vector asuint16(vector value); +matrix asuint16(matrix value); +/// See Availability 2 +uint16_t asuint16(half value); +/// See Availability 1 +vector asuint16(vector value); +matrix asuint16(matrix value); +``` + +## Availability + +1. **HLSL** +2. **GLSL** **HLSL** **CUDA** + +## Parameters + +* `N` +* `R` +* `C` +* `value` + +-------------------------------------------------------------------------------- +# `asint16` + +## Signature + +``` +/// See Availability 1 +int16_t asint16(int16_t value); +vector asint16(vector value); +matrix asint16(matrix value); +int16_t asint16(uint16_t value); +vector asint16(vector value); +matrix asint16(matrix value); +/// See Availability 2 +int16_t asint16(half value); +/// See Availability 1 +vector asint16(vector value); +matrix asint16(matrix value); +``` + +## Availability + +1. **HLSL** +2. **HLSL** **CUDA** + +## Parameters + +* `N` +* `R` +* `C` +* `value` + +-------------------------------------------------------------------------------- +# `asfloat16` + +## Signature + +``` +/// See Availability 1 +half asfloat16(half value); +vector asfloat16(vector value); +matrix asfloat16(matrix value); +/// See Availability 2 +half asfloat16(uint16_t value); +/// See Availability 1 +vector asfloat16(vector value); +matrix asfloat16(matrix value); +/// See Availability 3 +half asfloat16(int16_t value); +/// See Availability 1 +vector asfloat16(vector value); +matrix asfloat16(matrix value); +``` + +## Availability + +1. **HLSL** +2. **GLSL** **HLSL** **CUDA** +3. **HLSL** **CUDA** + +## Parameters + +* `N` +* `R` +* `C` +* `value` + +-------------------------------------------------------------------------------- +# `atan` + +## Signature + +``` +/// See Availability 1 +T atan(T x); +/// See Availability 2 +vector atan(vector x); +/// See Availability 3 +matrix atan(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `atan2` + +## Signature + +``` +/// See Availability 1 +T atan2( + T y, + T x); +/// See Availability 2 +vector atan2( + vector y, + vector x); +/// See Availability 3 +matrix atan2( + matrix y, + matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `y` +* `x` + +-------------------------------------------------------------------------------- +# `ceil` + +## Signature + +``` +/// See Availability 1 +T ceil(T x); +/// See Availability 2 +vector ceil(vector x); +/// See Availability 3 +matrix ceil(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `CheckAccessFullyMapped` + +## Signature + +``` +bool CheckAccessFullyMapped(uint status); +``` + +## Parameters + +* `status` + +-------------------------------------------------------------------------------- +# `clamp` + +## Signature + +``` +/// See Availability 1 +T clamp( + T x, + T minBound, + T maxBound); +vector clamp( + vector x, + vector minBound, + vector maxBound); +/// See Availability 2 +matrix clamp( + matrix x, + matrix minBound, + matrix maxBound); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `minBound` +* `maxBound` + +-------------------------------------------------------------------------------- +# `clip` + +## Signature + +``` +void clip(T x); +void clip(vector x); +void clip(matrix x); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `cos` + +## Signature + +``` +/// See Availability 1 +T cos(T x); +/// See Availability 2 +vector cos(vector x); +/// See Availability 3 +matrix cos(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `cosh` + +## Signature + +``` +/// See Availability 1 +T cosh(T x); +/// See Availability 2 +vector cosh(vector x); +/// See Availability 3 +matrix cosh(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `countbits` + +## Signature + +``` +uint countbits(uint value); +``` + +## Availability + +**GLSL** **HLSL** **CPP** **CUDA** + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `cross` + +## Signature + +``` +vector cross( + vector left, + vector right); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `left` +* `right` + +-------------------------------------------------------------------------------- +# `D3DCOLORtoUBYTE4` + +## Signature + +``` +vector D3DCOLORtoUBYTE4(vector color); +``` + +## Parameters + +* `color` + +-------------------------------------------------------------------------------- +# `ddx` + +## Signature + +``` +/// See Availability 1 +T ddx(T x); +vector ddx(vector x); +/// See Availability 2 +matrix ddx(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ddx_coarse` + +## Signature + +``` +/// See Availability 1 +T ddx_coarse(T x); +vector ddx_coarse(vector x); +/// See Availability 2 +matrix ddx_coarse(matrix x); +``` + +## Availability + +1. **GLSL** `GL_ARB_derivative_control` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ddx_fine` + +## Signature + +``` +/// See Availability 1 +T ddx_fine(T x); +vector ddx_fine(vector x); +/// See Availability 2 +matrix ddx_fine(matrix x); +``` + +## Availability + +1. **GLSL** `GL_ARB_derivative_control` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ddy` + +## Signature + +``` +/// See Availability 1 +T ddy(T x); +vector ddy(vector x); +/// See Availability 2 +matrix ddy(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ddy_coarse` + +## Signature + +``` +/// See Availability 1 +T ddy_coarse(T x); +vector ddy_coarse(vector x); +/// See Availability 2 +matrix ddy_coarse(matrix x); +``` + +## Availability + +1. **GLSL** `GL_ARB_derivative_control` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ddy_fine` + +## Signature + +``` +/// See Availability 1 +T ddy_fine(T x); +vector ddy_fine(vector x); +/// See Availability 2 +matrix ddy_fine(matrix x); +``` + +## Availability + +1. **GLSL** `GL_ARB_derivative_control` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `degrees` + +## Signature + +``` +/// See Availability 1 +T degrees(T x); +vector degrees(vector x); +/// See Availability 2 +matrix degrees(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `determinant` + +## Signature + +``` +T determinant(matrix m); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `m` + +-------------------------------------------------------------------------------- +# `DeviceMemoryBarrier` + +## Signature + +``` +void DeviceMemoryBarrier(); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `DeviceMemoryBarrierWithGroupSync` + +## Signature + +``` +void DeviceMemoryBarrierWithGroupSync(); +``` + +## Availability + +**GLSL** **HLSL** + +-------------------------------------------------------------------------------- +# `distance` + +## Signature + +``` +T distance( + vector x, + vector y); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `dot` + +## Signature + +``` +T dot( + vector x, + vector y); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `dst` + +## Signature + +``` +vector dst( + vector x, + vector y); +``` + +## Parameters + +* `T` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `EvaluateAttributeAtCentroid` + +## Signature + +``` +/// See Availability 1 +T EvaluateAttributeAtCentroid(T x); +vector EvaluateAttributeAtCentroid(vector x); +/// See Availability 2 +matrix EvaluateAttributeAtCentroid(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `EvaluateAttributeAtSample` + +## Signature + +``` +/// See Availability 1 +T EvaluateAttributeAtSample( + T x, + uint sampleindex); +vector EvaluateAttributeAtSample( + vector x, + uint sampleindex); +/// See Availability 2 +matrix EvaluateAttributeAtSample( + matrix x, + uint sampleindex); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `sampleindex` + +-------------------------------------------------------------------------------- +# `EvaluateAttributeSnapped` + +## Signature + +``` +/// See Availability 1 +T EvaluateAttributeSnapped( + T x, + vector offset); +vector EvaluateAttributeSnapped( + vector x, + vector offset); +/// See Availability 2 +matrix EvaluateAttributeSnapped( + matrix x, + vector offset); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `offset` + +-------------------------------------------------------------------------------- +# `exp` + +## Signature + +``` +/// See Availability 1 +T exp(T x); +/// See Availability 2 +vector exp(vector x); +/// See Availability 3 +matrix exp(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `exp2` + +## Signature + +``` +/// See Availability 1 +T exp2(T x); +/// See Availability 2 +vector exp2(vector x); +/// See Availability 3 +matrix exp2(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `f32tof16` + +## Signature + +``` +/// See Availability 1 +uint f32tof16(float value); +/// See Availability 2 +vector f32tof16(vector value); +``` + +## Availability + +1. **GLSL** `GLSL420` **HLSL** +2. **HLSL** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `f16tof32` + +## Signature + +``` +/// See Availability 1 +float f16tof32(uint value); +/// See Availability 2 +vector f16tof32(vector value); +/// See Availability 3 +float f16tof32(half value); +/// See Availability 4 +vector f16tof32(vector value); +``` + +## Availability + +1. **GLSL** `GLSL420` **HLSL** +2. **HLSL** +3. **GLSL** `GLSL420` **HLSL** **CUDA** +4. **HLSL** **CUDA** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `f32tof16_` + +## Signature + +``` +/// See Availability 1 +half f32tof16_(float value); +/// See Availability 2 +vector f32tof16_(vector value); +``` + +## Availability + +1. **GLSL** `GLSL420` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `faceforward` + +## Signature + +``` +vector faceforward( + vector n, + vector i, + vector ng); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `n` +* `i` +* `ng` + +-------------------------------------------------------------------------------- +# `firstbithigh` + +## Signature + +``` +/// See Availability 1 +int firstbithigh(int value); +/// See Availability 2 +vector firstbithigh(vector value); +/// See Availability 1 +uint firstbithigh(uint value); +/// See Availability 2 +vector firstbithigh(vector value); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `firstbitlow` + +## Signature + +``` +/// See Availability 1 +int firstbitlow(int value); +/// See Availability 2 +vector firstbitlow(vector value); +/// See Availability 1 +uint firstbitlow(uint value); +/// See Availability 2 +vector firstbitlow(vector value); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `floor` + +## Signature + +``` +/// See Availability 1 +T floor(T x); +/// See Availability 2 +vector floor(vector x); +/// See Availability 3 +matrix floor(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `fma` + +## Signature + +``` +/// See Availability 1 +double fma( + double a, + double b, + double c); +/// See Availability 2 +vector fma( + vector a, + vector b, + vector c); +/// See Availability 3 +matrix fma( + matrix a, + matrix b, + matrix c); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `N` +* `M` +* `a` +* `b` +* `c` + +-------------------------------------------------------------------------------- +# `fmod` + +## Signature + +``` +/// See Availability 1 +T fmod( + T x, + T y); +/// See Availability 2 +vector fmod( + vector x, + vector y); +matrix fmod( + matrix x, + matrix y); +``` + +## Availability + +1. **HLSL** **CPP** **CUDA** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `frac` + +## Signature + +``` +/// See Availability 1 +T frac(T x); +/// See Availability 2 +vector frac(vector x); +/// See Availability 3 +matrix frac(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `frexp` + +## Signature + +``` +/// See Availability 1 +T frexp( + T x, + out int exp); +vector frexp( + vector x, + out vector exp); +/// See Availability 2 +matrix frexp( + matrix x, + out matrix exp); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `exp` + +-------------------------------------------------------------------------------- +# `fwidth` + +## Signature + +``` +/// See Availability 1 +T fwidth(T x); +/// See Availability 2 +vector fwidth(vector x); +/// See Availability 1 +matrix fwidth(matrix x); +``` + +## Availability + +1. **HLSL** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `GetAttributeAtVertex` + +## Description + + Get the value of a vertex attribute at a specific vertex. + + The `GetAttributeAtVertex()` function can be used in a fragment shader + to get the value of the given `attribute` at the vertex of the primitive + that corresponds to the given `vertexIndex`. + + Note that the `attribute` must have been a declared varying input to + the fragment shader with the `nointerpolation` modifier. + + This function can be applied to scalars, vectors, and matrices of + built-in scalar types. + + Note: these functions are not currently implemented for Vulkan/SPIR-V output. + +## Signature + +``` +T GetAttributeAtVertex( + T attribute, + uint vertexIndex); +vector GetAttributeAtVertex( + vector attribute, + uint vertexIndex); +matrix GetAttributeAtVertex( + matrix attribute, + uint vertexIndex); +``` + +## Availability + +**GLSL** `GLSL450`, `GL_NV_fragment_shader_barycentric` **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `attribute` +* `vertexIndex` + +-------------------------------------------------------------------------------- +# `GetRenderTargetSampleCount` + +## Signature + +``` +uint GetRenderTargetSampleCount(); +``` + +-------------------------------------------------------------------------------- +# `GetRenderTargetSamplePosition` + +## Signature + +``` +vector GetRenderTargetSamplePosition(int Index); +``` + +## Parameters + +* `Index` + +-------------------------------------------------------------------------------- +# `GroupMemoryBarrier` + +## Signature + +``` +void GroupMemoryBarrier(); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `GroupMemoryBarrierWithGroupSync` + +## Signature + +``` +void GroupMemoryBarrierWithGroupSync(); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `InterlockedAdd` + +## Signature + +``` +void InterlockedAdd( + int dest, + int value); +void InterlockedAdd( + uint dest, + uint value); +void InterlockedAdd( + int dest, + int value, + out int original_value); +void InterlockedAdd( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedAnd` + +## Signature + +``` +void InterlockedAnd( + int dest, + int value); +void InterlockedAnd( + uint dest, + uint value); +void InterlockedAnd( + int dest, + int value, + out int original_value); +void InterlockedAnd( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedCompareExchange` + +## Signature + +``` +void InterlockedCompareExchange( + int dest, + int compare_value, + int value, + out int original_value); +void InterlockedCompareExchange( + uint dest, + uint compare_value, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `compare_value` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedCompareStore` + +## Signature + +``` +void InterlockedCompareStore( + int dest, + int compare_value, + int value); +void InterlockedCompareStore( + uint dest, + uint compare_value, + uint value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `compare_value` +* `value` + +-------------------------------------------------------------------------------- +# `InterlockedExchange` + +## Signature + +``` +void InterlockedExchange( + int dest, + int value, + out int original_value); +void InterlockedExchange( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedMax` + +## Signature + +``` +void InterlockedMax( + int dest, + int value); +void InterlockedMax( + uint dest, + uint value); +void InterlockedMax( + int dest, + int value, + out int original_value); +void InterlockedMax( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedMin` + +## Signature + +``` +void InterlockedMin( + int dest, + int value); +void InterlockedMin( + uint dest, + uint value); +void InterlockedMin( + int dest, + int value, + out int original_value); +void InterlockedMin( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedOr` + +## Signature + +``` +void InterlockedOr( + int dest, + int value); +void InterlockedOr( + uint dest, + uint value); +void InterlockedOr( + int dest, + int value, + out int original_value); +void InterlockedOr( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `InterlockedXor` + +## Signature + +``` +void InterlockedXor( + int dest, + int value); +void InterlockedXor( + uint dest, + uint value); +void InterlockedXor( + int dest, + int value, + out int original_value); +void InterlockedXor( + uint dest, + uint value, + out uint original_value); +``` + +## Availability + +**GLSL** **HLSL** **CUDA** + +## Parameters + +* `dest` +* `value` +* `original_value` + +-------------------------------------------------------------------------------- +# `isfinite` + +## Signature + +``` +/// See Availability 1 +bool isfinite(T x); +/// See Availability 2 +vector isfinite(vector x); +matrix isfinite(matrix x); +``` + +## Availability + +1. **HLSL** **CPP** **CUDA** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `isinf` + +## Signature + +``` +/// See Availability 1 +bool isinf(T x); +/// See Availability 2 +vector isinf(vector x); +/// See Availability 3 +matrix isinf(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **CPP** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `isnan` + +## Signature + +``` +/// See Availability 1 +bool isnan(T x); +/// See Availability 2 +vector isnan(vector x); +/// See Availability 3 +matrix isnan(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **CPP** **CUDA** +2. **GLSL** **HLSL** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `ldexp` + +## Signature + +``` +/// See Availability 1 +T ldexp( + T x, + T exp); +vector ldexp( + vector x, + vector exp); +/// See Availability 2 +matrix ldexp( + matrix x, + matrix exp); +``` + +## Availability + +1. **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `exp` + +-------------------------------------------------------------------------------- +# `length` + +## Signature + +``` +T length(vector x); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `x` + +-------------------------------------------------------------------------------- +# `lerp` + +## Signature + +``` +/// See Availability 1 +T lerp( + T x, + T y, + T s); +vector lerp( + vector x, + vector y, + vector s); +/// See Availability 2 +matrix lerp( + matrix x, + matrix y, + matrix s); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `y` +* `s` + +-------------------------------------------------------------------------------- +# `lit` + +## Signature + +``` +vector lit( + float n_dot_l, + float n_dot_h, + float m); +``` + +## Parameters + +* `n_dot_l` +* `n_dot_h` +* `m` + +-------------------------------------------------------------------------------- +# `log` + +## Signature + +``` +/// See Availability 1 +T log(T x); +/// See Availability 2 +vector log(vector x); +/// See Availability 3 +matrix log(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `log10` + +## Signature + +``` +/// See Availability 1 +T log10(T x); +/// See Availability 2 +vector log10(vector x); +/// See Availability 3 +matrix log10(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `log2` + +## Signature + +``` +/// See Availability 1 +T log2(T x); +/// See Availability 2 +vector log2(vector x); +/// See Availability 3 +matrix log2(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `mad` + +## Signature + +``` +/// See Availability 1 +T mad( + T mvalue, + T avalue, + T bvalue); +/// See Availability 2 +vector mad( + vector mvalue, + vector avalue, + vector bvalue); +/// See Availability 3 +matrix mad( + matrix mvalue, + matrix avalue, + matrix bvalue); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `mvalue` +* `avalue` +* `bvalue` + +-------------------------------------------------------------------------------- +# `max` + +## Signature + +``` +/// See Availability 1 +T max( + T x, + T y); +/// See Availability 2 +vector max( + vector x, + vector y); +/// See Availability 3 +matrix max( + matrix x, + matrix y); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `min` + +## Signature + +``` +/// See Availability 1 +T min( + T x, + T y); +/// See Availability 2 +vector min( + vector x, + vector y); +/// See Availability 3 +matrix min( + matrix x, + matrix y); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `modf` + +## Signature + +``` +/// See Availability 1 +T modf( + T x, + out T ip); +/// See Availability 2 +vector modf( + vector x, + out vector ip); +/// See Availability 1 +matrix modf( + matrix x, + out matrix ip); +``` + +## Availability + +1. **HLSL** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `ip` + +-------------------------------------------------------------------------------- +# `msad4` + +## Signature + +``` +vector msad4( + uint reference, + vector source, + vector accum); +``` + +## Parameters + +* `reference` +* `source` +* `accum` + +-------------------------------------------------------------------------------- +# `mul` + +## Signature + +``` +/// See Availability 1 +T mul( + T x, + T y); +vector mul( + vector x, + T y); +vector mul( + T x, + vector y); +matrix mul( + matrix x, + T y); +matrix mul( + T x, + matrix y); +/// See Availability 2 +T mul( + vector x, + vector y); +vector mul( + vector left, + matrix right); +vector mul( + matrix left, + vector right); +matrix mul( + matrix right, + matrix left); +``` + +## Availability + +1. **HLSL** +2. **GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `R` +* `C` +* `x` +* `y` +* `left` +* `right` + +-------------------------------------------------------------------------------- +# `noise` + +## Signature + +``` +float noise(float x); +float noise(vector x); +``` + +## Parameters + +* `N` +* `x` + +-------------------------------------------------------------------------------- +# `NonUniformResourceIndex` + +## Signature + +``` +uint NonUniformResourceIndex(uint index); +int NonUniformResourceIndex(int index); +``` + +## Availability + +**GLSL** `GL_EXT_nonuniform_qualifier` **HLSL** + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `normalize` + +## Signature + +``` +vector normalize(vector x); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `x` + +-------------------------------------------------------------------------------- +# `pow` + +## Signature + +``` +/// See Availability 1 +T pow( + T x, + T y); +/// See Availability 2 +vector pow( + vector x, + vector y); +/// See Availability 3 +matrix pow( + matrix x, + matrix y); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `y` + +-------------------------------------------------------------------------------- +# `Process2DQuadTessFactorsAvg` + +## Signature + +``` +void Process2DQuadTessFactorsAvg( + in vector RawEdgeFactors, + in vector InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `Process2DQuadTessFactorsMax` + +## Signature + +``` +void Process2DQuadTessFactorsMax( + in vector RawEdgeFactors, + in vector InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `Process2DQuadTessFactorsMin` + +## Signature + +``` +void Process2DQuadTessFactorsMin( + in vector RawEdgeFactors, + in vector InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `ProcessIsolineTessFactors` + +## Signature + +``` +void ProcessIsolineTessFactors( + in float RawDetailFactor, + in float RawDensityFactor, + out float RoundedDetailFactor, + out float RoundedDensityFactor); +``` + +## Parameters + +* `RawDetailFactor` +* `RawDensityFactor` +* `RoundedDetailFactor` +* `RoundedDensityFactor` + +-------------------------------------------------------------------------------- +# `ProcessQuadTessFactorsAvg` + +## Signature + +``` +void ProcessQuadTessFactorsAvg( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `ProcessQuadTessFactorsMax` + +## Signature + +``` +void ProcessQuadTessFactorsMax( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `ProcessQuadTessFactorsMin` + +## Signature + +``` +void ProcessQuadTessFactorsMin( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out vector RoundedInsideTessFactors, + out vector UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `ProcessTriTessFactorsAvg` + +## Signature + +``` +void ProcessTriTessFactorsAvg( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out float RoundedInsideTessFactor, + out float UnroundedInsideTessFactor); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactor` +* `UnroundedInsideTessFactor` + +-------------------------------------------------------------------------------- +# `ProcessTriTessFactorsMax` + +## Signature + +``` +void ProcessTriTessFactorsMax( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out float RoundedInsideTessFactor, + out float UnroundedInsideTessFactor); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactor` +* `UnroundedInsideTessFactor` + +-------------------------------------------------------------------------------- +# `ProcessTriTessFactorsMin` + +## Signature + +``` +void ProcessTriTessFactorsMin( + in vector RawEdgeFactors, + in float InsideScale, + out vector RoundedEdgeTessFactors, + out float RoundedInsideTessFactors, + out float UnroundedInsideTessFactors); +``` + +## Parameters + +* `RawEdgeFactors` +* `InsideScale` +* `RoundedEdgeTessFactors` +* `RoundedInsideTessFactors` +* `UnroundedInsideTessFactors` + +-------------------------------------------------------------------------------- +# `radians` + +## Signature + +``` +/// See Availability 1 +T radians(T x); +vector radians(vector x); +/// See Availability 2 +matrix radians(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `rcp` + +## Signature + +``` +T rcp(T x); +vector rcp(vector x); +matrix rcp(matrix x); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `reflect` + +## Signature + +``` +vector reflect( + vector i, + vector n); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `i` +* `n` + +-------------------------------------------------------------------------------- +# `refract` + +## Signature + +``` +vector refract( + vector i, + vector n, + T eta); +``` + +## Availability + +**GLSL** **HLSL** **SPIRV** + +## Parameters + +* `T` +* `N` +* `i` +* `n` +* `eta` + +-------------------------------------------------------------------------------- +# `reversebits` + +## Signature + +``` +/// See Availability 1 +uint reversebits(uint value); +/// See Availability 2 +vector reversebits(vector value); +``` + +## Availability + +1. **GLSL** **HLSL** **CPP** **CUDA** +2. **GLSL** **HLSL** + +## Parameters + +* `N` +* `value` + +-------------------------------------------------------------------------------- +# `round` + +## Signature + +``` +/// See Availability 1 +T round(T x); +/// See Availability 2 +vector round(vector x); +/// See Availability 3 +matrix round(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `rsqrt` + +## Signature + +``` +/// See Availability 1 +T rsqrt(T x); +/// See Availability 2 +vector rsqrt(vector x); +/// See Availability 3 +matrix rsqrt(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `saturate` + +## Signature + +``` +T saturate(T x); +vector saturate(vector x); +matrix saturate(matrix x); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `sign` + +## Signature + +``` +/// See Availability 1 +int sign(T x); +/// See Availability 2 +vector sign(vector x); +/// See Availability 3 +matrix sign(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `sin` + +## Signature + +``` +/// See Availability 1 +T sin(T x); +/// See Availability 2 +vector sin(vector x); +/// See Availability 3 +matrix sin(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `sincos` + +## Signature + +``` +/// See Availability 1 +void sincos( + T x, + out T s, + out T c); +/// See Availability 2 +void sincos( + vector x, + out vector s, + out vector c); +void sincos( + matrix x, + out matrix s, + out matrix c); +``` + +## Availability + +1. **HLSL** **CUDA** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` +* `s` +* `c` + +-------------------------------------------------------------------------------- +# `sinh` + +## Signature + +``` +/// See Availability 1 +T sinh(T x); +/// See Availability 2 +vector sinh(vector x); +/// See Availability 3 +matrix sinh(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `smoothstep` + +## Signature + +``` +/// See Availability 1 +T smoothstep( + T min, + T max, + T x); +vector smoothstep( + vector min, + vector max, + vector x); +/// See Availability 2 +matrix smoothstep( + matrix min, + matrix max, + matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `min` +* `max` +* `x` + +-------------------------------------------------------------------------------- +# `sqrt` + +## Signature + +``` +/// See Availability 1 +T sqrt(T x); +/// See Availability 2 +vector sqrt(vector x); +/// See Availability 3 +matrix sqrt(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `step` + +## Signature + +``` +/// See Availability 1 +T step( + T y, + T x); +vector step( + vector y, + vector x); +/// See Availability 2 +matrix step( + matrix y, + matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `y` +* `x` + +-------------------------------------------------------------------------------- +# `tan` + +## Signature + +``` +/// See Availability 1 +T tan(T x); +/// See Availability 2 +vector tan(vector x); +/// See Availability 3 +matrix tan(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `tanh` + +## Signature + +``` +/// See Availability 1 +T tanh(T x); +/// See Availability 2 +vector tanh(vector x); +/// See Availability 3 +matrix tanh(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `transpose` + +## Signature + +``` +matrix transpose(matrix x); +``` + +## Availability + +**GLSL** **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `trunc` + +## Signature + +``` +/// See Availability 1 +T trunc(T x); +/// See Availability 2 +vector trunc(vector x); +/// See Availability 3 +matrix trunc(matrix x); +``` + +## Availability + +1. **GLSL** **HLSL** **SPIRV** **CPP** **CUDA** +2. **GLSL** **HLSL** **SPIRV** +3. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `x` + +-------------------------------------------------------------------------------- +# `WaveGetConvergedMask` + +## Signature + +``` +uint WaveGetConvergedMask(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WaveGetActiveMask` + +## Signature + +``` +uint WaveGetActiveMask(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** + +-------------------------------------------------------------------------------- +# `WaveMaskIsFirstLane` + +## Signature + +``` +bool WaveMaskIsFirstLane(uint mask); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMaskAllTrue` + +## Signature + +``` +bool WaveMaskAllTrue( + uint mask, + bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` +* `condition` + +-------------------------------------------------------------------------------- +# `WaveMaskAnyTrue` + +## Signature + +``` +bool WaveMaskAnyTrue( + uint mask, + bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` +* `condition` + +-------------------------------------------------------------------------------- +# `WaveMaskBallot` + +## Signature + +``` +uint WaveMaskBallot( + uint mask, + bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` +* `condition` + +-------------------------------------------------------------------------------- +# `WaveMaskCountBits` + +## Signature + +``` +uint WaveMaskCountBits( + uint mask, + bool value); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot` **HLSL** **CUDA** + +## Parameters + +* `mask` +* `value` + +-------------------------------------------------------------------------------- +# `AllMemoryBarrierWithWaveMaskSync` + +## Signature + +``` +void AllMemoryBarrierWithWaveMaskSync(uint mask); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` + +-------------------------------------------------------------------------------- +# `GroupMemoryBarrierWithWaveMaskSync` + +## Signature + +``` +void GroupMemoryBarrierWithWaveMaskSync(uint mask); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` + +-------------------------------------------------------------------------------- +# `AllMemoryBarrierWithWaveSync` + +## Signature + +``` +void AllMemoryBarrierWithWaveSync(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** + +-------------------------------------------------------------------------------- +# `GroupMemoryBarrierWithWaveSync` + +## Signature + +``` +void GroupMemoryBarrierWithWaveSync(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WaveMaskBroadcastLaneAt` + +## Signature + +``` +/// See Availability 1 +T WaveMaskBroadcastLaneAt( + uint mask, + T value, + int lane); +vector WaveMaskBroadcastLaneAt( + uint mask, + vector value, + int lane); +/// See Availability 2 +matrix WaveMaskBroadcastLaneAt( + uint mask, + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WaveMaskReadLaneAt` + +## Signature + +``` +/// See Availability 1 +T WaveMaskReadLaneAt( + uint mask, + T value, + int lane); +vector WaveMaskReadLaneAt( + uint mask, + vector value, + int lane); +/// See Availability 2 +matrix WaveMaskReadLaneAt( + uint mask, + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WaveMaskShuffle` + +## Signature + +``` +/// See Availability 1 +T WaveMaskShuffle( + uint mask, + T value, + int lane); +vector WaveMaskShuffle( + uint mask, + vector value, + int lane); +/// See Availability 2 +matrix WaveMaskShuffle( + uint mask, + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixCountBits` + +## Signature + +``` +uint WaveMaskPrefixCountBits( + uint mask, + bool value); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** + +## Parameters + +* `mask` +* `value` + +-------------------------------------------------------------------------------- +# `WaveMaskBitAnd` + +## Signature + +``` +/// See Availability 1 +T WaveMaskBitAnd( + uint mask, + T expr); +vector WaveMaskBitAnd( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskBitAnd( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskBitOr` + +## Signature + +``` +/// See Availability 1 +T WaveMaskBitOr( + uint mask, + T expr); +vector WaveMaskBitOr( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskBitOr( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskBitXor` + +## Signature + +``` +/// See Availability 1 +T WaveMaskBitXor( + uint mask, + T expr); +vector WaveMaskBitXor( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskBitXor( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskMax` + +## Signature + +``` +/// See Availability 1 +T WaveMaskMax( + uint mask, + T expr); +vector WaveMaskMax( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskMax( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskMin` + +## Signature + +``` +/// See Availability 1 +T WaveMaskMin( + uint mask, + T expr); +vector WaveMaskMin( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskMin( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskProduct` + +## Signature + +``` +/// See Availability 1 +T WaveMaskProduct( + uint mask, + T expr); +vector WaveMaskProduct( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskProduct( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskSum` + +## Signature + +``` +/// See Availability 1 +T WaveMaskSum( + uint mask, + T expr); +vector WaveMaskSum( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskSum( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskAllEqual` + +## Signature + +``` +/// See Availability 1 +bool WaveMaskAllEqual( + uint mask, + T value); +bool WaveMaskAllEqual( + uint mask, + vector value); +/// See Availability 2 +bool WaveMaskAllEqual( + uint mask, + matrix value); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** **CUDA** `SM 7.0` +2. **HLSL** **CUDA** `SM 7.0` + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `value` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixProduct` + +## Signature + +``` +/// See Availability 1 +T WaveMaskPrefixProduct( + uint mask, + T expr); +vector WaveMaskPrefixProduct( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskPrefixProduct( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixSum` + +## Signature + +``` +/// See Availability 1 +T WaveMaskPrefixSum( + uint mask, + T expr); +vector WaveMaskPrefixSum( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskPrefixSum( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskReadLaneFirst` + +## Signature + +``` +/// See Availability 1 +T WaveMaskReadLaneFirst( + uint mask, + T expr); +vector WaveMaskReadLaneFirst( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskReadLaneFirst( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskMatch` + +## Signature + +``` +uint WaveMaskMatch( + uint mask, + T value); +uint WaveMaskMatch( + uint mask, + vector value); +uint WaveMaskMatch( + uint mask, + matrix value); +``` + +## Availability + +**HLSL** **CUDA** `SM 7.0` + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `value` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixBitAnd` + +## Signature + +``` +/// See Availability 1 +T WaveMaskPrefixBitAnd( + uint mask, + T expr); +/// See Availability 2 +vector WaveMaskPrefixBitAnd( + uint mask, + vector expr); +/// See Availability 3 +matrix WaveMaskPrefixBitAnd( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +3. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixBitOr` + +## Signature + +``` +/// See Availability 1 +T WaveMaskPrefixBitOr( + uint mask, + T expr); +vector WaveMaskPrefixBitOr( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskPrefixBitOr( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveMaskPrefixBitXor` + +## Signature + +``` +/// See Availability 1 +T WaveMaskPrefixBitXor( + uint mask, + T expr); +vector WaveMaskPrefixBitXor( + uint mask, + vector expr); +/// See Availability 2 +matrix WaveMaskPrefixBitXor( + uint mask, + matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `mask` +* `expr` + +-------------------------------------------------------------------------------- +# `QuadReadLaneAt` + +## Signature + +``` +T QuadReadLaneAt( + T sourceValue, + uint quadLaneID); +vector QuadReadLaneAt( + vector sourceValue, + uint quadLaneID); +matrix QuadReadLaneAt( + matrix sourceValue, + uint quadLaneID); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `sourceValue` +* `quadLaneID` + +-------------------------------------------------------------------------------- +# `QuadReadAcrossX` + +## Signature + +``` +T QuadReadAcrossX(T localValue); +vector QuadReadAcrossX(vector localValue); +matrix QuadReadAcrossX(matrix localValue); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `localValue` + +-------------------------------------------------------------------------------- +# `QuadReadAcrossY` + +## Signature + +``` +T QuadReadAcrossY(T localValue); +vector QuadReadAcrossY(vector localValue); +matrix QuadReadAcrossY(matrix localValue); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `localValue` + +-------------------------------------------------------------------------------- +# `QuadReadAcrossDiagonal` + +## Signature + +``` +T QuadReadAcrossDiagonal(T localValue); +vector QuadReadAcrossDiagonal(vector localValue); +matrix QuadReadAcrossDiagonal(matrix localValue); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `localValue` + +-------------------------------------------------------------------------------- +# `WaveActiveBitAnd` + +## Signature + +``` +/// See Availability 1 +T WaveActiveBitAnd(T expr); +vector WaveActiveBitAnd(vector expr); +/// See Availability 2 +matrix WaveActiveBitAnd(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveBitOr` + +## Signature + +``` +/// See Availability 1 +T WaveActiveBitOr(T expr); +vector WaveActiveBitOr(vector expr); +/// See Availability 2 +matrix WaveActiveBitOr(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveBitXor` + +## Signature + +``` +/// See Availability 1 +T WaveActiveBitXor(T expr); +vector WaveActiveBitXor(vector expr); +/// See Availability 2 +matrix WaveActiveBitXor(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveMax` + +## Signature + +``` +/// See Availability 1 +T WaveActiveMax(T expr); +vector WaveActiveMax(vector expr); +/// See Availability 2 +matrix WaveActiveMax(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveMin` + +## Signature + +``` +/// See Availability 1 +T WaveActiveMin(T expr); +vector WaveActiveMin(vector expr); +/// See Availability 2 +matrix WaveActiveMin(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveProduct` + +## Signature + +``` +/// See Availability 1 +T WaveActiveProduct(T expr); +vector WaveActiveProduct(vector expr); +/// See Availability 2 +matrix WaveActiveProduct(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveSum` + +## Signature + +``` +/// See Availability 1 +T WaveActiveSum(T expr); +vector WaveActiveSum(vector expr); +/// See Availability 2 +matrix WaveActiveSum(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveActiveAllEqual` + +## Signature + +``` +/// See Availability 1 +bool WaveActiveAllEqual(T value); +bool WaveActiveAllEqual(vector value); +/// See Availability 2 +bool WaveActiveAllEqual(matrix value); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `value` + +-------------------------------------------------------------------------------- +# `WaveActiveAllTrue` + +## Signature + +``` +bool WaveActiveAllTrue(bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** + +## Parameters + +* `condition` + +-------------------------------------------------------------------------------- +# `WaveActiveAnyTrue` + +## Signature + +``` +bool WaveActiveAnyTrue(bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_vote`, `SPIR-V 1.3` **HLSL** + +## Parameters + +* `condition` + +-------------------------------------------------------------------------------- +# `WaveActiveBallot` + +## Signature + +``` +vector WaveActiveBallot(bool condition); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** + +## Parameters + +* `condition` + +-------------------------------------------------------------------------------- +# `WaveActiveCountBits` + +## Signature + +``` +uint WaveActiveCountBits(bool value); +``` + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `WaveGetLaneCount` + +## Signature + +``` +uint WaveGetLaneCount(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WaveGetLaneIndex` + +## Signature + +``` +uint WaveGetLaneIndex(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WaveIsFirstLane` + +## Signature + +``` +bool WaveIsFirstLane(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_basic`, `SPIR-V 1.3` **HLSL** + +-------------------------------------------------------------------------------- +# `_WaveCountBits` + +## Signature + +``` +uint _WaveCountBits(vector value); +``` + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `WavePrefixProduct` + +## Signature + +``` +/// See Availability 1 +T WavePrefixProduct(T expr); +vector WavePrefixProduct(vector expr); +/// See Availability 2 +matrix WavePrefixProduct(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WavePrefixSum` + +## Signature + +``` +/// See Availability 1 +T WavePrefixSum(T expr); +vector WavePrefixSum(vector expr); +/// See Availability 2 +matrix WavePrefixSum(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveReadLaneFirst` + +## Signature + +``` +/// See Availability 1 +T WaveReadLaneFirst(T expr); +vector WaveReadLaneFirst(vector expr); +/// See Availability 2 +matrix WaveReadLaneFirst(matrix expr); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` + +-------------------------------------------------------------------------------- +# `WaveBroadcastLaneAt` + +## Signature + +``` +/// See Availability 1 +T WaveBroadcastLaneAt( + T value, + int lane); +vector WaveBroadcastLaneAt( + vector value, + int lane); +/// See Availability 2 +matrix WaveBroadcastLaneAt( + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WaveReadLaneAt` + +## Signature + +``` +/// See Availability 1 +T WaveReadLaneAt( + T value, + int lane); +vector WaveReadLaneAt( + vector value, + int lane); +/// See Availability 2 +matrix WaveReadLaneAt( + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WaveShuffle` + +## Signature + +``` +/// See Availability 1 +T WaveShuffle( + T value, + int lane); +vector WaveShuffle( + vector value, + int lane); +/// See Availability 2 +matrix WaveShuffle( + matrix value, + int lane); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_shuffle`, `SPIR-V 1.3` **HLSL** +2. **HLSL** + +## Parameters + +* `T` +* `N` +* `M` +* `value` +* `lane` + +-------------------------------------------------------------------------------- +# `WavePrefixCountBits` + +## Signature + +``` +uint WavePrefixCountBits(bool value); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** + +## Parameters + +* `value` + +-------------------------------------------------------------------------------- +# `WaveGetConvergedMulti` + +## Signature + +``` +vector WaveGetConvergedMulti(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WaveGetActiveMulti` + +## Signature + +``` +vector WaveGetActiveMulti(); +``` + +## Availability + +**GLSL** `GL_KHR_shader_subgroup_ballot`, `SPIR-V 1.3` **HLSL** + +-------------------------------------------------------------------------------- +# `WaveMatch` + +## Signature + +``` +vector WaveMatch(T value); +vector WaveMatch(vector value); +vector WaveMatch(matrix value); +``` + +## Parameters + +* `T` +* `N` +* `M` +* `value` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixCountBits` + +## Signature + +``` +uint WaveMultiPrefixCountBits( + bool value, + vector mask); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `value` +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixBitAnd` + +## Signature + +``` +/// See Availability 1 +T WaveMultiPrefixBitAnd( + T expr, + vector mask); +vector WaveMultiPrefixBitAnd( + vector expr, + vector mask); +/// See Availability 2 +matrix WaveMultiPrefixBitAnd( + matrix expr, + vector mask); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixBitOr` + +## Signature + +``` +/// See Availability 1 +T WaveMultiPrefixBitOr( + T expr, + vector mask); +vector WaveMultiPrefixBitOr( + vector expr, + vector mask); +/// See Availability 2 +matrix WaveMultiPrefixBitOr( + matrix expr, + vector mask); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixBitXor` + +## Signature + +``` +/// See Availability 1 +T WaveMultiPrefixBitXor( + T expr, + vector mask); +vector WaveMultiPrefixBitXor( + vector expr, + vector mask); +/// See Availability 2 +matrix WaveMultiPrefixBitXor( + matrix expr, + vector mask); +``` + +## Availability + +1. **GLSL** `GL_KHR_shader_subgroup_arithmetic`, `SPIR-V 1.3` **HLSL** **CUDA** +2. **HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `expr` +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixProduct` + +## Signature + +``` +T WaveMultiPrefixProduct( + T value, + vector mask); +vector WaveMultiPrefixProduct( + vector value, + vector mask); +matrix WaveMultiPrefixProduct( + matrix value, + vector mask); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `value` +* `mask` + +-------------------------------------------------------------------------------- +# `WaveMultiPrefixSum` + +## Signature + +``` +T WaveMultiPrefixSum( + T value, + vector mask); +vector WaveMultiPrefixSum( + vector value, + vector mask); +matrix WaveMultiPrefixSum( + matrix value, + vector mask); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `T` +* `N` +* `M` +* `value` +* `mask` + +-------------------------------------------------------------------------------- +# `struct Buffer` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `Buffer.GetDimensions` + +## Signature + +``` +void Buffer.GetDimensions(out uint dim); +``` + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `Buffer.Load` + +## Signature + +``` +/// See Availability 1 +T Buffer.Load(int location); +/// See Availability 2 +T Buffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `Buffer.subscript` + +## Signature + +``` +T Buffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct RWBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RWBuffer.GetDimensions` + +## Signature + +``` +void RWBuffer.GetDimensions(out uint dim); +``` + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `RWBuffer.Load` + +## Signature + +``` +/// See Availability 1 +T RWBuffer.Load(int location); +/// See Availability 2 +T RWBuffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RWBuffer.subscript` + +## Signature + +``` +T RWBuffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# `struct RasterizerOrderedBuffer` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` +* `Load` +* `subscript` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedBuffer.GetDimensions` + +## Signature + +``` +void RasterizerOrderedBuffer.GetDimensions(out uint dim); +``` + +## Parameters + +* `dim` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedBuffer.Load` + +## Signature + +``` +/// See Availability 1 +T RasterizerOrderedBuffer.Load(int location); +/// See Availability 2 +T RasterizerOrderedBuffer.Load( + int location, + out uint status); +``` + +## Availability + +1. **GLSL** `GL_EXT_samplerless_texture_functions` **HLSL** +2. **HLSL** + +## Parameters + +* `location` +* `status` + +-------------------------------------------------------------------------------- +# `RasterizerOrderedBuffer.subscript` + +## Signature + +``` +T RasterizerOrderedBuffer.subscript(uint index); +``` + +## Parameters + +* `index` + +-------------------------------------------------------------------------------- +# RAY_FLAG_NONE + +``` +uint RAY_FLAG_NONE +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_FORCE_OPAQUE + +``` +uint RAY_FLAG_FORCE_OPAQUE +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_FORCE_NON_OPAQUE + +``` +uint RAY_FLAG_FORCE_NON_OPAQUE +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH + +``` +uint RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_SKIP_CLOSEST_HIT_SHADER + +``` +uint RAY_FLAG_SKIP_CLOSEST_HIT_SHADER +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_CULL_BACK_FACING_TRIANGLES + +``` +uint RAY_FLAG_CULL_BACK_FACING_TRIANGLES +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_CULL_FRONT_FACING_TRIANGLES + +``` +uint RAY_FLAG_CULL_FRONT_FACING_TRIANGLES +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_CULL_OPAQUE + +``` +uint RAY_FLAG_CULL_OPAQUE +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_CULL_NON_OPAQUE + +``` +uint RAY_FLAG_CULL_NON_OPAQUE +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_SKIP_TRIANGLES + +``` +uint RAY_FLAG_SKIP_TRIANGLES +``` + +-------------------------------------------------------------------------------- +# RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES + +``` +uint RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES +``` + +-------------------------------------------------------------------------------- +# `struct RayDesc` + +## Fields + +* `Origin` +* `TMin` +* `Direction` +* `TMax` + +-------------------------------------------------------------------------------- +# `struct RaytracingAccelerationStructure` + +-------------------------------------------------------------------------------- +# `struct BuiltInTriangleIntersectionAttributes` + +## Fields + +* `barycentrics` + +-------------------------------------------------------------------------------- +# `CallShader` + +## Signature + +``` +void CallShader( + uint shaderIndex, + inout Payload payload); +``` + +## Parameters + +* `Payload` +* `shaderIndex` +* `payload` + +-------------------------------------------------------------------------------- +# `TraceRay` + +## Signature + +``` +void TraceRay( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + inout payload_t Payload); +``` + +## Availability + +**HLSL** **CUDA** + +## Parameters + +* `payload_t` +* `AccelerationStructure` +* `RayFlags` +* `InstanceInclusionMask` +* `RayContributionToHitGroupIndex` +* `MultiplierForGeometryContributionToHitGroupIndex` +* `MissShaderIndex` +* `Ray` +* `Payload` + +-------------------------------------------------------------------------------- +# `TraceMotionRay` + +## Signature + +``` +void TraceMotionRay( + RaytracingAccelerationStructure AccelerationStructure, + uint RayFlags, + uint InstanceInclusionMask, + uint RayContributionToHitGroupIndex, + uint MultiplierForGeometryContributionToHitGroupIndex, + uint MissShaderIndex, + RayDesc Ray, + float CurrentTime, + inout payload_t Payload); +``` + +## Parameters + +* `payload_t` +* `AccelerationStructure` +* `RayFlags` +* `InstanceInclusionMask` +* `RayContributionToHitGroupIndex` +* `MultiplierForGeometryContributionToHitGroupIndex` +* `MissShaderIndex` +* `Ray` +* `CurrentTime` +* `Payload` + +-------------------------------------------------------------------------------- +# `ReportHit` + +## Signature + +``` +bool ReportHit( + float tHit, + uint hitKind, + A attributes); +``` + +## Parameters + +* `A` +* `tHit` +* `hitKind` +* `attributes` + +-------------------------------------------------------------------------------- +# `IgnoreHit` + +## Signature + +``` +void IgnoreHit(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `AcceptHitAndEndSearch` + +## Signature + +``` +void AcceptHitAndEndSearch(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `DispatchRaysIndex` + +## Signature + +``` +vector DispatchRaysIndex(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `DispatchRaysDimensions` + +## Signature + +``` +vector DispatchRaysDimensions(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WorldRayOrigin` + +## Signature + +``` +vector WorldRayOrigin(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `WorldRayDirection` + +## Signature + +``` +vector WorldRayDirection(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `RayTMin` + +## Signature + +``` +float RayTMin(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `RayTCurrent` + +## Signature + +``` +float RayTCurrent(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `RayFlags` + +## Signature + +``` +uint RayFlags(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `InstanceIndex` + +## Signature + +``` +uint InstanceIndex(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `InstanceID` + +## Signature + +``` +uint InstanceID(); +``` + +## Availability + +**GLSL** `__glslRayTracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `PrimitiveIndex` + +## Signature + +``` +uint PrimitiveIndex(); +``` + +## Availability + +**GLSL** `__glslRayTracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `ObjectRayOrigin` + +## Signature + +``` +vector ObjectRayOrigin(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `ObjectRayDirection` + +## Signature + +``` +vector ObjectRayDirection(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# `ObjectToWorld3x4` + +## Signature + +``` +matrix ObjectToWorld3x4(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** + +-------------------------------------------------------------------------------- +# `WorldToObject3x4` + +## Signature + +``` +matrix WorldToObject3x4(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** + +-------------------------------------------------------------------------------- +# `ObjectToWorld4x3` + +## Signature + +``` +matrix ObjectToWorld4x3(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** + +-------------------------------------------------------------------------------- +# `WorldToObject4x3` + +## Signature + +``` +matrix WorldToObject4x3(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** + +-------------------------------------------------------------------------------- +# `RayCurrentTime` + +## Signature + +``` +float RayCurrentTime(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_NV_ray_tracing_motion_blur` **HLSL** + +-------------------------------------------------------------------------------- +# `ObjectToWorld` + +## Signature + +``` +matrix ObjectToWorld(); +``` + +-------------------------------------------------------------------------------- +# `WorldToObject` + +## Signature + +``` +matrix WorldToObject(); +``` + +-------------------------------------------------------------------------------- +# `HitKind` + +## Signature + +``` +uint HitKind(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing`, `GL_NV_ray_tracing` **HLSL** **CUDA** + +-------------------------------------------------------------------------------- +# HIT_KIND_TRIANGLE_FRONT_FACE + +``` +uint HIT_KIND_TRIANGLE_FRONT_FACE +``` + +-------------------------------------------------------------------------------- +# HIT_KIND_TRIANGLE_BACK_FACE + +``` +uint HIT_KIND_TRIANGLE_BACK_FACE +``` + +-------------------------------------------------------------------------------- +# `dot4add_u8packed` + +## Signature + +``` +uint dot4add_u8packed( + uint left, + uint right, + uint acc); +``` + +## Parameters + +* `left` +* `right` +* `acc` + +-------------------------------------------------------------------------------- +# `dot4add_i8packed` + +## Signature + +``` +int dot4add_i8packed( + uint left, + uint right, + int acc); +``` + +## Parameters + +* `left` +* `right` +* `acc` + +-------------------------------------------------------------------------------- +# `dot2add` + +## Signature + +``` +float dot2add( + vector left, + vector right, + float acc); +``` + +## Parameters + +* `left` +* `right` +* `acc` + +-------------------------------------------------------------------------------- +# `SetMeshOutputCounts` + +## Signature + +``` +void SetMeshOutputCounts( + uint vertexCount, + uint primitiveCount); +``` + +## Parameters + +* `vertexCount` +* `primitiveCount` + +-------------------------------------------------------------------------------- +# `DispatchMesh` + +## Signature + +``` +void DispatchMesh

    ( + uint threadGroupCountX, + uint threadGroupCountY, + uint threadGroupCountZ, + P meshPayload); +``` + +## Parameters + +* `P` +* `threadGroupCountX` +* `threadGroupCountY` +* `threadGroupCountZ` +* `meshPayload` + +-------------------------------------------------------------------------------- +# `struct SAMPLER_FEEDBACK_MIN_MIP` + +*Implements:* `__BuiltinSamplerFeedbackType` + +-------------------------------------------------------------------------------- +# `struct SAMPLER_FEEDBACK_MIP_REGION_USED` + +*Implements:* `__BuiltinSamplerFeedbackType` + +-------------------------------------------------------------------------------- +# `struct FeedbackTexture2D` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2D.GetDimensions` + +## Signature + +``` +void FeedbackTexture2D.GetDimensions( + out uint width, + out uint height); +void FeedbackTexture2D.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint numberOfLevels); +void FeedbackTexture2D.GetDimensions( + out float width, + out float height); +void FeedbackTexture2D.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float numberOfLevels); +``` + +## Parameters + +* `width` +* `height` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2D.WriteSamplerFeedbackLevel` + +## Signature + +``` +void FeedbackTexture2D.WriteSamplerFeedbackLevel( + Texture2D tex, + SamplerState samp, + vector location, + float lod); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `tex` +* `samp` +* `location` +* `lod` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2D.WriteSamplerFeedback` + +## Signature + +``` +void FeedbackTexture2D.WriteSamplerFeedback( + Texture2D tex, + SamplerState samp, + vector location, + float clamp); +void FeedbackTexture2D.WriteSamplerFeedback( + Texture2D tex, + SamplerState samp, + vector location); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `tex` +* `samp` +* `location` +* `clamp` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2D.WriteSamplerFeedbackBias` + +## Signature + +``` +void FeedbackTexture2D.WriteSamplerFeedbackBias( + Texture2D tex, + SamplerState samp, + vector location, + float bias, + float clamp); +void FeedbackTexture2D.WriteSamplerFeedbackBias( + Texture2D tex, + SamplerState samp, + vector location, + float bias); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `tex` +* `samp` +* `location` +* `bias` +* `clamp` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2D.WriteSamplerFeedbackGrad` + +## Signature + +``` +void FeedbackTexture2D.WriteSamplerFeedbackGrad( + Texture2D tex, + SamplerState samp, + vector location, + vector ddx, + vector ddy, + float clamp); +void FeedbackTexture2D.WriteSamplerFeedbackGrad( + Texture2D tex, + SamplerState samp, + vector location, + vector ddx, + vector ddy); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `tex` +* `samp` +* `location` +* `ddx` +* `ddy` +* `clamp` + +-------------------------------------------------------------------------------- +# `struct FeedbackTexture2DArray` + +## Generic Parameters + +* `T` + +## Methods + +* `GetDimensions` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2DArray.GetDimensions` + +## Signature + +``` +void FeedbackTexture2DArray.GetDimensions( + out uint width, + out uint height, + out uint elements); +void FeedbackTexture2DArray.GetDimensions( + uint mipLevel, + out uint width, + out uint height, + out uint elements, + out uint numberOfLevels); +void FeedbackTexture2DArray.GetDimensions( + out float width, + out float height, + out float elements); +void FeedbackTexture2DArray.GetDimensions( + uint mipLevel, + out float width, + out float height, + out float elements, + out float numberOfLevels); +``` + +## Parameters + +* `width` +* `height` +* `elements` +* `mipLevel` +* `numberOfLevels` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2DArray.WriteSamplerFeedbackLevel` + +## Signature + +``` +void FeedbackTexture2DArray.WriteSamplerFeedbackLevel( + Texture2DArray texArray, + SamplerState samp, + vector location, + float lod); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `texArray` +* `samp` +* `location` +* `lod` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2DArray.WriteSamplerFeedback` + +## Signature + +``` +void FeedbackTexture2DArray.WriteSamplerFeedback( + Texture2DArray texArray, + SamplerState samp, + vector location, + float clamp); +void FeedbackTexture2DArray.WriteSamplerFeedback( + Texture2DArray texArray, + SamplerState samp, + vector location); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `texArray` +* `samp` +* `location` +* `clamp` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2DArray.WriteSamplerFeedbackBias` + +## Signature + +``` +void FeedbackTexture2DArray.WriteSamplerFeedbackBias( + Texture2DArray texArray, + SamplerState samp, + vector location, + float bias, + float clamp); +void FeedbackTexture2DArray.WriteSamplerFeedbackBias( + Texture2DArray texArray, + SamplerState samp, + vector location, + float bias); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `texArray` +* `samp` +* `location` +* `bias` +* `clamp` + +-------------------------------------------------------------------------------- +# `FeedbackTexture2DArray.WriteSamplerFeedbackGrad` + +## Signature + +``` +void FeedbackTexture2DArray.WriteSamplerFeedbackGrad( + Texture2DArray texArray, + SamplerState samp, + vector location, + vector ddx, + vector ddy, + float clamp); +void FeedbackTexture2DArray.WriteSamplerFeedbackGrad( + Texture2DArray texArray, + SamplerState samp, + vector location, + vector ddx, + vector ddy); +``` + +## Availability + +**HLSL** **CPP** + +## Parameters + +* `S` +* `texArray` +* `samp` +* `location` +* `ddx` +* `ddy` +* `clamp` + +-------------------------------------------------------------------------------- +# `GeometryIndex` + +## Signature + +``` +uint GeometryIndex(); +``` + +## Availability + +**GLSL** `GL_EXT_ray_tracing` **HLSL** + +-------------------------------------------------------------------------------- +# COMMITTED_NOTHING + +``` +uint COMMITTED_NOTHING +``` + +-------------------------------------------------------------------------------- +# COMMITTED_TRIANGLE_HIT + +``` +uint COMMITTED_TRIANGLE_HIT +``` + +-------------------------------------------------------------------------------- +# COMMITTED_PROCEDURAL_PRIMITIVE_HIT + +``` +uint COMMITTED_PROCEDURAL_PRIMITIVE_HIT +``` + +-------------------------------------------------------------------------------- +# CANDIDATE_NON_OPAQUE_TRIANGLE + +``` +uint CANDIDATE_NON_OPAQUE_TRIANGLE +``` + +-------------------------------------------------------------------------------- +# CANDIDATE_PROCEDURAL_PRIMITIVE + +``` +uint CANDIDATE_PROCEDURAL_PRIMITIVE +``` + +-------------------------------------------------------------------------------- +# `struct RayQuery` + +## Generic Parameters + +* `rayFlags` + +## Methods + +* `init` +* `TraceRayInline` +* `Proceed` +* `Abort` +* `CandidateType` +* `CandidateObjectToWorld3x4` +* `CandidateObjectToWorld4x3` +* `CandidateWorldToObject3x4` +* `CandidateWorldToObject4x3` +* `CandidateInstanceIndex` +* `CandidateInstanceID` +* `CandidateGeometryIndex` +* `CandidatePrimitiveIndex` +* `CandidateInstanceContributionToHitGroupIndex` +* `CandidateObjectRayOrigin` +* `CandidateObjectRayDirection` +* `CandidateProceduralPrimitiveNonOpaque` +* `CandidateTriangleFrontFace` +* `CandidateTriangleBarycentrics` +* `CandidateTriangleRayT` +* `CommitNonOpaqueTriangleHit` +* `CommitProceduralPrimitiveHit` +* `CommittedStatus` +* `CommittedObjectToWorld3x4` +* `CommittedObjectToWorld4x3` +* `CommittedWorldToObject3x4` +* `CommittedWorldToObject4x3` +* `CommittedRayT` +* `CommittedInstanceIndex` +* `CommittedInstanceID` +* `CommittedGeometryIndex` +* `CommittedPrimitiveIndex` +* `CommittedInstanceContributionToHitGroupIndex` +* `CommittedObjectRayOrigin` +* `CommittedObjectRayDirection` +* `CommittedTriangleFrontFace` +* `CommittedTriangleBarycentrics` +* `RayFlags` +* `WorldRayOrigin` +* `WorldRayDirection` +* `RayTMin` + +-------------------------------------------------------------------------------- +# `RayQuery.init` + +## Signature + +``` +RayQuery.init(); +``` + +-------------------------------------------------------------------------------- +# `RayQuery.TraceRayInline` + +## Signature + +``` +void RayQuery.TraceRayInline( + RaytracingAccelerationStructure accelerationStructure, + uint rayFlags, + uint instanceInclusionMask, + RayDesc ray); +``` + +## Parameters + +* `accelerationStructure` +* `rayFlags` +* `instanceInclusionMask` +* `ray` + +-------------------------------------------------------------------------------- +# `RayQuery.Proceed` + +## Signature + +``` +bool RayQuery.Proceed(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.Abort` + +## Signature + +``` +void RayQuery.Abort(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateType` + +## Signature + +``` +uint RayQuery.CandidateType(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateObjectToWorld3x4` + +## Signature + +``` +matrix RayQuery.CandidateObjectToWorld3x4(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateObjectToWorld4x3` + +## Signature + +``` +matrix RayQuery.CandidateObjectToWorld4x3(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateWorldToObject3x4` + +## Signature + +``` +matrix RayQuery.CandidateWorldToObject3x4(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateWorldToObject4x3` + +## Signature + +``` +matrix RayQuery.CandidateWorldToObject4x3(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateInstanceIndex` + +## Signature + +``` +uint RayQuery.CandidateInstanceIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateInstanceID` + +## Signature + +``` +uint RayQuery.CandidateInstanceID(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateGeometryIndex` + +## Signature + +``` +uint RayQuery.CandidateGeometryIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidatePrimitiveIndex` + +## Signature + +``` +uint RayQuery.CandidatePrimitiveIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateInstanceContributionToHitGroupIndex` + +## Signature + +``` +uint RayQuery.CandidateInstanceContributionToHitGroupIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateObjectRayOrigin` + +## Signature + +``` +vector RayQuery.CandidateObjectRayOrigin(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateObjectRayDirection` + +## Signature + +``` +vector RayQuery.CandidateObjectRayDirection(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateProceduralPrimitiveNonOpaque` + +## Signature + +``` +bool RayQuery.CandidateProceduralPrimitiveNonOpaque(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateTriangleFrontFace` + +## Signature + +``` +bool RayQuery.CandidateTriangleFrontFace(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateTriangleBarycentrics` + +## Signature + +``` +vector RayQuery.CandidateTriangleBarycentrics(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CandidateTriangleRayT` + +## Signature + +``` +float RayQuery.CandidateTriangleRayT(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommitNonOpaqueTriangleHit` + +## Signature + +``` +void RayQuery.CommitNonOpaqueTriangleHit(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommitProceduralPrimitiveHit` + +## Signature + +``` +void RayQuery.CommitProceduralPrimitiveHit(float t); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +## Parameters + +* `t` + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedStatus` + +## Signature + +``` +uint RayQuery.CommittedStatus(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedObjectToWorld3x4` + +## Signature + +``` +matrix RayQuery.CommittedObjectToWorld3x4(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedObjectToWorld4x3` + +## Signature + +``` +matrix RayQuery.CommittedObjectToWorld4x3(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedWorldToObject3x4` + +## Signature + +``` +matrix RayQuery.CommittedWorldToObject3x4(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedWorldToObject4x3` + +## Signature + +``` +matrix RayQuery.CommittedWorldToObject4x3(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedRayT` + +## Signature + +``` +float RayQuery.CommittedRayT(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedInstanceIndex` + +## Signature + +``` +uint RayQuery.CommittedInstanceIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedInstanceID` + +## Signature + +``` +uint RayQuery.CommittedInstanceID(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedGeometryIndex` + +## Signature + +``` +uint RayQuery.CommittedGeometryIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedPrimitiveIndex` + +## Signature + +``` +uint RayQuery.CommittedPrimitiveIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedInstanceContributionToHitGroupIndex` + +## Signature + +``` +uint RayQuery.CommittedInstanceContributionToHitGroupIndex(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedObjectRayOrigin` + +## Signature + +``` +vector RayQuery.CommittedObjectRayOrigin(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedObjectRayDirection` + +## Signature + +``` +vector RayQuery.CommittedObjectRayDirection(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedTriangleFrontFace` + +## Signature + +``` +bool RayQuery.CommittedTriangleFrontFace(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.CommittedTriangleBarycentrics` + +## Signature + +``` +vector RayQuery.CommittedTriangleBarycentrics(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.RayFlags` + +## Signature + +``` +uint RayQuery.RayFlags(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.WorldRayOrigin` + +## Signature + +``` +vector RayQuery.WorldRayOrigin(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.WorldRayDirection` + +## Signature + +``` +vector RayQuery.WorldRayDirection(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `RayQuery.RayTMin` + +## Signature + +``` +float RayQuery.RayTMin(); +``` + +## Availability + +**GLSL** `GLSL460`, `GL_EXT_ray_query` **HLSL** + +-------------------------------------------------------------------------------- +# `struct VkSubpassInput` + +## Generic Parameters + +* `T` + +## Methods + +* `SubpassLoad` + +-------------------------------------------------------------------------------- +# `VkSubpassInput.SubpassLoad` + +## Signature + +``` +T VkSubpassInput.SubpassLoad(); +``` + +-------------------------------------------------------------------------------- +# `struct VkSubpassInputMS` + +## Generic Parameters + +* `T` + +## Methods + +* `SubpassLoad` + +-------------------------------------------------------------------------------- +# `VkSubpassInputMS.SubpassLoad` + +## Signature + +``` +T VkSubpassInputMS.SubpassLoad(int sampleIndex); +``` + +## Parameters + +* `sampleIndex` + diff --git a/lib/All/slang/share/doc/slang/stdlib-docgen.md b/lib/All/slang/share/doc/slang/stdlib-docgen.md new file mode 100644 index 0000000..37c4d30 --- /dev/null +++ b/lib/All/slang/share/doc/slang/stdlib-docgen.md @@ -0,0 +1,123 @@ +# Slang Core Module Documentation Generation Tool + +Slang's core module reference (https://shader-slang.com/stdlib-reference) is generated by `slangc` from the source of the core module. +This page covers how `slangc` can be used to generate this documentation. + +## Generating Documentation + +Follow these steps to generate the core module reference documentation and view the generated markdown files locally: + +``` +# clone stdlib-reference repo +git clone https://github.com/shader-slang/stdlib-reference +cd stdlib-reference + +# delete existing pages +rm -rf ./interfaces +rm -rf ./types +rm -rf ./global-decls +rm -rf ./attributes + +# generate updated pages +slangc -compile-core-module -doc + +# optional: move generated toc.html to `_includes` +mv toc.html ./_includes/stdlib-reference-toc.html +``` + +`slangc` will read the `config.txt` file in the stdlib-reference repository, and then generate all the markdown files +located in `types`, `attributes`, `interfaces` and `global-decls` directory. + +Note that the `index.md` in root is not generated. + +You should review the generated markdown file to make sure it is formatted correctly after making comment edits in the +`*.meta.slang` files. + + +## Writing and Updating Documentation + +The core module documentation is done directly in comments inside `source/slang/*.meta.slang` files. +A documentation comment should be placed directly above the declaration, either inside a `/** */` comment block, or +after `///`. The following directives are allowed in comments: + +- `@param paramName description` documents a parameter or a generic parameter. +- `@remarks` starts the remarks section. +- `@see` starts the "See also" section. +- `@return` starts the `Return value" section. +- `@example` starts the "Example" section. +- `@category categoryID Category Name` marks the decl to be in a category. The category name is only required for the first time `categoryID` is used, and omitted for the remaining `@category` lines. +- `@internal` marks the declaration as internal. +- `@experimental` marks the declaration as experimental. +- `@deprecated` marks the declaration as deprecated. + +You can use markdown syntax in any part of the comment. + +For overloaded functions, only document the first overload. List all parameters from all overloads in the same comment block for the first overload. Documentation on the remaining overloads will be ignored by the tool. If an overloaded decl has differing documentation on different overload candidates, the `slangc` tool will emit a warning. + +The following code is an example of how `_Texture.Sample` is documented. Notice that only the first overload is documented, and it also includes documentation for parameters which are only present in subsequent overloads, such as `offset`. + +```csharp + /// Samples the texture at the given location. + /// + ///@param s The `SamplerState` to use for the sampling operation. This parameter is omitted when `this` is a combined texture sampler type (`isCombined == 0`). + ///@param location The location to sample the texture at. + ///@param offset Texel offset to apply. + ///@param clamp The max level of detail to use. + ///@param[out] status The result status of the operation. + /// This parameter is currently only used when targeting HLSL. + /// For other targets, the result status is always 0. + ///@return The sampled texture value. + ///@see `SampleBias`, `SampleLevel`, `SampleGrad`, `SampleCmp`, `SampleCmpLevelZero`. + ///@remarks + /// The `Sample` function is defined for all read-only texture types, including + /// `Texture1D`, `Texture2D`, `Texture3D`, `TextureCube`, + /// `Texture1DArray`, `Texture2DArray` and `TextureCubeArray`. + /// + /// The function is not available for read-write texture types. + /// + /// For HLSL/D3D targets, the texture element type must be a scalar or vector of float or half types. + /// + [__readNone] + [ForceInline] + [require(cpp_cuda_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] + T Sample(vector location) + { + ... + } + + [__readNone] + [ForceInline] + [require(cpp_glsl_hlsl_metal_spirv_wgsl, texture_sm_4_0_fragment)] + T Sample(vector location, constexpr vector offset) + { + ... + } + +``` + +Note that unlike doxygen, the directives marks the start of a new section, and applies to all following paragraphs. You don't need to repetitively mark new paragraphs +as with `@remarks`. + +## What to document + +- Provide a brief description of the declaration in under three sentenses. +- Document all nuances, including target specific behaviors in the remarks section. +- Include examples if needed in the examples section. +- Provide a see also section with links to related declarations. + +After updating comments, build `slangc`, and run `slangc -compile-core-module -doc` in `stdlib-reference` directory to update the markdown files for preview. +Your PR only needs to include changes to *.meta.slang files. Once your PR is merged, slang CI will run `slangc` and push the updated markdown files to +the `stdlib-reference` repo. + +## Hiding a declaration + +Use `// @hidden:` to hide all declarations after the line for docgen purpose. +Use `// @public: ` to stop hiding all declarations after the line. These two special lines act like +C++'s visibility modifiers: they apply to everything after it. + +## How to preview generated html page locally + +To preview github pages locally, you need to follow instructions on setting up Jekyll: +https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/testing-your-github-pages-site-locally-with-jekyll + +You will need to use Jekyll to create a Gem file before serving it. diff --git a/lib/All/slang/share/doc/slang/target-compatibility.md b/lib/All/slang/share/doc/slang/target-compatibility.md new file mode 100644 index 0000000..690d8e1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/target-compatibility.md @@ -0,0 +1,360 @@ +# Slang Target Compatibility + +Shader Model (SM) numbers are D3D Shader Model versions, unless explicitly stated otherwise. +OpenGL compatibility is not listed here, because OpenGL isn't an officially supported target. + +Items with a + means that the feature is anticipated to be added in the future. +Items with ^ means there is some discussion about support later in the document for this target. + +| Feature | D3D11 | D3D12 | VK | CUDA | Metal | CPU | +| ---------------------------------------------------- | ----- | --------- | ------- | -------------- | ----- | --------- | +| [Half Type](#half) | No | Yes ^ | Yes | Yes ^ | Yes | No + | +| Double Type | Yes | Yes | Yes | Yes | No | Yes | +| Double Intrinsics | No | Limited + | Limited | Most | No | Yes | +| [u/int8_t Type](#int8_t) | No | No | Yes ^ | Yes | Yes | Yes | +| [u/int16_t Type](#int16_t) | No | Yes ^ | Yes ^ | Yes | Yes | Yes | +| [u/int64_t Type](#int64_t) | No | Yes ^ | Yes | Yes | Yes | Yes | +| u/int64_t Intrinsics | No | No | Yes | Yes | Yes | Yes | +| [int matrix](#int-matrix) | Yes | Yes | No + | Yes | No | Yes | +| [tex.GetDimensions](#tex-get-dimensions) | Yes | Yes | Yes | No | Yes | Yes | +| [SM6.0 Wave Intrinsics](#sm6-wave) | No | Yes | Partial | Yes ^ | No | No | +| SM6.0 Quad Intrinsics | No | Yes | No + | No | No | No | +| [SM6.5 Wave Intrinsics](#sm6.5-wave) | No | Yes ^ | No + | Yes ^ | No | No | +| [WaveMask Intrinsics](#wave-mask) | Yes ^ | Yes ^ | Yes + | Yes | No | No | +| [WaveShuffle](#wave-shuffle) | No | Limited ^ | Yes | Yes | No | No | +| [Tesselation](#tesselation) | Yes ^ | Yes ^ | No + | No | No | No | +| [Graphics Pipeline](#graphics-pipeline) | Yes | Yes | Yes | No | Yes | No | +| [Ray Tracing DXR 1.0](#ray-tracing-1.0) | No | Yes ^ | Yes ^ | No | No | No | +| Ray Tracing DXR 1.1 | No | Yes | No + | No | No | No | +| [Native Bindless](#native-bindless) | No | No | No | Yes | No | Yes | +| [Buffer bounds](#buffer-bounds) | Yes | Yes | Yes | Limited ^ | No ^ | Limited ^ | +| [Resource bounds](#resource-bounds) | Yes | Yes | Yes | Yes (optional) | Yes | Yes | +| Atomics | Yes | Yes | Yes | Yes | Yes | Yes | +| Group shared mem/Barriers | Yes | Yes | Yes | Yes | Yes | No + | +| [TextureArray.Sample float](#tex-array-sample-float) | Yes | Yes | Yes | No | Yes | Yes | +| [Separate Sampler](#separate-sampler) | Yes | Yes | Yes | No | Yes | Yes | +| [tex.Load](#tex-load) | Yes | Yes | Yes | Limited ^ | Yes | Yes | +| [Full bool](#full-bool) | Yes | Yes | Yes | No | Yes | Yes ^ | +| [Mesh Shader](#mesh-shader) | No | Yes | Yes | No | Yes | No | +| [`[unroll]`](#unroll] | Yes | Yes | Yes ^ | Yes | No ^ | Limited + | +| Atomics | Yes | Yes | Yes | Yes | Yes | No + | +| [Atomics on RWBuffer](#rwbuffer-atomics) | Yes | Yes | Yes | No | Yes | No + | +| [Sampler Feedback](#sampler-feedback) | No | Yes | No + | No | No | Yes ^ | +| [RWByteAddressBuffer Atomic](#byte-address-atomic) | No | Yes ^ | Yes ^ | Yes | Yes | No + | +| [Shader Execution Reordering](#ser) | No | Yes ^ | Yes ^ | No | No | No | +| [debugBreak](#debug-break) | No | No | Yes | Yes | No | Yes | +| [realtime clock](#realtime-clock) | No | Yes ^ | Yes | Yes | No | No | +| [Switch Fall-Through](#switch-fallthrough) | No ^ | Yes | Yes | Yes | Yes | Yes | + + + +## Half Type + +There appears to be a problem writing to a StructuredBuffer containing half on D3D12. D3D12 also appears to have problems doing calculations with half. + +In order for half to work in CUDA, NVRTC must be able to include `cuda_fp16.h` and related files. Please read the [CUDA target documentation](cuda-target.md) for more details. + + + +## u/int8_t Type + +Not currently supported in D3D11/D3D12 because not supported in HLSL/DXIL/DXBC. + +Supported in Vulkan via the extensions `GL_EXT_shader_explicit_arithmetic_types` and `GL_EXT_shader_8bit_storage`. + + + +## u/int16_t Type + +Requires SM6.2 which requires DXIL and therefore DXC and D3D12. For DXC this is discussed [here](https://github.com/Microsoft/DirectXShaderCompiler/wiki/16-Bit-Scalar-Types). + +Supported in Vulkan via the extensions `GL_EXT_shader_explicit_arithmetic_types` and `GL_EXT_shader_16bit_storage`. + + + +## u/int64_t Type + +Requires SM6.0 which requires DXIL for D3D12. Therefore not available with DXBC on D3D11 or D3D12. + + + +## int matrix + +Means can use matrix types containing integer types. + + + +## tex.GetDimensions + +tex.GetDimensions is the GetDimensions method on 'texture' objects. This is not supported on CUDA as CUDA has no equivalent functionality to get these values. GetDimensions work on Buffer resource types on CUDA. + + + +## SM6.0 Wave Intrinsics + +CUDA has premliminary support for Wave Intrinsics, introduced in [PR #1352](https://github.com/shader-slang/slang/pull/1352). Slang synthesizes the 'WaveMask' based on program flow and the implied 'programmer view' of execution. This support is built on top of WaveMask intrinsics with Wave Intrinsics being replaced with WaveMask Intrinsic calls with Slang generating the code to calculate the appropriate WaveMasks. + +Please read [PR #1352](https://github.com/shader-slang/slang/pull/1352) for a better description of the status. + + + +## SM6.5 Wave Intrinsics + +SM6.5 Wave Intrinsics are supported, but requires a downstream DXC compiler that supports SM6.5. As it stands the DXC shipping with windows does not. + + + +## WaveMask Intrinsics + +In order to map better to the CUDA sync/mask model Slang supports 'WaveMask' intrinsics. They operate in broadly the same way as the Wave intrinsics, but require the programmer to specify the lanes that are involved. To write code that uses wave intrinsics across targets including CUDA, currently the WaveMask intrinsics must be used. For this to work, the masks passed to the WaveMask functions should exactly match the 'Active lanes' concept that HLSL uses, otherwise the result is undefined. + +The WaveMask intrinsics are not part of HLSL and are only available on Slang. + + + +## WaveShuffle + +`WaveShuffle` and `WaveBroadcastLaneAt` are Slang specific intrinsic additions to expand the options available around `WaveReadLaneAt`. + +To be clear this means they will not compile directly on 'standard' HLSL compilers such as `dxc`, but Slang HLSL _output_ (which will not contain these intrinsics) can (and typically is) compiled via dxc. + +The difference between them can be summarized as follows + +- WaveBroadcastLaneAt - laneId must be a compile time constant +- WaveReadLaneAt - laneId can be dynamic but _MUST_ be the same value across the Wave ie 'dynamically uniform' across the Wave +- WaveShuffle - laneId can be truly dynamic (NOTE! That it is not strictly truly available currently on all targets, specifically HLSL) + +Other than the different restrictions on laneId they act identically to WaveReadLaneAt. + +`WaveBroadcastLaneAt` and `WaveReadLaneAt` will work on all targets that support wave intrinsics, with the only current restriction being that on GLSL targets, only scalars and vectors are supported. + +`WaveShuffle` will always work on CUDA/Vulkan. + +On HLSL based targets currently `WaveShuffle` will be converted into `WaveReadLaneAt`. Strictly speaking this means it _requires_ the `laneId` to be `dynamically uniform` across the Wave. In practice some hardware supports the loosened usage, and others does not. In the future this may be fixed in Slang and/or HLSL to work across all hardware. For now if you use `WaveShuffle` on HLSL based targets it will be necessary to confirm that `WaveReadLaneAt` has the loosened behavior for all the hardware intended. If target hardware does not support the loosened restrictions it's behavior is undefined. + + + +## Tesselation + +Although tesselation stages should work on D3D11 and D3D12 they are not tested within our test framework, and may have problems. + + + +## Native Bindless + +Bindless is possible on targets that support it - but is not the default behavior for those targets, and typically require significant effort in Slang code. + +'Native Bindless' targets use a form of 'bindless' for all targets. On CUDA this requires the target to use 'texture object' style binding and for the device to have 'compute capability 3.0' or higher. + + + +## Resource bounds + +For CUDA this is optional as can be controlled via the SLANG_CUDA_BOUNDARY_MODE macro in the `slang-cuda-prelude.h`. By default it's behavior is `cudaBoundaryModeZero`. + + + +## Buffer Bounds + +This is the feature when accessing outside of the bounds of a Buffer there is well defined behavior - on read returning all 0s, and on write, the write being ignored. + +On CPU there is only bounds checking on debug compilation of C++ code. This will assert if the access is out of range. + +On CUDA out of bounds accesses default to element 0 (!). The behavior can be controlled via the SLANG_CUDA_BOUND_CHECK macro in the `slang-cuda-prelude.h`. This behavior may seem a little strange - and it requires a buffer that has at least one member to not do something nasty. It is really a 'least worst' answer to a difficult problem and is better than out of range accesses or worse writes. + +In Metal, accessing a buffer out of bounds is undefined behavior. + + + +## TextureArray.Sample float + +When using 'Sample' on a TextureArray, CUDA treats the array index parameter as an int, even though it is passed as a float. + + + +## Separate Sampler + +This feature means that a multiple Samplers can be used with a Texture. In terms of the HLSL code this can be seen as the 'SamplerState' being a parameter passed to the 'Sample' method on a texture object. + +On CUDA the SamplerState is ignored, because on this target a 'texture object' is the Texture and Sampler combination. + + + +## Graphics Pipeline + +CPU and CUDA only currently support compute shaders. + + + +## Ray Tracing DXR 1.0 + +Vulkan does not support a local root signature, but there is the concept of a 'shader record'. In Slang a single constant buffer can be marked as a shader record with the `[[vk::shader_record]]` attribute, for example: + +``` +[[vk::shader_record]] +cbuffer ShaderRecord +{ + uint shaderRecordID; +} +``` + +In practice to write shader code that works across D3D12 and VK you should have a single constant buffer marked as 'shader record' for VK and then on D3D that constant buffer should be bound in the local root signature on D3D. + + + +## tex.Load + +tex.Load is only supported on CUDA for Texture1D. Additionally CUDA only allows such access for linear memory, meaning the bound texture can also not have mip maps. Load _is_ allowed on RWTexture types of other dimensions including 1D on CUDA. + + + +## Full bool + +Means fully featured bool support. CUDA has issues around bool because there isn't a vector bool type built in. Currently bool aliases to an int vector type. + +On CPU there are some issues in so far as bool's size is not well defined in size an alignment. Most C++ compilers now use a byte to represent a bool. In the past it has been backed by an int on some compilers. + + + +## `[unroll]` + +The unroll attribute allows for unrolling `for` loops. At the moment the feature is dependent on downstream compiler support which is mixed. In the longer term the intention is for Slang to contain it's own loop unroller - and therefore not be dependent on the feature on downstream compilers. + +On C++ this attribute becomes SLANG_UNROLL which is defined in the prelude. This can be predefined if there is a suitable mechanism, if there isn't a definition SLANG_UNROLL will be an empty definition. + +On GLSL and VK targets loop unrolling uses the [GL_EXT_control_flow_attributes](https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_control_flow_attributes.txt) extension. + +Metal Shading Language does not support loop unrolling. + +Slang does have a cross target mechanism to [unroll loops](language-reference/06-statements.md), in the section `Compile-Time For Statement`. + + + +## Atomics on RWBuffer + +For VK the GLSL output from Slang seems plausible, but VK binding fails in tests harness. + +On CUDA RWBuffer becomes CUsurfObject, which is a 'texture' type and does not support atomics. + +On the CPU atomics are not supported, but will be in the future. + + + +## Sampler Feedback + +The HLSL [sampler feedback feature](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html) is available for DirectX12. The features requires shader model 6.5 and therefore a version of [DXC](https://github.com/Microsoft/DirectXShaderCompiler) that supports that model or higher. The Shader Model 6.5 requirement also means only DXIL binary format is supported. + +There doesn't not appear to be a similar feature available in Vulkan yet, but when it is available support should be added. + +For CPU targets there is the IFeedbackTexture interface that requires an implementation for use. Slang does not currently include CPU implementations for texture types. + + + +## RWByteAddressBuffer Atomic + +The additional supported methods on RWByteAddressBuffer are... + +``` +void RWByteAddressBuffer::InterlockedAddF32(uint byteAddress, float valueToAdd, out float originalValue); +void RWByteAddressBuffer::InterlockedAddF32(uint byteAddress, float valueToAdd); + +void RWByteAddressBuffer::InterlockedAddI64(uint byteAddress, int64_t valueToAdd, out int64_t originalValue); +void RWByteAddressBuffer::InterlockedAddI64(uint byteAddress, int64_t valueToAdd); + +void RWByteAddressBuffer::InterlockedCompareExchangeU64(uint byteAddress, uint64_t compareValue, uint64_t value, out uint64_t outOriginalValue); + +uint64_t RWByteAddressBuffer::InterlockedExchangeU64(uint byteAddress, uint64_t value); + +uint64_t RWByteAddressBuffer::InterlockedMaxU64(uint byteAddress, uint64_t value); +uint64_t RWByteAddressBuffer::InterlockedMinU64(uint byteAddress, uint64_t value); + +uint64_t RWByteAddressBuffer::InterlockedAndU64(uint byteAddress, uint64_t value); +uint64_t RWByteAddressBuffer::InterlockedOrU64(uint byteAddress, uint64_t value); +uint64_t RWByteAddressBuffer::InterlockedXorU64(uint byteAddress, uint64_t value); +``` + +On HLSL based targets this functionality is achieved using [NVAPI](https://developer.nvidia.com/nvapi). Support for NVAPI is described +in the separate [NVAPI Support](nvapi-support.md) document. + +On Vulkan, for float the [`GL_EXT_shader_atomic_float`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_EXT_shader_atomic_float.html) extension is required. For int64 the [`GL_EXT_shader_atomic_int64`](https://raw.githubusercontent.com/KhronosGroup/GLSL/master/extensions/ext/GL_EXT_shader_atomic_int64.txt) extension is required. + +CUDA requires SM6.0 or higher for int64 support. + + + +## Mesh Shader + +There is preliminary [Mesh Shader support](https://github.com/shader-slang/slang/pull/2464). + + + +## Shader Execution Reordering + +More information about [Shader Execution Reordering](shader-execution-reordering.md). + +Currently support is available in D3D12 via NVAPI, and for Vulkan via the [GL_NV_shader_invocation_reorder](https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_shader_invocation_reorder.txt) extension. + + + +## Debug Break + +Slang has preliminary support for `debugBreak()` intrinsic. With the appropriate tooling, when `debugBreak` is hit it will cause execution to halt and display in the attached debugger. + +This is not supported on HLSL, GLSL, SPIR-V or Metal backends. Note that on some targets if there isn't an appropriate debugging environment the debugBreak might cause execution to fail or potentially it is ignored. + +On C++ targets debugBreak is implemented using SLANG_BREAKPOINT defined in "slang-cpp-prelude.h". If there isn't a suitable intrinsic, this will default to attempting to write to `nullptr` leading to a crash. + +Some additional details: + +- If [slang-llvm](cpu-target.md#slang-llvm) is being used as the downstream compiler (as is typical with `host-callable`), it will crash into the debugger, but may not produce a usable stack trace. +- For "normal" C++ downstream compilers such as Clang/Gcc/Visual Studio, to break into readable source code, debug information is typically necessary. Disabling optimizations may be useful to break on the appropriate specific line, and have variables inspectable. + + + +## Realtime Clock + +Realtime clock support is available via the API + +``` +// Get low 32 bits of realtime clock +uint getRealtimeClockLow(); +// Get 64 bit realtime clock, with low bits in .x and high bits in .y +uint2 getRealtimeClock(); +``` + +On D3D this is supported through NVAPI via `NvGetSpecial`. + +On Vulkan this is supported via [VK_KHR_shader_clock extension](https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_shader_clock.html) + +On CUDA this is supported via [clock](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#time-function). + +Currently this is not supported on CPU, although this will potentially be added in the future. + + + +## Switch Fall-Through + +Switch fall-through allows code in one case to execute and then continue into the next case without a `break`: + +```hlsl +switch(value) +{ +case 0: + x = 10; + // Fall through to case 1 +case 1: + result = x + value; + break; +} +``` + +This is natively supported on most targets. However, D3D11 (FXC/DXBC) and WGSL do not support fall-through in their switch statements. + +For these targets, Slang restructures the code by duplicating the fall-through destination into each source case. This produces functionally correct results, but has implications: + +- **Code size**: The generated code may be larger due to duplication. +- **Wave convergence**: If the duplicated code contains wave/subgroup operations, each copy executes independently, which may affect convergence behavior compared to native fall-through. + +When restructuring occurs, Slang emits warning 41026 to alert developers to this behavior change. + +To avoid restructuring, ensure each case ends with `break`, `return`, or another control transfer statement. diff --git a/lib/All/slang/share/doc/slang/update_spirv.md b/lib/All/slang/share/doc/slang/update_spirv.md new file mode 100644 index 0000000..8115ac2 --- /dev/null +++ b/lib/All/slang/share/doc/slang/update_spirv.md @@ -0,0 +1,231 @@ +# Updating external spirv + +There are three directories under `external` that are related to SPIR-V: +- external/spirv-headers +- external/spirv-tools +- external/spirv-tools-generated + +In order to use the latest or custom SPIR-V, they need to be updated. + + +## Update SPIRV-Tools + +On the Slang repo, you need to update to use the latest commit of SPIRV-Tools and SPIRV-Headers. + +1. Create a branch for the update. + ``` + # This doc will use "update_spirv" as a branch name, + # but you can use a different name. + git checkout -b update_spirv + ``` + +1. Synchronize and update submodules. + ``` + git submodule sync + git submodule update --init --recursive + ``` + +1. Update the SPIRV-Tools submodule to the latest version. + ``` + git -C external/spirv-tools fetch + git -C external/spirv-tools checkout origin/main + ``` + +## Build spirv-tools + +A directory, `external/spirv-tools/generated`, holds a set of files generated from spirv-tools directory. +You need to build spirv-tools in order to generate them. + +``` +cd external +cd spirv-tools +python3.exe utils\git-sync-deps # this step may require you to register your ssh public key to gitlab.khronos.org +cmake.exe . -B build +cmake.exe --build build --config Release + +# Go back to repository root +cd ../.. +``` + +## Update SPIRV-Headers + +1. Update the SPIRV-Headers submodule to what SPIRV-Tools uses + ``` + git -C external/spirv-headers fetch + git -C external/spirv-tools/external/spirv-headers log -1 --oneline + git -C external/spirv-headers checkout [commit hash from the previous command] + ``` + Alternatively you can get the hash value of spirv-headers with the following command, + ``` + grep spirv_headers_revision external/spirv-tools/DEPS + ``` + +Note that the update of SPIRV-Headers should be done after running `python3.exe utils\git-sync-deps`, because the python script will update `external/spirv-tools/external/spirv-headers` to whichever commit the current SPIRV-Tools depends on. + + +## Copy the generated files from `spirv-tools/build/` to `spirv-tools-generated/` + +Copy the generated header files from `external/spirv-tools/build/` to `external/spirv-tools-generated/`. +``` +rm external/spirv-tools-generated/*.h +rm external/spirv-tools-generated/*.inc +cp external/spirv-tools/build/*.h external/spirv-tools-generated/ +cp external/spirv-tools/build/*.inc external/spirv-tools-generated/ +``` + + +## Build Slang and run slang-test + +After SPIRV submodules are updated, you need to build and test. +``` +# Make sure to clean up data generated from the previous SPIRV +rm -fr build +``` + +There are many ways to build Slang executables. Refer to the [document](https://github.com/shader-slang/slang/blob/master/docs/building.md) for more detail. +For a quick reference, you can build with the following commands, +``` +cmake.exe --preset vs2022 +cmake.exe --build --preset release +``` + +After building Slang executables, run `slang-test` to see all tests are passing. +``` +set SLANG_RUN_SPIRV_VALIDATION=1 +build\Release\bin\slang-test.exe -use-test-server -server-count 8 +``` + +It is often the case that some of tests fail, because of the changes on SPIRV-Header. +You need to properly resolve them before proceed. + + +## Commit and create a Pull Request + +After testing is done, you need to stage and commit the updated submodule references and any generated files. +Note that when you want to use new commit IDs of the submodules, you have to stage with git-add command for the directory of the submodule itself. + +``` +git add external/spirv-headers +git add external/spirv-tools +git add external/spirv-tools-generated + +# Add any other changes needed to resolve test failures + +git commit -m "Update SPIRV-Tools and SPIRV-Headers to latest versions" +git push origin update_spirv # Use your own branch name as needed +``` + +Once all changes are pushed to GitHub, you can create a Pull Request on the main Slang repository. + +## CI Validation + +The Slang CI system includes an automated check that verifies the generated files in `external/spirv-tools-generated/` are up-to-date whenever changes are made to `external/spirv-tools` or `external/spirv-headers`. + +### What the CI Check Does + +When you create a Pull Request that modifies the SPIRV submodules, the CI will: + +1. Detect changes to `external/spirv-tools` or `external/spirv-headers` +2. Verify that the `spirv-headers` commit matches what `spirv-tools/DEPS` expects +3. Automatically regenerate the files that should be in `external/spirv-tools-generated/` +4. Compare the regenerated files with the committed files +5. **Fail the CI** if there are any discrepancies or mismatches + +This ensures that: +- The `spirv-headers` version is compatible with `spirv-tools` +- All generated files are correctly synchronized with the SPIRV-Tools version + +### When Does the CI Check Run? + +The check only runs when: +- A pull request modifies `external/spirv-tools/**` +- A pull request modifies `external/spirv-headers/**` +- A pull request modifies `external/spirv-tools-generated/**` +- The workflow or check script itself is modified + +This path filtering prevents unnecessary builds and keeps CI fast. + +### What Files Are Validated? + +The check verifies that the following generated files are present and up-to-date: +- `*.inc` files (e.g., `build-version.inc`, `core_tables_body.inc`, etc.) +- `*.h` files (e.g., `DebugInfo.h`, `OpenCLDebugInfo100.h`, etc.) + +The `README.md` file in `external/spirv-tools-generated/` is excluded from validation. + +### If the CI Check Fails + +If you see a failure from the "Check SPIRV Generated Files" job, it means the generated files are out of sync. The CI output will show: + +- Which files are missing +- Which files have differences +- Which files are orphaned (should be removed) + +To fix the issue, follow the instructions in the CI output, or re-run the steps in the [Copy the generated files](#copy-the-generated-files-from-spirv-toolsbuild-to-spirv-tools-generated) section above. + +#### Common Failure Scenarios + +**Scenario 1: Missing Files** +``` +ERROR: Missing file in spirv-tools-generated: new_file.inc +``` +This means a new file is now generated by SPIRV-Tools but hasn't been added to the repository. + +**Fix:** Follow the copy steps in the error message to add the new file. + +--- + +**Scenario 2: Outdated Files** +``` +ERROR: File differs: build-version.inc +``` +This means the file exists but its content doesn't match what SPIRV-Tools would generate. + +**Fix:** Regenerate and replace the file following the instructions in the CI output. + +--- + +**Scenario 3: Orphaned Files** +``` +ERROR: Orphaned file in spirv-tools-generated: old_file.inc +``` +This means a file exists in the repository but is no longer generated by SPIRV-Tools. + +**Fix:** Remove the file with `git rm external/spirv-tools-generated/old_file.inc` + +--- + +**Scenario 4: spirv-headers Commit Mismatch** +``` +ERROR: spirv-headers commit mismatch! +ERROR: Expected (from spirv-tools/DEPS): 6bb105b6c4b3a246e1e6bb96366fe14c6dbfde83 +ERROR: Actual (submodule): 1234567890abcdef1234567890abcdef12345678 +``` +This means the `spirv-headers` submodule commit doesn't match what `spirv-tools` expects in its DEPS file. + +**Fix:** Update `spirv-headers` to the expected commit: +```bash +git -C external/spirv-headers fetch +git -C external/spirv-headers checkout 6bb105b6c4b3a246e1e6bb96366fe14c6dbfde83 +git add external/spirv-headers +``` + +--- + +**Scenario 5: Submodule Not Updated** + +If you updated generated files but forgot to update the submodule reference: +```bash +git add external/spirv-tools +git add external/spirv-tools-generated +``` + +### Testing Locally + +You can run the same check locally before pushing to catch issues early: + +```bash +bash extras/check-spirv-generated.sh +``` + +This script will verify that your generated files match what would be produced by building SPIRV-Tools with the current submodule version. diff --git a/lib/All/slang/share/doc/slang/user-guide/00-introduction.md b/lib/All/slang/share/doc/slang/user-guide/00-introduction.md new file mode 100644 index 0000000..d9316ca --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/00-introduction.md @@ -0,0 +1,103 @@ +--- +layout: user-guide +permalink: /user-guide/introduction +--- + +Introduction +============ + +Welcome to the _Slang User's Guide_, an introduction to the Slang language, compiler, and API. + +Why use Slang? +-------------- + +The Slang system helps real-time graphics developers write cleaner and more maintainable GPU code, without sacrificing run-time performance. +Slang extends the HLSL language with thoughtfully selected features from modern general-purpose languages that support improved developer productivity and code quality. +These features have been carefully implemented with an understanding of GPU performance. + +Some of the benefits of Slang include: + +* Slang is backwards compatible with most existing HLSL code + +* _Parameter blocks_ allow shader parameters to be grouped by update rate in order to take advantage of Direct3D 12 descriptor tables and Vulkan descriptor sets, without verbose and error-prone per-parameter markup + +* _Interfaces_ and _generics_ provide first-class alternatives to hacky preprocessor-based or string-pasting shader specialization. Preprocessor hacks can be replaced with a well-understood language feature already used in Rust, Swift, C#, Java, and more. + +* _Automatic differentiation_ greatly simplifies the implementation of learning-based techniques in shaders. Slang supports automatically generating both forward derivative and backward derivative propagation functions from forward computation code. + +* Slang supports a first-class _module_ system, which enables true separate compilation and semantic checking of shader code. + +* Slang supports compute, rasterization, and ray-tracing shaders + +* The same Slang compiler can generate code for DX bytecode, DXIL, SPIR-V, HLSL, GLSL, CUDA, and more + +* Slang provides a robust and feature-complete reflection API, which provides binding/offset/layout information about all shader parameters in a consistent format across all the supported targets + +Who is Slang for? +----------------- + +Slang aims to be the best language possible for real-time graphics developers who care about code quality, portability and performance. + +### Real-Time Graphics Developers + +Slang is primarily intended for developers creating real-time graphics applications that run on end-user/client machines, such as 3D games and digital content creation (DCC) tools. + +Slang can still provide value in other scenarios -- offline rather than real-time rendering, non-graphics GPU programming, or for applications that run on a server instead of client machines -- but the system has been designed first and foremost around the requirements of real-time graphics. + +### From Hobbyists to Professionals + +The Slang language is simple and familiar enough for hobbyist developers to use, but scales up to the demands of professional development teams creating next-generation game renderers. + +### Developers of Multi-Platform Applications + +The Slang system builds for multiple OSes, supports many graphics APIs, and works with GPUs from multiple hardware vendors. +The project is completely open-source and patches to support additional platforms are welcome. + +Even for developers who only care about a single target platform or graphics API, Slang can provide a better programming experience than the default/native GPU language for that API. + +### Developers with an existing investment in HLSL code + +One of Slang's key features is its high degree of compatibility with existing HLSL code. +Developers who are currently responsible for large HLSL codebases but find themselves chafing at the restrictions of that language can incrementally adopt the features of Slang to improve the quality of their codebase over time. + +Developers who do not have an existing investment in HLSL code, or who already have a large codebase in some other language will need to carefully consider the trade-offs in migrating to a new language (whether Slang or something else). + +Who is this guide for? +---------------------- + +The content of this guide is written for real-time graphics programmers with a moderate or higher experience level. +It assumes the reader has previously used a real-time shading language like HLSL, GLSL, or MetalSL together with an API like Direct3D 11/12, Vulkan, or Metal. +We also assume that the reader is familiar enough with C/C++ to understand code examples and API signatures in those languages. + +If you are new to programming entirely, this guide is unlikely to be helpful. +If you are an experienced programmer but have never worked in real-time graphics with GPU shaders, you may find some of the terminology or concepts from the domain confusing. + +If you've only ever used OpenGL or Direct3D 11 before, some references to concepts in "modern" graphics APIs like D3D12/Vulkan/Metal may be confusing. +This effect may be particularly pronounced for OpenGL users. + +It may be valuable for a user with limited experience with "modern" graphics APIs to work with both this guide and a guide to their chosen API (e.g., Direct3D 12, Vulkan, or Metal) so that concepts in each can reinforce the other. + +When introducing Slang language features, this guide may make reference to languages such as Swift, Rust, C#, or Java. +Readers who almost exclusively use C/C++ may find certain features surprising or confusing, especially if they insist on equating concepts with the closest thing in C++ (assuming "generics `==` templates"). + +Goals and Non-Goals +------------------- + +The rest of this guide introduces the services provided by the Slang system and explains how to use them to solve challenges in real-time graphics programming. +When services are introduced one after another, it may be hard to glimpse the bigger picture: why these particular services? Why these implementations? Why these APIs? + +Before we dive into actually _using_ Slang, let us step back and highlight some of the key design goals (and non-goals) that motivate the design: + +* **Performance**: Real-time graphics demands high performance, which motivates the use of GPUs. Whenever possible, the benefits of using Slang must not come at the cost of performance. When a choice involves a performance trade-off the *user* of the system should be able to make that choice. + +* **Productivity**: Modern GPU codebases are large and growing. Productivity in a large codebase is less about _writing_ code quickly, and more about having code that is understandable, maintainable, reusable, and extensible. Language concepts like "modularity" or "separate compilation" are valuable if they foster greater developer productivity. + +* **Portability**: Real-time graphics developers need to support a wide variety of hardware, graphics APIs, and operating systems. These platforms differ greatly in the level of functionality they provide. Some systems hand-wave portability concerns out of existence by enforcing a "lowest common denominator" approach and/or raising their "min spec" to exclude older or less capable platforms; our goals differ greatly. We aspire to keep our "min spec" as low as is practical (e.g., supporting Direct3D 11 and not just Direct3D 12), while also allowing each target to expose its distinguishing capabilities. + +* **Ease of Adoption**: A language feature or service is worthless if nobody can use it. When possible, the system should be compatible with existing code and approaches. New language features should borrow syntax and semantics from other languages users might be familiar with. APIs and tools might need to support complicated and detailed use-cases, but should also provide conveniences and short-cuts for the most common cases. + +* **Predictability**: Code should do what it appears to, consistently, across as many platforms as possible. Whenever possible the compiler should conform to programmer expectation, even in the presence of "undefined behavior." Tools and optimization passes should keep their behavior as predictable as possible; simple tools empower the user to do smart things. + +* **Limited Scope**: The Slang system is a language, compiler, and module. It is not an engine, not a renderer, and not a "framework." The Slang system explicitly does *not* assume responsibility for interacting with GPU APIs to load code, allocate resources, bind parameters, or kick off work. While a user *may* use the Slang runtime library in their application, they are not *required* to do so. + +The ordering here is significant, with earlier goals generally being more important than later ones. diff --git a/lib/All/slang/share/doc/slang/user-guide/01-get-started.md b/lib/All/slang/share/doc/slang/user-guide/01-get-started.md new file mode 100644 index 0000000..4ce5bcc --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/01-get-started.md @@ -0,0 +1,108 @@ +--- +layout: user-guide +permalink: /user-guide/get-started +--- + +# Getting Started with Slang + +Slang enables you to do many powerful things with shader code, including compiling shader code to many different platforms, obtaining reflection information, organizing your shader library in a modern modular fashion, controlling specialization and more. The following sections help you get started with the basics of Slang in a simple example. We will assume Windows as the operating system, but the steps performed here are similar for other platforms. + +## Installation + +The easiest way to start using Slang is to download a [binary release](https://github.com/shader-slang/slang/releases/) from the GitHub repository. Once you have downloaded and extracted the files from a release package, you can find the `slangc.exe` or `slangc` executable under `/bin`. In this tutorial we will use the `slangc` standalone Slang compiler included in a release package. + +> #### Note: Required Dependencies #### +> For Windows, `slang-compiler.dll` and `slang-glslang.dll` must be placed in the same directory as `slangc.exe` as they are required by the standalone executable. + +> #### Note: Multiple Slang Installations #### +> If you have multiple versions of Slang installed on your system (such as Slang from the Vulkan SDK), ensure that the correct dynamic libraries are being loaded. On Linux, the `LD_LIBRARY_PATH` environment variable will override the `RUNPATH` embedded in the `slangc` executable, causing it to load `libslang-compiler.so` from the path specified in `LD_LIBRARY_PATH` first. This can lead to version mismatches and unexpected behavior. + +If you are interested in building from source, please refer to the [documentation on building Slang](../building.md). + +## Your first Slang shader + +In this section we demonstrate how to write a simple compute shader in Slang that adds numbers from two buffers and writes the results into a third buffer. To start, create a text file named `hello-world.slang` in any directory, and paste the following content in the newly created file: + +```hlsl +// hello-world.slang +StructuredBuffer buffer0; +StructuredBuffer buffer1; +RWStructuredBuffer result; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + uint index = threadId.x; + result[index] = buffer0[index] + buffer1[index]; +} +``` + +> #### Note #### +> Slang has official language extension support for both [Visual Studio](https://marketplace.visualstudio.com/items?itemName=shader-slang.slang-vs-extension) and [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=shader-slang.slang-language-extension). The extensions are powered by the Slang compiler to support a wide range of +> assisting features including auto-completion, function signature hinting, semantic highlighting and more. + +As you can see, `hello-world.slang` is no different from a normal HLSL shader file. In fact, Slang is compatible with most HLSL code you would write. On top of HLSL, Slang has added many new language and compiler features that simplifies various tasks with shader code, which we will cover in future chapters. For now we will demonstrate one key feature of Slang: cross-compiling to different platforms. + +Slang supports compiling shaders into many different targets including Direct3D 11, Direct3D 12, Vulkan, CUDA and C++ (for execution on CPU). You can run `slangc` with the following command line to compile `hello-world.slang` into Vulkan SPIRV: + +```bat +.\slangc.exe hello-world.slang -profile glsl_450 -target spirv -o hello-world.spv -entry computeMain +``` + +If you would like to see the equivalent GLSL of the generated SPIRV code, simply change the `-target` argument to `glsl`: +```bat +.\slangc.exe hello-world.slang -profile glsl_450 -target glsl -o hello-world.glsl -entry computeMain +``` + +The resulting `hello-world.glsl` generated by `slangc` is shown below: +```glsl +// hello-world.glsl (generated by slangc) +#version 450 +layout(row_major) uniform; +layout(row_major) buffer; + +#line 2 0 +layout(std430, binding = 0) readonly buffer _S1 { + float _data[]; +} buffer0_0; + +#line 3 +layout(std430, binding = 1) readonly buffer _S2 { + float _data[]; +} buffer1_0; + +#line 4 +layout(std430, binding = 2) buffer _S3 { + float _data[]; +} result_0; + +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +void main() +{ + +#line 10 + uint index_0 = gl_GlobalInvocationID.x; + float _S4 = ((buffer0_0)._data[(index_0)]); + +#line 11 + float _S5 = ((buffer1_0)._data[(index_0)]); + +#line 11 + float _S6 = _S4 + _S5; + +#line 11 + ((result_0)._data[(index_0)]) = _S6; + +#line 8 + return; +} +``` + +As you can see, things are being translated just as expected to GLSL: the HLSL `StructuredBuffer` and `RWStructuredBuffer` types are mapped to shader storage objects and the `[numthreads]` attribute are translated into proper `layout(...) in` qualifier on the `main` entry-point. + +Note that in the generated GLSL code, all shader parameters are qualified with explicit binding layouts. This is because Slang provides a guarantee that all parameters will have fixed bindings regardless of shader optimization. Without generating explicit binding layout qualifiers, the downstream compiler in the driver may change the binding of a parameter depending on whether any preceding parameters are eliminated during optimization passes. In practice this causes a pain in application code, where developers will need to rely on run-time reflection to determine the binding location of a compiled shader kernel. The issue gets harder to manage when the application also needs to deal with shader specializations. Since Slang will always generate explicit binding locations in its output on all targets as if no parameters are eliminated, the user is assured that parameters always gets a deterministic binding location without having to write any manual binding qualifiers in the Slang code themselves. In fact, we strongly encourage users not to qualify their Slang code with explicit binding qualifiers and let the Slang compiler do its work to properly lay out parameters. This is best practice to maintain code modularity and avoid potential binding location conflicts between different shader modules. + +## The full example + +The full Vulkan example that sets up and runs the `hello-world.slang` shader is located in the [/examples/hello-world](https://github.com/shader-slang/slang/tree/master/examples/hello-world) directory of the Slang repository. The example code initializes a Vulkan context and runs the compiled SPIRV code. The example code demonstrates how to use the Slang API to load and compile shaders. diff --git a/lib/All/slang/share/doc/slang/user-guide/02-conventional-features.md b/lib/All/slang/share/doc/slang/user-guide/02-conventional-features.md new file mode 100644 index 0000000..4f381f6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/02-conventional-features.md @@ -0,0 +1,1186 @@ +--- +layout: user-guide +permalink: /user-guide/conventional-features +--- + +Conventional Language Features +============================== + +Many of the language concepts in Slang are similar to those in other real-time shading languages like HLSL and GLSL, and also to general-purpose programming languages in the "C family." +This chapter covers those parts of the Slang language that are _conventional_ and thus unlikely to surprise users who are already familiar with other shading languages, or languages in the C family. + +Readers who are comfortable with HLSL variables, types, functions, statements, as well as conventions for shader parameters and entry points may prefer to skip this chapter. +Readers who are not familiar with HLSL, but who are comfortable with GLSL and/or C/C++, may want to carefully read the sections on types, expressions, shader parameters, and entry points while skimming the others. + +Types +----- + +Slang supports conventional shading language types including scalars, vectors, matrices, arrays, structures, enumerations, and resources. + +> #### Note #### +> Slang has limited support for pointers when targeting platforms with native pointer support, including SPIRV, C++, and CUDA. + +### Scalar Types + +#### Integer Types + +The following integer types are provided: + +| Name | Description | +|---------------|-------------| +| `int8_t` | 8-bit signed integer | +| `int16_t` | 16-bit signed integer | +| `int` | 32-bit signed integer | +| `int64_t` | 64-bit signed integer | +| `uint8_t` | 8-bit unsigned integer | +| `uint16_t` | 16-bit unsigned integer | +| `uint` | 32-bit unsigned integer | +| `uint64_t` | 64-bit unsigned integer | + +All targets support the 32-bit `int` and `uint` types, but support for the other types depends on the capabilities of each target platform. + +Integer literals can be both decimal and hexadecimal. An integer literal can be explicitly made unsigned +with a `u` suffix, and explicitly made 64-bit with the `ll` suffix. The type of a decimal non-suffixed integer literal is the first integer type from +the list [`int`, `int64_t`] which can represent the specified literal value. If the value cannot fit, the literal is represented as +an `uint64_t` and a warning is given. The type of hexadecimal non-suffixed integer literal is the first type from the list +[`int`, `uint`, `int64_t`, `uint64_t`] that can represent the specified literal value. For more information on 64 bit integer literals see the documentation on [64 bit type support](../64bit-type-support.md). + +The following floating-point types are provided: + +| Name | Description | +|---------------|------------------------------| +| `half` | 16-bit floating-point number | +| `float` | 32-bit floating-point number | +| `double` | 64-bit floating-point number | + +All targets support the 32-bit `float`, but support for the other types depends on the capabilities of each target platform. + +### Boolean Type + +The type `bool` is used to represent Boolean truth values: `true` and `false`. + +For compatibility reasons, the `sizeof(bool)` depends on the target. + +| Target | sizeof(bool) | +|--------| ---------------------- | +| GLSL | 4 bytes / 32-bit value | +| HLSL | 4 bytes / 32-bit value | +| CUDA | 1 bytes / 8-bit value | + +> #### Note #### +> When storing bool types in structures, make sure to either pad host-side data structures accordingly, or store booleans as, eg, `uint8_t`, to guarantee +> consistency with the host language's boolean type. + +#### The Void Type + +The type `void` is used as a placeholder to represent the result type of functions that don't return anything. + +### Vector Types + +Vector types can be written as `vector` where `T` is a scalar type and `N` is an integer from 2 to 4 (inclusive). +The type `vector` is a vector of `N` _elements_ (also called _components_) each of type `T`. + +As a convenience, pre-defined vector types exist for each scalar type and valid element count, with a name using the formula `<><>`. +For example, `float3` is a convenient name for `vector`. + +> Note: Slang doesn't support vectors longer than 4 elements. They map to native vector types on many platforms, including CUDA, and none of these platforms support vectors longer than 4 elements. If needed, you can use an array like `float myArray[8]`. + +### Matrix Types + +Matrix types can be written as `matrix` where `T` is a scalar type and both `R` and `C` are integers from 2 to 4 (inclusive). +The type `matrix` is a matrix with _elements_ of type `T`, and comprising `R` rows and `C` columns. + +As a convenience, pre-defined matrix types exist for each scalar type and valid row/column count, with a name using the formula `<><>x<>`. +For example, a `float3x4` is a convenient name for `matrix`. + +> #### Note #### +> Readers familiar with GLSL should be aware that a Slang `float3x4` represents a matrix with three rows and four columns, while a GLSL `mat3x4` represents a matrix with three *columns* and four *rows*. +> In most cases, this difference is immaterial because the subscript expression `m[i]` returns a `float4` (`vec4`) in either language. +> For now it is enough to be aware that there is a difference in convention between Slang/HLSL/D3D and GLSL/OpenGL. + +### Array Types + +An array type `T[N]` represents an array of `N` elements of type `T`. +When declaring a variable with an array type, the `[]` brackets come after the variable name, following the C convention for variable declarations: + +```hlsl +// the type of `a` is `int[3]` +int a[3]; +``` + +Sometimes a value with an array type can be declared without an explicit element count. +In some cases the element count is then inferred from the initial value of a variable: + +```hlsl +// the type of `a` is `int[3]` +int a[] = { 1, 2, 3 }; +``` + +In other cases, the result is a _unsized_ array, where the actual element count will be determined later: + +```hlsl +// the type of `b` is `int[]` +void f( int b[] ) +{ ... } +``` + +It is allowed to pass a sized array as argument to an unsized array parameter when calling a function. + +Array types has a `getCount()` member function that returns the length of the array. + +```hlsl +int f( int b[] ) +{ + return b.getCount(); // Note: all arguments to `b` must be resolvable to sized arrays. +} + +void test() +{ + int arr[3] = { 1, 2, 3 }; + int x = f(arr); // OK, passing sized array to unsized array parameter, x will be 3. +} +``` + +Please note that if a function calls `getCount()` method on an unsized array parameter, then all +calls to that function must provide a sized array argument, otherwise the compiler will not be able +to resolve the size and will report an error. The following code shows an example of valid and +invalid cases. + +```hlsl +int f( int b[] ) +{ + return b.getCount(); +} +int g( int b[] ) +{ + return f(b); // transitive calls are allowed. +} +uniform int unsizedParam[]; +void test() +{ + g(unsizedParam); // Not OK, `unsizedParam` doesn't have a known size at compile time. + int arr[3]; + g(arr); // OK. +} +``` + +There are more limits on how runtime-sized arrays can be used than on arrays of statically-known element count. + +> #### Note #### +> In Slang arrays are _value types_, meaning that assignment, parameter passing, etc. semantically copy values of array type. +> In some languages -- notably C, C++, C#, and Java -- assignment and parameter passing for treat arrays as _reference types_, +> meaning that these operations assign/pass a reference to the same underlying storage. + +### Structure Types + +Structure types can be introduced with the `struct` keyword, as in most C-family languages: + +```hlsl +struct MyData +{ + int a; + float b; +} +``` + +> #### Note #### +> Unlike C, and like most other C-family languages, the `struct` keyword in Slang introduces a type directly, and there is no need to combine it with a `typedef`. + +> #### Note #### +> Slang allows for a trailing semicolon (`;`) on `struct` declarations, but does not require it. + +> #### Note #### +> Unlike C/C++, `class` is not a valid keyword for GPU code and it is reserved for CPU/host side logic. + +Structure types can have constructors. Constructors are defined with the `__init` keyword: + +```hlsl +struct MyData +{ + int a; + __init() { a = 5; } + __init(int t) { a = t; } +} +void test() +{ + MyData d; // invokes default constructor, d.a = 5 + MyData h = MyData(4); // invokes overloaded constructor, h.a = 4 +} +``` + +### Default Values for Struct Members + +Alternatively, you can specify default values of members in the struct like so: + +```hlsl +struct MyData +{ + int a = 1; + float3 b = float3(0.5); +} +void test() +{ + MyData data = {}; // will initialize data.a to 1 and data.b to {0.5, 0.5, 0.5} + MyData data2 = MyData(); // equivalent to MyData data2 = {}; + MyData data3; // data3.a and data3.b will be undefined ! +} +``` + +### Enumeration Types + +Enumeration types can be introduced with the `enum` keyword to provide type-safe constants for a range of values: + +```hlsl +enum Channel +{ + Red, + Green, + Blue +} +``` + +Unlike C/C++, `enum` types in Slang are always scoped by default (like `enum class` in C++). You can write `enum class` in Slang if it makes you happy, but it isn't required. If you want a `enum` type to be unscoped, you can use the `[UnscopedEnum]` attribute: +```csharp +[UnscopedEnum] +enum Channel +{ + Red, Green, Blue +} +void test(Channel c) +{ + if (c == Red) { /*...*/ } +} +``` + +You can specify an explicit underlying integer type for `enum` types: +```csharp +enum Channel : uint16_t +{ + Red, Green, Blue +} +``` + +By default, the underlying type of an enumeration type is `int`. Enumeration types are implicitly convertible to their underlying type. All enumeration types conform to the builtin `ILogical` interface, which provides operator overloads for bit operations. The following code is allowed: + +```csharp +void test() +{ + Channel c = Channel.Red | Channel.Green; +} +``` + +You can explicitly assign values to each enum case: +```csharp +enum Channel +{ + Red = 5, + Green, // = 6 + Blue // = 7 +} +``` +Slang automatically assigns integer values to enum cases without an explicit value. By default, the value starts from 0 and is increment by 1 for each +enum case. + +You can override the implicit value assignment behavior with the `[Flags]` attribute, which will make value assignment start from 1 and increment by power of 2, making it suitable for enums that represent bit flags. For example: +```csharp +[Flags] +enum Channel +{ + Red, // = 1 + Green, // = 2 + Blue, // = 4 + Alpha, // = 8 +} +``` + +### Opaque Types + +The Slang core module defines a large number of _opaque_ types which provide access to objects that are allocated via GPU APIs. + +What all opaque types have in common is that they are not "first-class" types on most platforms. +Opaque types (and structure or array types that contain them) may be limited in the following ways (depending on the platform): + +* Functions that return opaque types may not be allowed +* Global and `static` variables that use opaque types may not be allowed +* Opaque types may not appear in the element types of buffers, except where explicitly noted as allowed + +#### Texture Types + +Texture types -- including `Texture2D`, `TextureCubeArray`, `RWTexture2D`, and more -- are used to access formatted data for read, write, and sampling operations. +Textures can be used to represent simple images, but also support _mipmapping_ as a way to reduce noise when sampling at lower than full resolution. +The full space of texture types follows the formula: + + <>Texture<><><><> + +where: + +* The _access_ can be read-only (no prefix), read-write (`RW`), or read-write with a guarantee of rasterization order for operations on the given resource (`RasterizerOrdered`). +* The _base shape_ can be `1D`, `2D`, `3D`, or `Cube`. +* The _multisample-ness_ can be non-multiple-sample, or multi-sampled (`MS`). +* The _array-ness_ can either be non-arrayed, or arrayed (`Array`). +* The _element type_ can either be explicitly specified (``) or left as the default of `float4` + +Not all combinations of these options are supported, and some combinations may be unsupported on some targets. + +#### Sampler + +Sampler types encapsulate parameters that control addressing and filtering for texture-sampling operations. +There are two sampler types: `SamplerState` and `SamplerComparisonState`. +`SamplerState` is applicable to most texture sampling operations, while `SamplerComparisonState` is used for "shadow" texture sampling operations which compare texels to a reference value before filtering. + +> #### Note #### +> Some target platforms and graphics APIs do not support separation of textures and sampling state into distinct types in shader code. +> On these platforms the Slang texture types include their own sampling state, and the sampler types are placeholder types that carry no data. + +#### Buffers + +There are multiple buffer types supported by modern graphics APIs, with substantially different semantics. + +##### Formatted Buffers + +Formatted buffers (sometimes referred to as "typed buffers" or "buffer textures") are similar to 1D textures (in that they support format conversion on loads), without support for mipmapping. +The formula for formatted buffer types is: + + <>Buffer<><> + +Where the _access_, _array-ness_, and _element type_ are the same as for textures, with the difference that _element type_ is not optional. + +A buffer type like `Buffer` represents a GPU resource that stores one or more values that may be fetched as a `float4` (but might internally be stored in another format, like RGBA8). + +##### Flat Buffers + +Flat buffers differ from formatted buffers in that they do not support format conversion. +Flat buffers are either _structured_ buffers or _byte-addressed_ buffers. + +Structured buffer types like `StructuredBuffer` include an explicit element type `T` that will be loaded and stored from the buffer. +Byte-addressed buffer types like `ByteAddressBuffer` do not specify any particular element type, and instead allow for values to be loaded or stored from any (suitably aligned) byte offset in the buffer. +Both structured and byte-addressed buffers can use an _access_ to distinguish between read-only and read-write usage. + +##### Constant Buffers + +Constant buffers (sometimes also called "uniform buffers") are typically used to pass immutable parameter data from a host application to GPU code. +The constant buffer type `ConstantBuffer` includes an explicit element type. +Unlike formatted or flat buffers, a constant buffer conceptually contains only a *single* value of its element type, rather than one or more values. + +Expressions +----------- + +Slang supports the following expression forms with nearly identical syntax to HLSL, GLSL, and C/C++: + +* Literals: `123`, `4.56`, `false` + +> #### Note #### +> Unlike C/C++, but like HLSL/GLSL, an unsuffixed floating-point literal has the `float` type in Slang, rather than `double` + +* Member lookup: `structValue.someField`, `MyEnumType.FirstCase` + +* Function calls: `sin(a)` + +* Vector/matrix initialization: `int4(1, 2, 3, 4)` + +* Casts: `(int)x`, `double(0.0)` + +* Subscript (indexing): `a[i]` + +* Initializer lists: `int b[] = { 1, 2, 3 };` + +* Assignment: `l = r` + +* Operators: `-a`, `b + c`, `d++`, `e %= f` + +> #### Note #### +> Like HLSL but unlike most other C-family languages, the `&&` and `||` operators do *not* currently perform "short-circuiting". +> they evaluate all of their operands unconditionally. +> However, the `?:` operator does perform short-circuiting if the condition is a scalar. Use of `?:` where the condition is a vector is deprecated in Slang. The vector version of `?:` operator does *not* perform short-circuiting, and the user is advised to call `select` instead. +> The default behavior of these operators is likely to change in a future Slang release. + +Additional expression forms specific to shading languages follow. + +### Operators on Vectors and Matrices + +The ordinary unary and binary operators can also be applied to vectors and matrices, where they apply element-wise. + +> #### Note #### +> In GLSL, most operators apply component-wise to vectors and matrices, but the multiplication operator `*` computes the traditional linear-algebraic product of two matrices, or a matrix and a vector. +> Where a GLSL programmer would write `m * v` to multiply a `mat3x4` by a `vec3`, a Slang programmer should write `mul(v,m)` to multiply a `float3` by a `float3x4`. +> In this example, the order of operands is reversed to account for the difference in row/column conventions. + +### Swizzles + +Given a value of vector type, a _swizzle_ expression extracts one or more of the elements of the vector to produce a new vector. +For example, if `v` is a vector of type `float4`, then `v.xy` is a `float2` consisting of the `x` and `y` elements of `v`. +Swizzles can reorder elements (`v.yx`) or include duplicate elements (`v.yyy`). + +> #### Note #### +> Unlike GLSL, Slang only supports `xyzw` and `rgba` as swizzle elements, and not the seldom-used `stpq`. + +> #### Note #### +> Unlike HLSL, Slang does not currently support matrix swizzle syntax. + +Statements +---------- + +Slang supports the following statement forms with nearly identical syntax to HLSL, GLSL, and C/C++: + +* Expression statements: `f(a, 3);`, `a = b * c;` + +* Local variable declarations: `int x = 99;` + +* Blocks: `{ ... }` + +* Empty statement: `;` + +* `if` statements + +* `switch` statements + +> #### Note #### +> Unlike C/C++, `case` and `default` statements must be directly nested under a `switch`, rather than being allowed under nested control flow (Duff's Device and similar idioms are not allowed). +> In addition, while multiple `case`s can be grouped together, all other forms of "fall through" are unsupported. + +* `for` statements + +* `while` statements + +* `do`-`while` statements + +* `break` statements + +* `continue` statements + +* `return` statements + +* `defer` statements + +> #### Note #### +> The `defer` statement in Slang is tied to scope. The deferred statement runs at the end of the scope like in Swift, not just at the end of the function like in Go. +> `defer` supports but does not require block statements: both `defer f();` and `defer { f(); g(); }` are legal. + +> #### Note #### +> Slang does not support the C/C++ `goto` keyword. + +> #### Note #### +> Slang does not support the C++ `throw` keyword. + +Additional statement forms specific to shading languages follow. + +### Discard Statements + +A `discard` statement can be used in the context of a fragment shader to terminate shader execution for the current fragment, and to cause the graphics system to discard the corresponding fragment. + +Functions +--------- + +Slang supports function definitions with traditional C syntax: + +```hlsl +float addSomeThings(int x, float y) +{ + return x + y; +} +``` + +In addition to the traditional C syntax, you can use the modern syntax to define functions with the `func` keyword: +```swift +func addSomeThings(x : int, y : float) -> float +{ + return x + y; +} +``` + +Slang supports overloading of functions based on parameter types. + +Function parameters may be marked with a _direction_ qualifier: + +* `in` (the default) indicates a by-value input parameter +* `out` indicates an output parameter +* `inout` or `in out` indicates an input/output parameter + +> #### Note #### +> The `out` and `inout` directions are superficially similar to non-`const` reference parameters in C++. +> In cases that do not involve aliasing of mutable memory, the semantics should be equivalent. + +Preprocessor +------------ + +Slang supports a C-style preprocessor with the following directives; + +* `#include` +* `#define` +* `#undef` +* `#if`, `#ifdef`, `#ifndef` +* `#else`, `#elif` +* `#endif` +* `#error` +* `#warning` +* `#line` +* `#pragma`, including `#pragma once` + +Variadic macros are supported by the Slang preprocessor. + +> #### Note #### +> The use of `#include` in new code is discouraged as this functionality has +> been superseded by the module system, please refer to +> [Modules and Access Control](04-modules-and-access-control.md) + +Attributes +---------- + +_Attributes_ are a general syntax for decorating declarations and statements with additional semantic information or meta-data. +Attributes are surrounded with square brackets (`[]`) and prefix the declaration or statement they apply to. + +For example, an attribute can indicate the programmer's desire that a loop be unrolled as much as possible: + +```hlsl +[unroll] +for(int i = 0; i < n; i++) +{ /* ... */ } +``` + +> #### Note #### +> Traditionally, all attributes in HLSL used a single layer of `[]` brackets, matching C#. +> Later, C++ borrowed the idea from C# but used two layers of brackets (`[[]]`). +> Some recent extensions to HLSL have used the C++-style double brackets instead of the existing single brackets syntax. +> Slang tries to support both alternatives uniformly. + +Global Variables and Shader Parameters +-------------------------------------- + +By default, global-scope variable declarations in Slang represent _shader parameters_ passed from host application code into GPU code. +Programmers must explicitly mark a global-scope variable with `static` for it not to be treated as a shader parameter, even if the variable is marked `const`: + +```hlsl +// a shader parameter: +float a; + +// also a shader parameter (despite `const`): +const int b = 2; + +// a "thread-local" global variable +static int c = 3; + +// a compile-time constant +static const int d = 4; +``` + +### Global Constants + +A global-scope `static const` variable defines a compile-time constant for use in shader code. + +### Global-Scope Static Variables + +A non-`const` global-scope `static` variable is conceptually similar to a global variable in C/C++, with the key difference that it has distinct storage per *thread* rather than being truly global. +Each logical thread of shader execution initiated by the GPU will be allocated fresh storage for these `static` variables, and values written to those variables will be lost when a shader thread terminates. + +> #### Note #### +> Some target platforms do not support `static` global variables in all use cases. +> Support for `static` global variables should be seen as a legacy feature, and further use is discouraged. + +### Global Shader Parameters + +Global shader parameters may use any type, including both opaque and non-opaque types: + +```hlsl +ConstantBuffer c; +Texture2D t; +float4 color; +``` + +To avoid confusion, the Slang compiler will warn on any global shader parameter that includes non-opaque types, because it is likely that a user thought they were declaring a global constant or a traditional global variable. +This warning may be suppressed by marking the parameter as `uniform`: + +```hlsl +// WARNING: this declares a global shader parameter, not a global variable +int gCounter = 0; + +// OK: +uniform float scaleFactor; +``` + +#### Legacy Constant Buffer Syntax + +For compatibility with existing HLSL code, Slang also supports global-scope `cbuffer` declarations to introduce constant buffers: + +```hlsl +cbuffer PerFrameCB +{ + float4x4 mvp; + float4 skyColor; + // ... +} +``` + +A `cbuffer` declaration like this is semantically equivalent to a shader parameter declared using the `ConstantBuffer` type: + +```hlsl +struct PerFrameData +{ + float4x4 mvp; + float4 skyColor; + // ... +} +ConstantBuffer PerFrameCB; +``` + +#### Explicit Binding Markup + +For compatibility with existing codebases, Slang supports pre-existing markup syntax for associating shader parameters of opaque types with binding information for specific APIs. + +Binding information for Direct3D platforms may be specified using `register` syntax: + +```hlsl +Texture2D a : register(t0); +Texture2D b : register(t1, space0); +``` + +Binding information for Vulkan (and OpenGL) may be specified using `[[vk::binding(...)]]` attributes + +```hlsl +[[vk::binding(0)]] +Texture2D a; + +[[vk::binding(1, 0)]] +Texture2D b; +``` + +A single parameter may use both the D3D-style and Vulkan-style markup, but in each case explicit binding markup only applies to the API family for which it was designed. + +> #### Note #### +> Explicit binding markup is tedious to write and error-prone to maintain. +> It is almost never required in Slang codebases. +> The Slang compiler can automatically synthesize bindings in a completely deterministic fashion and in most cases the bindings it generates are what a programmer would have written manually. + +Shader Entry Points +------------------- + +An _entry point_ is a function that can be used as the starting point for execution of a GPU thread. + +Here is an example of an entry-point function in Slang: + +```hlsl +[shader("vertex")] +float4 vertexMain( + float3 modelPosition : POSITION, + uint vertexID : SV_VertexID, + uniform float4x4 mvp) + : SV_Position +{ /* ... */ } +``` + +In the following sections we will use this example to explain important facets of entry point declarations in Slang. + +### Entry Point Attribute and Stages + +The `[shader(...)]` attribute is used to mark a function in Slang as a shader entry point, and also to specify which pipeline stage it is meant for. +In this example, the `vertexMain` shader indicates that it is meant for the `vertex` stage of the traditional rasterization pipeline. +Rasterization, compute, and ray-tracing pipelines each define their own stages, and new versions of graphics APIs may introduce new stages. + +For compatibility with legacy codebases, Slang supports code that leaves off `[shader(...)]` attributes; in these cases application developers must specify the names and stages for their entry points via explicit command-line or API options. +Such entry points will not be found via `IModule::findEntryPointByName()`. Instead `IModule::findAndCheckEntryPoint()` must be used, and a stage must be specified. +It is recommended that new codebases always use `[shader(...)]` attributes both to simplify their workflow, and to make code more explicit and "self-documenting." + +> #### Note #### +> In GLSL, a file of shader code may only include one entry point, and all code `#include`d into that file must be compatible with the stage of that entry point. By default, GLSL requires that an entry point be called `main`. +> Slang allows for multiple entry points to appear in a file, for any combination of stage, and with any valid identifier as a name. + +### Parameters + +The parameter of an entry-point function represent either _varying_ or _uniform_ inputs. +Varying inputs are those that may vary over threads invoked as part of the same batch (a draw call, compute dispatch, etc.), while uniform inputs are those that are guaranteed to be the same for all threads in a batch. +Entry-point parameters in Slang default to varying, but may be explicitly marked `uniform`. + +If an entry-point function declares a non-`void` result type, then its result behaves like an anonymous `out` parameter that is varying. + +### Binding Semantics + +The varying parameters of an entry point must declare a _binding semantic_ to indicate how those parameters should be connected to the execution environment. +A binding semantic for a parameter may be introduced by suffixing the variable name with a colon (`:`) and an identifier for the chosen binding semantic. +A binding semantic for a function result is introduced similarly, but comes after the parameter list. + +It is not shown in this example, but binding semantics may also be applied to individual `struct` fields, in cases where a varying parameter of `struct` type is used. + +#### System-Defined Binding Semantics + +In the `vertexMain` entry point, the `vertexID` parameter uses the `SV_VertexID` binding semantic, which is a _system-defined_ binding semantic. +Standard system-defined semantics are distinguished by the `SV_` prefix. + +A system-defined binding semantic on an input parameter indicates that the parameter should receive specific data from the GPU as defined by the pipeline and stage being used. +For example, in a vertex shader the `SV_VertexID` binding semantic on an input yields the ID of the particular vertex being processed on the current thread. + +A system-defined binding semantic on an output parameter or function result indicates that when a shader thread returns from the entry point the value stored in that output should be used by the GPU in a specific way defined by the pipeline and stage being used. +For example, in a vertex shader the `SV_Position` binding semantic on an output indicates that it represents a clip-space position that should be communicated to the rasterizer. + +The set of allowed system-defined binding semantics for inputs and outputs depends on the pipeline and stage of an entry point. +Some system-defined binding semantics may only be available on specific targets or specific versions of those targets. + +> #### Note #### +> Instead of using ordinary function parameters with system-defined binding semantics, GLSL uses special system-defined global variables with the `gl_` name prefix. +> Some recent HLSL features have introduced special globally-defined functions that behave similarly to these `gl_` globals. + +#### User-Defined Binding Semantics + +In the `vertexMain` entry point, the `modelPosition` parameter used the `POSITION` binding semantic, which is a _user-defined_ binding semantic. + +A user-defined binding semantic on an input indicates that the parameter should receive data with a matching binding semantic from a preceding stage. +A user-defined binding semantic on an output indicates that the parameter should provide data to a parameter with a matching binding semantic in a following stage. + +Whether or not inputs and outputs with user-defined binding semantics are allowed depends on the pipeline and stage of an entry point. + +Different APIs and different stages within the same API may match up entry point inputs/outputs with user-defined binding semantics in one of two ways: + +* By-index matching: user-defined outputs from one stage and inputs to the next are matched up by order of declaration. The types of matching output/input parameters must either be identical or compatible (according to API-specific rules). Some APIs also require that the binding semantics of matching output/input parameters are identical. + +* By-name matching: user-defined outputs from one stage and inputs to the next are matched up by their binding semantics. The types of matching output/input parameters must either be identical or compatible (according to API-specific rules). The order of declaration of the parameters need not match. + +Because the matching policy may differ across APIs, the only completely safe option is for parameters passed between pipeline stages to match in terms of order, type, *and* binding semantic. + +> #### Note #### +> Instead of using ordinary function parameters for user-defined varying inputs/outputs, GLSL uses global-scope variable declarations marked with the `in` or `out` modifier. + +### Entry-Point Uniform Parameters + +In the `vertexMain` entry point, the `mvp` parameter is an _entry-point uniform parameter_. + +Entry-point uniform parameters are semantically similar to global-scope shader parameters, but do not pollute the global scope. + +> #### Note #### +> GLSL does not support entry-point `uniform` parameters; all shader parameters must be declared at the global scope. +> Historically, HLSL has supported entry-point `uniform` parameters, but this feature was dropped by recent compilers. + +Mixed Shader Entry Points +-------------------------- + +Through the `[shader(...)]` syntax, users of slang can freely combine multiple entry points into the same file. This can be especially convenient for reuse between entry points which have a logical connection. + +For example, mixed entry points offer a convenient way for ray tracing applications to concisely define a complete pipeline in one source file, while also providing users with additional opportunities to improve type safety of +shared structure definitions: + +```hlsl +struct Payload { float3 color; }; + +[shader("raygeneration")] +void rayGenerationProgram() { + Payload payload; + TraceRay(/*...*/, payload); + /* ... */ +} + +[shader("closesthit")] +void closestHitProgram(out Payload payload) { + payload.color = {1.0}; +} + +[shader("miss")] +void missProgram(out Payload payload) { + payload.color = {1.0}; +} +``` + +> #### Note #### +> GLSL does not support multiple entry-points; however, SPIR-V does. Vulkan users wanting to take advantage of Slang mixed entry points must pass `-fvk-use-entrypoint-name` and `-emit-spirv-directly` as compiler arguments. + +### Mixed Entry-Point Uniform Parameters + +Like with the previous `vertexMain` example, mixed entry point setups also support _entry-point uniform parameters_. + +However, because of certain systematic differences between entry point types, a uniform being _global_ or _local_ will have very important consequences on the underlying layout and behavior. + +For most all entry point types, D3D12 will use one common root signature to define both global and local uniform parameters. +Likewise, Vulkan descriptors will bind to a common pipeline layout. For both of these cases, Slang maps uniforms to the common root signature / pipeline layout. + +However, for ray tracing entry points and D3D12, these parameters map to either _global_ root signatures or to _local_ root signatures, with the latter being stored in the shader binding table. +In Vulkan, D3D12's global root signatures translate to a shared ray tracing pipeline layout, while local root signatures map again to shader binding table records. + +When entry points match a "ray tracing" type, we bind uniforms which are in the _global_ scope to the _global_ root signature (or ray tracing pipeline layout), while uniforms which are _local_ are bound to shader binding table records, which depend on the underlying runtime record indexing. + +Consider the following: + +```hlsl +uniform float3 globalUniform; + +[shader("compute")][numThreads(1,2,3)] +void computeMain1(uniform float3 localUniform1) +{ /* ... */ } + +[shader("compute")][numThreads(1,2,3)] +void computeMain2(uniform float3 localUniform2) +{ /* ... */ } + +[shader("raygeneration")] +void rayGenerationMain(uniform float3 localUniform3) +{ /* ... */ } + +[shader("closesthit")] +void closestHitMain(uniform float3 localUniform4) +{ /* ... */ } +``` + +In this example, `globalUniform` is appended to the global root signature / pipeline layouts for _both_ compute _and_ ray generation stages for all four entry points. +Compute entry points lack "local root signatures" in D3D12, and likewise Vulkan has no concept of "local" vs "global" compute pipeline layouts, so `localUniform1` is "pushed" to the stack of reserved global uniform parameters for use in `computeMain1`. +Leaving that entry point scope "pops" that global uniform parameter such that `localUniform2` can reuse the same binding location for `computeMain2`. +However, local uniforms for ray tracing shaders map to the corresponding "local" hit records in the shader binding table, and so no "push" or "pop" to the global root signature / pipeline layouts occurs for these parameters. + +Auto-Generated Constructors +---------- + +### Auto-Generated Constructors - Struct + +Slang has the following rules: +1. Auto-generate a `__init()` if not already defined. + + Assume: + ```csharp + struct DontGenerateCtor + { + int a; + int b = 5; + + // Since the user has explicitly defined a constructor + // here, Slang will not synthesize a conflicting + // constructor. + __init() + { + // b = 5; + a = 5; + b = 6; + } + }; + + struct GenerateCtor + { + int a; + int b = 5; + + // Slang will automatically generate an implicit constructor: + // __init() + // { + // b = 5; + // } + }; + ``` + +2. If all members have equal visibility, auto-generate a 'member-wise constructor' if not conflicting with a user defined constructor. + ```csharp + struct GenerateCtorInner + { + int a; + + // Slang will automatically generate an implicit + // __init(int in_a) + // { + // a = in_a; + // } + }; + struct GenerateCtor : GenerateCtorInner + { + int b; + int c = 5; + + // Slang will automatically generate an implicit + // __init(int in_a, int in_b, int in_c) + // { + // c = 5; + // + // this = GenerateCtorInner(in_a); + // + // b = in_b; + // c = in_c; + // } + }; + ``` + +3. If not all members have equal visibility, auto-generate a 'member-wise constructor' based on member visibility if not conflicting with a user defined constructor. + + We generate 3 different visibilities of 'member-wise constructor's in order: + 1. `public` 'member-wise constructor' + - Contains members of visibility: `public` + - Do not generate if `internal` or `private` member lacks an init expression + 2. `internal` 'member-wise constructor' + - Contains members of visibility: `internal`, `public` + - Do not generate if `private` member lacks an init expression + 3. `private` 'member-wise constructor' + - Contains members of visibility: `private`, `internal`, `public` + + ```csharp + struct GenerateCtorInner1 + { + internal int a = 0; + + // Slang will automatically generate an implicit + // internal __init(int in_a) + // { + // a = 0; + // + // a = in_a; + // } + }; + struct GenerateCtor1 : GenerateCtorInner1 + { + internal int b = 0; + public int c; + + // Slang will automatically generate an implicit + // internal __init(int in_a, int in_b, int in_c) + // { + // b = 0; + // + // this = GenerateCtorInner1(in_a); + // + // b = in_b; + // c = in_c; + // } + // + // public __init(int in_c) + // { + // b = 0; + // + // this = GenerateCtorInner1(); + // + // c = in_c; + // } + }; + + struct GenerateCtorInner2 + { + internal int a; + // Slang will automatically generate an implicit + // internal __init(int in_a) + // { + // a = in_a; + // } + }; + struct GenerateCtor2 : GenerateCtorInner2 + { + internal int b; + public int c; + + /// Note: `internal b` is missing init expression, + // Do not generate a `public` 'member-wise' constructor. + + // Slang will automatically generate an implicit + // internal __init(int in_a, int in_b, int in_c) + // { + // this = GenerateCtorInner2(in_a); + // + // b = in_b; + // c = in_c; + // } + }; + ``` + +Initializer Lists +---------- +Initializer Lists are an expression of the form `{...}`. + +```csharp +int myFunc() +{ + int a = {}; // Initializer List +} +``` + +### Initializer Lists - Scalar + +```csharp +// Equivalent to `int a = 1` +int a = {1}; +``` + +### Initializer Lists - Vectors + +```csharp +// Equivalent to `float3 a = float3(1,2,3)` +float3 a = {1, 2, 3}; +``` + +### Initializer Lists - Arrays/Matrices + +#### Array Of Scalars + +```csharp +// Equivalent to `int[2] a; a[0] = 1; a[1] = 2;` +int a[2] = {1, 2} +``` + +#### Array Of Aggregates + +```csharp +// Equivalent to `float3 a[2]; a[0] = {1,2,3}; b[1] = {4,5,6};` +float3 a[2] = { {1,2,3}, {4,5,6} }; +``` + +#### Flattened Array Initializer + +```csharp +// Equivalent to `float3 a[2] = { {1,2,3}, {4,5,6} };` +float3 a[3] = {1,2,3, 4,5,6}; +``` + +### Initializer Lists - Struct + +In most scenarios, using an initializer list to create a struct typed value is equivalent to calling the struct's constructor using the elements in the initializer list as arguments for the constructor, for example: +```csharp +struct GenerateCtorInner1 +{ + internal int a = 0; + + // Slang will automatically generate an implicit + // internal __init(int in_a) + // { + // a = 0; + // + // a = in_a; + // } + + static GenerateCtorInner1 callGenerateCtorInner1() + { + // Calls `GenerateCtorInner1::__init(1);` + return {1}; + } +}; +struct GenerateCtor1 : GenerateCtorInner1 +{ + internal int b = 0; + public int c; + + // Slang will automatically generate an implicit + // internal __init(int in_a, int in_b, int in_c) + // { + // this = GenerateCtorInner1(in_a); + // + // b = 0; + // + // b = in_b; + // c = in_c; + // } + // + // public __init(int in_c) + // { + // this = GenerateCtorInner1(); + // + // b = 0; + // + // c = in_c; + // } + static GenerateCtorInner1 callInternalGenerateCtor() + { + // Calls `GenerateCtor1::__init(1, 2, 3);` + return {1, 2, 3}; + } + static GenerateCtorInner1 callPublicGenerateCtor() + { + // Calls `GenerateCtor1::__init(1);` + return {1}; + } +}; + +... + +// Calls `{ GenerateCtor1::__init(3), GenerateCtor1::__init(2) }` +GenerateCtor1 val[2] = { { 3 }, { 2 } }; +``` + +In addition, Slang also provides compatibility support for C-style initializer lists with `struct`s. C-style initializer lists can use [Partial Initializer List's](#Partial-Initializer-Lists) and [Flattened Array Initializer With Struct's](#Flattened-Array-Initializer-With-Structs) + +A struct is considered a C-style struct if: +1. User never defines a custom constructor with **more than** 0 parameters +2. All member variables in a `struct` have the same visibility (`public` or `internal` or `private`). + +#### Partial Initializer List's + +```csharp +struct Foo +{ + int a; + int b; + int c; +}; + +... + +// Equivalent to `Foo val; val.a = 1; val.b = 0; val.c = 0;` +Foo val = {1}; + +// Equivalent to `Foo val; val.a = 2; val.b = 3; val.c = 0;` +Foo val = {2, 3}; +``` + +#### Flattened Array Initializer With Struct's + +```csharp +struct Foo +{ + int a; + int b; + int c; +}; + +... + +// Equivalent to `Foo val[2] = { {0,1,2}, {3,4,5} };` +Foo val[2] = {0,1,2, 3,4,5}; +``` + + +### Initializer Lists - Default Initializer + +`{}` will default initialize a value: + +#### Non-Struct Type + +Value will zero-initialize +```csharp +// Equivalent to `int val1 = 0;` +int val1 = {}; + +// Equivalent to `float3 val2 = float3(0);` +float3 val2 = {}; +``` + +#### Struct Type + +1. Attempt to call default constructor (`__init()`) of a `struct` + + ```csharp + struct Foo + { + int a; + int b; + __init() + { + a = 5; + b = 5; + } + }; + + ... + + // Equivalent to `Foo val = Foo();` + Foo val = {}; + ``` + +2. As a fallback, zero-initialize the struct + + ```csharp + struct Foo + { + int a; + int b; + }; + + ... + + // Equivalent to `Foo val; val.a = 0; val.b = 0;` + Foo val = {}; + ``` + +### Initializer Lists - Other features + +Slang allows calling a default-initializer inside a default-constructor. + +```c# +__init() +{ + this = {}; //zero-initialize `this` +} +``` diff --git a/lib/All/slang/share/doc/slang/user-guide/03-convenience-features.md b/lib/All/slang/share/doc/slang/user-guide/03-convenience-features.md new file mode 100644 index 0000000..4e1a12c --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/03-convenience-features.md @@ -0,0 +1,1015 @@ +--- +layout: user-guide +permalink: /user-guide/convenience-features +--- + +# Basic Convenience Features + +This topic covers a series of nice-to-have language features in Slang. These features are not supported by HLSL but are introduced to Slang to simplify code development. Many of these features are added to Slang per request of our users. + +## Type Inference in Variable Definitions +Slang supports automatic variable type inference: +```csharp +var a = 1; // OK, `a` is an `int`. +var b = float3(0, 1, 2); // OK, `b` is a `float3`. +``` +Automatic type inference requires an initialization expression to be present. Without an initial value, the compiler is not able to infer the type of the variable. The following code will result in a compiler error: +```csharp +var a; // Error, cannot infer the type of `a`. +``` + +You may use the `var` keyword to define a variable in a modern syntax: +```csharp +var a : int = 1; // OK. +var b : int; // OK. +``` + +## Immutable Values +The `var` syntax and the traditional C-style variable definition introduce a _mutable_ variable whose value can be changed after its definition. If you wish to introduce an immutable or constant value, you may use the `let` keyword: +```rust +let a = 5; // OK, `a` is `int`. +let b : int = 5; // OK. +``` +Attempting to change an immutable value will result in a compiler error: +```rust +let a = 5; +a = 6; // Error, `a` is immutable. +``` + + +## Namespaces + +You can use the `namespace` syntax to define symbols in a namespace: +```csharp +namespace ns +{ + int f(); +} +``` + +Slang also supports the abbreviated syntax for defining nested namespaces: +```csharp +namespace ns1.ns2 +{ + int f(); +} +// equivalent to: +namespace ns1::ns2 +{ + int f(); +} +// equivalent to: +namespace ns1 +{ + namespace ns2 + { + int f(); + } +} +``` + +To access symbols defined in a namespace, you can use their qualified name with namespace prefixes: +```csharp +void test() +{ + ns1.ns2.f(); + ns1::ns2::f(); // equivalent syntax. +} +``` + +Symbols defined in the same namespace can access each other without a qualified name, this is true even if the referenced symbol is defined in a different file or module: +```csharp +namespace ns +{ + int f(); + int g() { f(); } // OK. +} +``` + +You can also use the `using` keyword to pull symbols defined in a different namespace to +the current scope, removing the requirement for using fully qualified names. +```cpp +namespace ns1.ns2 +{ + int f(); +} + +using ns1.ns2; +// or: +using namespace ns1.ns2; // alternative syntax. + +void test() { f(); } // OK. +``` + +## Member functions + +Slang supports defining member functions in `struct`s. For example, it is allowed to write: + +```hlsl +struct Foo +{ + int compute(int a, int b) + { + return a + b; + } +} +``` + +You can use the `.` syntax to invoke member functions: + +```hlsl +Foo foo; +int rs = foo.compute(1,2); +``` + +Slang also supports static member functions, For example: +``` +struct Foo +{ + static int staticMethod(int a, int b) + { + return a + b; + } +} +``` + +Static member functions are accessed the same way as other static members, via either the type name or an instance of the type: + +```hlsl +int rs = Foo.staticMethod(a, b); +``` + +or + +```hlsl +Foo foo; +... +int rs = foo.staticMethod(a,b); +``` + +### Mutability of member function + +For GPU performance considerations, the `this` argument in a member function is immutable by default. Attempting to modify `this` will result in a compile error. If you intend to define a member function that mutates the object, use `[mutating]` attribute on the member function as shown in the following example. + +```hlsl +struct Foo +{ + int count; + + [mutating] + void setCount(int x) { count = x; } + + // This would fail to compile. + // void setCount2(int x) { count = x; } +} + +void test() +{ + Foo f; + f.setCount(1); // Compiles +} +``` + +## Properties + +Properties provide a convenient way to access values exposed by a type, where the logic behind accessing the value is defined in `getter` and `setter` function pairs. Slang's `property` feature is similar to C# and Swift. +```csharp +struct MyType +{ + uint flag; + + property uint highBits + { + get { return flag >> 16; } + set { flag = (flag & 0xFF) + (newValue << 16); } + } +}; +``` + +Or equivalently in a "modern" syntax: + +```csharp +struct MyType +{ + uint flag; + + property highBits : uint + { + get { return flag >> 16; } + set { flag = (flag & 0xFF) + (newValue << 16); } + } +}; +``` + +You may also use an explicit parameter for the setter method: +```csharp +property uint highBits +{ + set(uint x) { flag = (flag & 0xFF) + (x << 16); } +} +``` + +> #### Note #### +> Slang currently does not support automatically synthesized `getter` and `setter` methods. For example, +> the following code is not supported: +> ``` +> property uint highBits {get;set;} // Not supported yet. +> ``` + +## Initializers + +### Constructors +> #### Note #### +> The syntax for defining constructors is subject to future change. + + +Slang supports defining constructors in `struct` types. You can write: +```csharp +struct MyType +{ + int myVal; + __init(int a, int b) + { + myVal = a + b; + } +} +``` + +You can use a constructor to construct a new instance by using the type name in a function call expression: +```csharp +MyType instance = MyType(1,2); // instance.myVal is 3. +``` + +You may also use C++ style initializer list to invoke a constructor: +```csharp +MyType instance = {1, 2}; +``` + +If a constructor does not define any parameters, it will be recognized as *default* constructor that will be automatically called at the definition of a variable: + +```csharp +struct MyType +{ + int myVal; + __init() + { + myVal = 10; + } +}; + +int test() +{ + MyType test; + return test.myVal; // returns 10. +} +``` + +Slang will also implicitly call a *default* constructor of all parents of a derived struct (same as C++): +```csharp +struct MyType_Base +{ + int myVal1; + __init() {myVal1 = 22;} +} + +struct MyType1 : MyType_Base +{ + int myVal2; + __init() + { + // implicitly calls `MyType_Base::__init()` + myVal2 = 15; + } +} +testMyType1() +{ + MyType1 a; + // a.myVal1 == 22 + // a.myVal2 == 15 +} + +struct MyType2 : MyType_Base +{ +} +testMyType2() +{ + MyType2 b; // implicitly calls `MyType_Base::__init()` + // b.myVal1 == 22 +} +``` + +### Member Init Expressions + +Slang supports member init expressions: +```csharp +struct MyType +{ + int myVal = 5; +} +``` + +## Operator Overloading + +Slang allows defining operator overloads as global methods: +```csharp +struct MyType +{ + int val; + __init(int x) { val = x; } +} + +MyType operator+(MyType a, MyType b) +{ + return MyType(a.val + b.val); +} + +int test() +{ + MyType rs = MyType(1) + MyType(2); + return rs.val; // returns 3. +} +``` +Slang currently supports overloading the following operators: `+`, `-`, `*`, `/`, `%`, `&`, `|`, `<`, `>`, `<=`, `>=`, `==`, `!=`, unary `-`, `~` and `!`. Please note that the `&&` and `||` operators are not supported. + +In addition, you can overload operator `()` as a member method: +```csharp +struct MyFunctor +{ + int operator()(float v) + { + // ... + } +} +void test() +{ + MyFunctor f; + int x = f(1.0f); // calls MyFunctor::operator(). + int y = f.operator()(1.0f); // explicitly calling operator(). +} +``` + +## Subscript Operator + +Slang allows overriding `operator[]` with `__subscript` syntax: +```csharp +struct MyType +{ + int val[12]; + __subscript(int x, int y) -> int + { + get { return val[x*3 + y]; } + set { val[x*3+y] = newValue; } + } +} +int test() +{ + MyType rs; + rs[0, 0] = 1; + rs[1, 0] = rs[0, 0] + 1; + return rs[1, 0]; // returns 2. +} +``` + +## Tuple Types + +Tuple types can hold collection of values of different types. +Tuples types are defined in Slang with the `Tuple<...>` syntax, and +constructed with either a constructor or the `makeTuple` function: +```csharp +Tuple t0 = Tuple(5, 2.0f, false); +Tuple t1 = makeTuple(3, 1.0f, true); +``` + +Tuple elements can be accessed with `_0`, `_1` member names: +```csharp +int i = t0._0; // 5 +bool b = t1._2; // true +``` + +You can use the swizzle syntax similar to vectors and matrices to form new +tuples: + +```csharp +t0._0_0_1 // evaluates to (5, 5, 2.0f) +``` + +You can concatenate two tuples: + +```csharp +concat(t0, t1) // evaluates to (5, 2.0f, false, 3, 1.0f, true) +``` + +If all element types of a tuple conforms to `IComparable`, then the tuple itself +will conform to `IComparable`, and you can use comparison operators on the tuples +to compare them: + +```csharp +let cmp = t0 < t1; // false +``` + +You can use `countof()` on a tuple type or a tuple value to obtain the number of +elements in a tuple. This is considered a compile-time constant. +```csharp +int n = countof(Tuple); // 2 +int n1 = countof(makeTuple(1,2,3)); // 3 +``` + +All tuple types will be translated to `struct` types, and receive the same layout +as `struct` types. + +## `Optional` type + +Slang supports the `Optional` type to represent a value that may not exist. +The dedicated `none` value can be used for any `Optional` to represent no value. +`Optional::value` property can be used to retrieve the value. + +```csharp +struct MyType +{ + int val; +} + +int useVal(Optional p) +{ + if (p == none) // Equivalent to `!p.hasValue` + return 0; + return p.value.val; +} + +int caller() +{ + MyType v; + v.val = 0; + useVal(v); // OK to pass `MyType` to `Optional`. + useVal(none); // OK to pass `none` to `Optional`. + return 0; +} +``` + +## `Conditional` Type + +A `Conditional` type can be used to define struct fields that can be specialized away. If `condition` is `false`, the field will be removed +by the compiler from the target code. This is useful for scenarios where a developer would like to make sure a field is not defined in a +specialized shader variant when it is not used by the shader. + +For example, a common use case is to define the vertex shader output / fragment shader input: + +```slang +interface IVertex +{ + property float3 position{get;} + property Optional normal{get;} + property Optional color{get;} +} + +struct Vertex : IVertex +{ + private float3 m_position; + private Conditional m_normal; + private Conditional m_color; + + __init(float3 position, float3 normal, float3 color) + { + m_position = position; + m_normal = normal; + m_color = color; + } + + property float3 position + { + get { return m_position; } + } + property Optional normal + { + get { return m_normal; } + } + property Optional color + { + get { return m_color; } + } +} +``` + +In this example, `Vertex` type is parameterized on `hasNormal` and `hasColor`. If `hasNormal` is false, the `m_normal` field will be eliminated in the target code, allowing a specialized vertex shader to declare minimum output fields. For example, a vertex shader +can be defined as follows: + +```slang +[shader("vertex")] +Vertex vertMain(VertexIn inputVertex) +{ + ... +} +``` + + +## `if_let` syntax +Slang supports `if (let name = expr)` syntax to simplify the code when working with `Optional` or `Conditional` value. The syntax is similar to Rust's +`if let` syntax, the value expression must be an `Optional` or `Conditional` type, for example: + +```csharp +Optional getOptInt() { ... } + +void test() +{ + if (let x = getOptInt()) + { + // if we are here, `getOptInt` returns a value `int`. + // and `x` represents the `int` value. + } +} +``` + +## `reinterpret` operation + +Sometimes it is useful to reinterpret the bits of one type as another type, for example: +```csharp +struct MyType +{ + int a; + float2 b; + uint c; +} + +MyType myVal; +float4 myPackedVector = packMyTypeToFloat4(myVal); +``` + +The `packMyTypeToFloat4` function is usually implemented by bit casting each field in the source type and assigning it into the corresponding field in the target type, +by calling `intAsFloat`, `floatAsInt` and using bit operations to shift things in the right place. +Instead of writing `packMyTypeToFloat4` function yourself, you can use Slang's built-in `reinterpret` to do just that for you: +``` +float4 myPackedVector = reinterpret(myVal); +``` + +`reinterpret` can pack any type into any other type as long as the target type is no smaller than the source type. + +## Pointers (limited) + +Slang supports pointers when generating code for SPIRV, C++ and CUDA targets. The syntax for pointers is similar to C, with the exception that operator `.` can also be used to dereference a member from a pointer. For example: +```csharp +struct MyType +{ + int a; +}; + +int test(MyType* pObj) +{ + MyType* pNext = pObj + 1; + MyType* pNext2 = &pNext[1]; + return pNext.a + pNext->a + (*pNext2).a + pNext2[0].a; +} + +cbuffer Constants +{ + MyType *ptr; +}; + +int validTest() +{ + return test(ptr); +} + +int invalidTest() +{ + // cannot produce a pointer from a local variable + MyType obj; + return test(&obj); // !! ERROR !! +} +``` + +Pointer types can also be specified using the generic syntax +`Ptr`. The generic syntax allows +declaring pointers to read-only and immutable values, and pointers to address spaces other than +`Device`. Pointers to immutable values can also be declared with type alias +`ImmutablePtr`. `Ptr` is equivalent to `MyType*`. + +### Limitations + +- Slang supports pointers to global and shared memory but not local memory. It is invalid to define a pointer to a local variable. + +- Slang supports pointers that are defined as shader parameters (e.g. as a constant buffer field). + +- Slang can produce pointers using the & operator from data in global memory. + +- Slang doesn't support forming pointers to opaque handle types, e.g. `Texture2D`. For handle pointers, use `DescriptorHandle` instead. + +- Slang doesn't support custom alignment specification. Functions + `loadAligned()` and `storeAligned()` may be used for loads and stores using pointers with known alignment. + +- Slang currently does not support `const` pointers. + +## `DescriptorHandle` for Bindless Descriptor Access + +Slang supports the `DescriptorHandle` type that represents a bindless handle to a resource. This feature provides a portable way of implementing +the bindless resource idiom. When targeting HLSL, GLSL and SPIRV where descriptor types (e.g. textures, samplers and buffers) are opaque handles, +`DescriptorHandle` will translate into a `uint2` so it can be defined in any memory location. The underlying `uint2` value is treated as an index +to access the global descriptor heap or resource array in order to obtain the actual resource handle. On targets with where resource handles +are not opaque handles, `DescriptorHandle` maps to `T` and will have the same size and alignment defined by the target. + +`DescriptorHandle` is declared as: +```slang +struct DescriptorHandle where T:IOpaqueDescriptor {} +``` +where `IOpaqueDescriptor` is an interface implemented by all resource types, including textures, +`ConstantBuffer`, `RaytracingAccelerationStructure`, `SamplerState`, `SamplerComparisonState` and all types of `StructuredBuffer`. + +You may also write `Texture2D.Handle` as a short-hand of `DescriptorHandle`. + +`DescriptorHandle` supports `operator *`, `operator ->`, and can implicitly convert to `T`, for example: + +```slang +uniform StructuredBuffer> textures; +uniform int textureIndex; + +// define a descriptor handle using builtin convenience typealias: +uniform StructuredBuffer.Handle output; + +[numthreads(1,1,1)] +void main() +{ + output[0] = textures[textureIndex].Load(int3(0)); + + // Alternatively, this syntax is also valid: + (*output)[0] = textures[textureIndex]->Load(int3(0)); +} +``` + +By default, when targeting HLSL, `DescriptorHandle` translates to uses of `ResourceDescriptorHeap[index]` and `SamplerDescriptorHeap[index]`. +In particular, when combined with combined texture sampler types (e.g. `Sampler2D`), Slang will fetch the texture using the first +component of the handle, and the sampler state from the second component of the handle. For example: + +``` +uniform DescriptorHandle s; +void test() +{ + s.Sample(uv); +} +``` + +translates to: + +```hlsl +uniform uint2 s; +void test() +{ + Texture2D(ResourceDescriptorHeap[s.x]).Sample( + SamplerState(SamplerDescriptorHeap[s.y]), + uv + ); +} +``` + +When targeting SPIRV, Slang will introduce a global array of descriptors and fetch from the global array. +The descriptor set ID of the global descriptor array can be configured with the `-bindless-space-index` +(or `CompilerOptionName::BindlessSpaceIndex` when using the API) option. + +Default behavior assigns binding-indicies based on descriptor types: + +| Enum Value | Vulkan Descriptor Type | Binding Index | +|------------------------|-------------------------------------------|---------------| +| Sampler | VK_DESCRIPTOR_TYPE_SAMPLER | 0 | +| CombinedTextureSampler | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER | 1 | +| Texture_Read | VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE | 2 | +| Texture_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_IMAGE | 2 | +| TexelBuffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER | 2 | +| TexelBuffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER | 2 | +| Buffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER | 2 | +| Buffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_BUFFER | 2 | +| Unknown | Other | 3 | + +> `ACCELERATION_STRUCTURE` is excluded from the list of types since Slang by default uses the handle to a `RaytracingAccelerationStructure` as a GPU address, casting the handle to a `RaytracingAccelerationStructure`. This removes the need for a binding-slot of `RaytracingAccelerationStructure`. + +> #### Note +> The default implementation for SPIRV may change in the future if SPIRV is extended to provide what is +> equivalent to D3D's `ResourceDescriptorHeap` construct. + +Users can override the default behavior of convering from bindless handle to resource handle, by providing a +`getDescriptorFromHandle` in user code. For example: + +```slang +// All texture and buffer handles are defined in descriptor set 100. +[vk::binding(0, 100)] +__DynamicResource<__DynamicResourceKind.General> resourceHandles[]; + +// All sampler handles are defined in descriptor set 101. +[vk::binding(0, 101)] +__DynamicResource<__DynamicResourceKind.Sampler> samplerHandles[]; + +export T getDescriptorFromHandle(DescriptorHandle handle) where T : IOpaqueDescriptor +{ + __target_switch + { + case spirv: + if (T.kind == DescriptorKind.Sampler) + return samplerHandles[((uint2)handle).x].asOpaqueDescriptor(); + else + return resourceHandles[((uint2)handle).x].asOpaqueDescriptor(); + default: + return defaultGetDescriptorFromHandle(handle); + } +} +``` + +Note that the `getDescriptorFromHandle` is not supposed to be called from the user code directly, +it will be automatically called by the compiler to dereference a `DescriptorHandle` to get `T`. +Think about providing `getDescriptorFromHandle` as a way to override `operator->` for `DescriptorHandle`. + +The `IOpaqueDescriptor` interface is defined as: + +```slang +interface IOpaqueDescriptor +{ + /// The kind of the descriptor. + static const DescriptorKind kind; + static const DescriptorAccess descriptorAccess; +} +``` + +The user can call `defaultGetDescriptorFromHandle` function from their implementation of +`getDescriptorFromHandle` to dispatch to the default behavior. + +Additionally, `defaultGetDescriptorFromHandle()` takes an optional argument whose type is `constexpr BindlessDescriptorOptions`. This parameter allows to specify alternative standard presets for how bindless-indexes are assigned. Note that this is currently only relevant to SPIRV: + ```slang +public enum BindlessDescriptorOptions +{ + None = 0, /// Bind assuming regular binding model rules. + VkMutable = 1, /// **Current Default** Bind assuming `VK_EXT_mutable_descriptor_type` +} + ``` + +`None` provides the following bindings for descriptor types: + +| Enum Value | Vulkan Descriptor Type | Binding Index | +|------------------------|-------------------------------------------|---------------| +| Sampler | VK_DESCRIPTOR_TYPE_SAMPLER | 0 | +| CombinedTextureSampler | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER | 1 | +| Texture_Read | VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE | 2 | +| Texture_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_IMAGE | 3 | +| TexelBuffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER | 4 | +| TexelBuffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER | 5 | +| Buffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER | 6 | +| Buffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_BUFFER | 7 | +| Unknown | Other | 8 | + +`VkMutable` provides the following bindings for descriptor types: + +| Enum Value | Vulkan Descriptor Type | Binding Index | +|------------------------|-------------------------------------------|---------------| +| Sampler | VK_DESCRIPTOR_TYPE_SAMPLER | 0 | +| CombinedTextureSampler | VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER | 1 | +| Texture_Read | VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE | 2 | +| Texture_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_IMAGE | 2 | +| TexelBuffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER | 2 | +| TexelBuffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER | 2 | +| Buffer_Read | VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER | 2 | +| Buffer_ReadWrite | VK_DESCRIPTOR_TYPE_STORAGE_BUFFER | 2 | +| Unknown | Other | 3 | + +The `kind` and `descriptorAccess` constants allows user code to fetch resources from different locations depending on the type and access of the resource being requested. The `DescriptorKind` and +`DescriptorAccess` enums are defined as: + +```slang +enum DescriptorKind +{ + Unknown, /// Unknown descriptor kind. + Texture, /// A texture descriptor. + CombinedTextureSampler, /// A combined texture and sampler state descriptor. + Buffer, /// A buffer descriptor. + Sampler, /// A sampler state descriptor. + AccelerationStructure, /// A ray tracing acceleration structure descriptor. + TexelBuffer /// A texel buffer descriptor. +} + +enum DescriptorAccess +{ + Unknown = -1, + Read = 0, + Write = 1, + ReadWrite = 2, + RasterizerOrdered = 3, + Feedback = 4, +} +``` + +By default, the value of a `DescriptorHandle` object is assumed to be dynamically uniform across all +execution threads. If this is not the case, the user is required to mark the `DescriptorHandle` as `nonuniform` +*immediately* before dereferencing it: +```slang +void test(DescriptorHandle t) +{ + nonuniform(t)->Sample(...); +} +``` + +If the resource pointer value is not uniform and `nonuniform` is not called, the result may be +undefined. + + + +Extensions +-------------------- +Slang allows defining additional methods for a type outside its initial definition. For example, suppose we already have a type defined: + +```csharp +struct MyType +{ + int field; + int get() { return field; } +} +``` + +You can extend `MyType` with new method members: +```csharp +extension MyType +{ + float getNewField() { return newField; } +} +``` + +All locations that sees the definition of the `extension` can access the new members: + +```csharp +void test() +{ + MyType t; + float val = t.getNewField(); +} +``` + +This feature is similar to extensions in Swift and extension methods in C#. + +> #### Note: +> You can only extend a type with additional methods. Extending with additional data fields is not allowed. + +Multi-level break +------------------- + +Slang allows `break` statements with a label to jump into any ancestor control flow break points, and not just the immediate parent. +Example: +``` +outer: +for (int i = 0; i < 5; i++) +{ + inner: + for (int j = 0; j < 10; j++) + { + if (someCondition) + break outer; + } +} +``` + +Force inlining +----------------- +Most of the downstream shader compilers will inline all the function calls. However you can instruct Slang compiler to do the inlining +by using the `[ForceInline]` decoration: +``` +[ForceInline] +int f(int x) { return x + 1; } +``` + +Error handling +----------------- + +Slang supports an error handling mechanism that is superficially similar to +exceptions in many other languages, but has some unique characteristics. + +In contrast to C++ exceptions, this mechanism makes the control flow of errors +more explicit, and the performance charasteristics are similar to adding an +if-statement after every potentially throwing function call to check and handle +the error. + +In order to be able to throw an error, a function must declare the type of that +error with `throws`: +``` +enum MyError +{ + Failure, + CatastrophicFailure +} + +int f() throws MyError +{ + if (computerIsBroken()) + throw MyError.CatastrophicFailure; + return 42; +} +``` +Currently, functions may only throw a single type of error. + +To call a function that may throw, you must prepend it with `try`: + +``` +let result = try f(); +``` + +If you don't catch the `try`, related errors are re-thrown and the calling +function must declare that it `throws` that error type: + +``` +void g() throws MyError +{ + // This would not compile if `g()` wasn't declared to throw MyError as well. + let result = try f(); + printf("Success: %d\n", result); +} +``` + +To catch an error, you can use a `do-catch` statement: + +``` +void g() +{ + do + { + let result = try f(); + printf("Success: %d\n", result); + } + catch(err: MyError) + { + printf("Not good!\n"); + } +} +``` + +You can chain multiple catch statements for different types of errors. + +Special Scoping Syntax +------------------- +Slang supports three special scoping syntax to allow users to mix in custom decorators and content in the shader code. These constructs allow a rendering engine to define custom meta-data in the shader, or map engine-specific block syntax to a meaningful block that is understood by the compiler via proper `#define`s. + +### `__ignored_block` +An ignored block will be parsed and ignored by the compiler: +``` +__ignored_block +{ + arbitrary content in the source file, + will be ignored by the compiler as if it is a comment. + Can have nested {} here. +} +``` + +### `__transparent_block` +Symbols defined in a transparent block will be treated as if they are defined +in the parent scope: +```csharp +struct MyType +{ + __transparent_block + { + int myFunc() { return 0; } + } +} +``` +Is equivalent to: +```csharp +struct MyType +{ + int myFunc() { return 0; } +} +``` + +### `__file_decl` +Symbols defined in a `__file_decl` will be treated as if they are defined in +the global scope. However, symbols defined in different `__file_decl`s is not visible +to each other. For example: +```csharp +__file_decl +{ + void f1() + { + } +} +__file_decl +{ + void f2() + { + f1(); // error: f1 is not visible from here. + } +} +``` + +User Defined Attributes (Experimental) +------------------- + +In addition to many system defined attributes, users can define their own custom attribute types to be used in the `[UserDefinedAttribute(args...)]` syntax. The following example shows how to define a custom attribute type. + +```csharp +[__AttributeUsage(_AttributeTargets.Var)] +struct MaxValueAttribute +{ + int value; + string description; +}; + +[MaxValue(12, "the scale factor")] +uniform int scaleFactor; +``` + +In the above code, the `MaxValueAttribute` struct type is decorated with the `[__AttributeUsage]` attribute, which informs that `MaxValueAttribute` type should be interpreted as a definition for a user-defined attribute, `[MaxValue]`, that can be used to decorate all variables or fields. The members of the struct defines the argument list for the attribute. + +The `scaleFactor` uniform parameter is declared with the user defined `[MaxValue]` attribute, providing two arguments for `value` and `description`. + +The `_AttributeTargets` enum is used to restrict the type of decls the attribute can apply. Possible values of `_AttributeTargets` can be `Function`, `Param`, `Struct` or `Var`. + +The usage of user-defined attributes can be queried via Slang's reflection API through `TypeReflection` or `VariableReflection`'s `getUserAttributeCount`, `getUserAttributeByIndex` and `findUserAttributeByName` methods. diff --git a/lib/All/slang/share/doc/slang/user-guide/04-modules-and-access-control.md b/lib/All/slang/share/doc/slang/user-guide/04-modules-and-access-control.md new file mode 100644 index 0000000..915c62e --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/04-modules-and-access-control.md @@ -0,0 +1,237 @@ +--- +layout: user-guide +permalink: /user-guide/modules +--- + +Modules and Access Control +=========================== + +While the preprocessor `#include` is still supported, Slang provides a _module_ system for software engineering benefits such as clean expression of subcomponent boundaries and dependencies, hiding implementation details, and providing a path towards true separate compilation. + + +## Defining a Module + +A module in Slang comprises one or more files. A module must have one and only one primary file that is used as the source-of-truth to uniquely identify the module. The primary file must start with a `module` declaration. For example, the following code defines a module named `scene`: + +``` +// scene.slang + +module scene; + +// ... +``` + +A module can contain more than one file. The additional files are pulled into the module with the `__include` syntax: + +``` +// scene.slang + +module scene; + +__include "scene-helpers"; + +``` +``` +// scene-helpers.slang + +implementing scene; +// ... +``` + +The files being included into a module must start with `implementing ` declaration. + +Note that the `__include` syntax here has a different meaning than the preprocessor `#include`. `__include` has the following semantics: +1. The preprocessor state at which a file inclusion does not apply to the file being included, and the preprocessor state after parsing the included file will not be visible to the outer "includer" file. For example, `#define`s before a `__include` is not visible to the included file, and `#define`s in the included file is not visible to the file that includes it. +2. A file will be included into the current module exactly once, no matter how many times a `__include` of that file is encountered. +3. Circular `__include`s are allowed, given (2). +4. All files that become part of a module via `__include` can access all other entities defined in the same module, regardless the order of `__include`s. + +This means that the following code is valid: + +``` +// a.slang +implementing m; +void f_a() {} + +// b.slang +implementing "m"; // alternate syntax. +__include a; // pulls in `a` to module `m`. +void f_b() { f_a(); } + +// c.slang +implementing "m.slang"; // alternate syntax. + +void f_c() +{ + // OK, `c.slang` is part of module `m` because it is `__include`'d by + // `m.slang`. + f_a(); f_b(); +} + +// m.slang +module m; +__include m; // OK, a file including itself is allowed and has no effect. +__include "b"; // Pulls in file b (alternate syntax), and transitively pulls in file a. +__include "c.slang"; // Pulls in file c, specifying the full file name. +void test() { f_a(); f_b(); f_c(); } +``` + +Note that both `module`, `implementing` and `__include` support two flavors of syntax to refer to a module or a file: either via +normal identifier tokens or via string literals. For example, the following flavors are equivalent and will resolve to the same file: +``` +__include dir.file_name; // `file_name` is translated to "file-name". +__include "dir/file-name.slang"; +__include "dir/file-name"; +``` + +Also note that a file is considered a part of a module only if the file can be discovered +via transitive `__include`s from the primary module file. It is possible to have a dangling +file with the `implementing` declaration that is not `__include`'d by any other files in +the module. Such dangling files will not be considered as part of the module and will not +be compiled. The `implementing` declaration is for the purpose of verification and language server code assisting, and does not carry any other semantics that affect compilation. + +> #### Note #### +> When using the identifier token syntax, Slang will translate any underscores(`_`) to hyphens("-") to obtain the file name. + +## Importing a Module + +At the global scope of a Slang file, you can use the `import` keyword to import another module by name: + +```hlsl +// MyShader.slang + +import YourLibrary; +``` + +This `import` declaration will cause the compiler to look for a module named `YourLibrary` and make its declarations visible in the current scope. Similar to `__include`, `import` also supports both the identifier-token and the file-name string syntax. + +You can only `import` a primary source file of a module. For example, given: +``` +// m.slang +module m; +__include helper; + +// helper.slang +implementing m; +// ... +``` +It is only valid for the user code to `import m`. Attempting to `import helper` will result a compile-time error. + +Multiple `import`s of the same module from different input files will only cause the module to be loaded once (there is no need for "include guards" or `#pragma once`). +Note that preprocessor definitions in the current file will not affect the compilation of `import`ed code, and the preprocessor definitions in the imported code is not visible to the current file. + +## Access Control + +Slang supports access control modifiers: `public`, `internal` and `private`. The module boundary plays an important role in access control. + +`public` symbols are accessible everywhere: from within the different types, different files or different modules. + +`private` symbols are only visible to other symbols in the same type. The following example shows the scope of `private` visibility: +```csharp +struct MyType +{ + private int member; + + int f() { member = 5; } // OK. + + struct ChildType + { + int g(MyType t) + { + return t.member; // OK. + } + } +} + +void outerFunc(MyType t) +{ + t.member = 2; // Error, `member` is not visible here. +} +``` + +`internal` symbols are visible throughout the same module, regardless if it is referenced from the same type or same file. But they are not visible to other modules. The following example shows the scope of `internal` visibility: + +```csharp +// a.slang +module a; +__include b; +public struct PS +{ + internal int internalMember; + public int publicMember; +} +internal void f() { f_b(); } // OK, f_b defined in the same module. + +// b.slang +implementing a; +internal void f_b(); // Defines f_b in module `a`. +public void publicFunc(); + +// m.slang +module m; +import a; +void main() +{ + f(); // Error, f is not visible here. + publicFunc(); // OK. + PS p; // OK. + p.internalMember = 1; // Error, internalMember is not visible. + p.publicMember = 1; // OK. +} +``` + +`internal` is the default visibility if no other access modifiers are specified, an exception is for `interface` members, where the default visibility is the visibility of the interface. + +### Additional Validation Rules + +The Slang compiler enforces the following rules regarding access control: +- A more visible entity should not expose less visible entities through its signature. For example, a `public` function cannot have a return type that is `internal`. +- A member of a `struct`, `interface` and other aggregate types cannot have a higher visibility than its parent. +- If a `struct` type has visibility `Vs`, and one of its member has visibility `Vm`, and the member is used to satisfy an interface requirement that has visibility `Vr`, then `Vm` must not be lower (less visible) than `min(Vs, Vr)`. +- Type definitions themselves cannot be `private`, for example, `private struct S {}` is not valid code. +- `interface` requirements cannot be `private`. + +## Organizing File Structure of Modules + +Slang does not seek to impose any specific organization of modules. However, there are some conventions that have emerged as being useful. + +### Module Organization Suggestions + +- The top-level directory contains modules that would be `import`ed by user code. +- The implementation details of the modules are placed in files at lower levels of the tree. + +This has the benefit that it is easy for a user to distinguish the public API from the implementation details. + +### Module Organization Example + +Module organization tree diagram + +### Module Organization Example + +The above diagram shows a module organization example. + +Top-level module files such as `utils.slang` are those that are directly `import`ed by user code. The implementation details of the module are placed in the lower levels of the tree, organized into similarly named subdirectories for clarity. + +Modules like `utils.slang` needn't contain anything more than a module declaration and a list of included files, with optional `import` statement(s) to pull in any external dependencies, e.g. + +``` +module utils; +import slangpy; + +__include "utils/accumlator.slang"; +__include "utils/tonemap.slang"; +__include "utils/fill.slang"; +``` + +Here, all the public symbols defined in `accumlator.slang`, `tonemap.slang`, and `fill.slang` are visible to the user of the `utils` module, and these constituent helper files do not need to clutter the top-level file hierarchy. + +## Legacy Modules + +Slang used to not have support for access control, and all symbols were treated as having `public` visibility. To provide compatibility with existing code, the Slang compiler will detect if the module is written in the legacy language, and treat all symbols as `public` if so. + +A module is determined to be written in legacy language if all the following conditions are met: +- The module is lacking `module` declaration at the beginning. +- There is no use of `__include`. +- There is no use of any visibility modifiers -- `public`, `private` or `internal`. + +The user is advised that this legacy mode is for compatibility only. This mode may be deprecated in the future, and it is strongly recommended that new code should not rely on this compiler behavior. diff --git a/lib/All/slang/share/doc/slang/user-guide/05-capabilities.md b/lib/All/slang/share/doc/slang/user-guide/05-capabilities.md new file mode 100644 index 0000000..1c85038 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/05-capabilities.md @@ -0,0 +1,337 @@ +--- +layout: user-guide +permalink: /user-guide/capabilities +--- + +# Capabilities + +One of the biggest challenges in maintaining cross-platform shader code is to manage the differences in hardware capabilities across different GPUs, graphics APIs, and shader stages. +Each graphics API or shader stage may expose operations that are not available on other platforms. Instead of restricting Slang's features to the lowest common denominator of different platforms, +Slang exposes operations from all target platforms to allow the user to take maximum advantage on a specific target. + +A consequence of this approach is that the user is now responsible for maintaining compatibility of their code. For example, if the user writes code that uses a Vulkan extension currently not +available on D3D/HLSL, they will get an error when attempting to compile that code to D3D. + +To help the user to maintain compatibility of their shader code on platforms that matter to their applications, Slang's type system can now infer and enforce capability requirements +to provide assurance that the shader code will be compatible with the specific set of platforms before compiling for that platform. + +For example, `Texture2D.SampleCmp` is available on D3D and Vulkan, but not available on CUDA. If the user is intended to write cross-platform code that targets CUDA, they will +receive a type-checking error when attempting to use `SampleCmp` before the code generation stage of compilation. When using Slang's intellisense plugin, the programmer should +get a diagnostic message directly in their code editor. + +As another example, `discard` is a statement that is only meaningful when used in fragment shaders. If a vertex shader contains a `discard` statement or calling a function that contains +a `discard` statement, it shall be a type-check error. + +## Capability Atoms and Capability Requirements + +Slang models code generation targets, shader stages, API extensions and hardware features as distinct capability atoms. For example, `GLSL_460` is a capability atom that stands for the GLSL 460 code generation target, +`compute` is an atom that represents the compute shader stage, `_sm_6_7` is an atom representing the shader model 6.7 feature set in D3D, `SPV_KHR_ray_tracing` is an atom representing the `SPV_KHR_ray_tracing` SPIR-V extension, and `spvShaderClockKHR` is an atom for the `ShaderClockKHR` SPIRV capability. For a complete list of capabilities supported by the Slang compiler, check the [capability definition file](https://github.com/shader-slang/slang/blob/master/source/slang/slang-capabilities.capdef). + +A capability **requirement** can be a single capability atom, a conjunction of capability atoms, or a disjunction of conjunction of capability atoms. A function can declare its +capability requirement with the following syntax: + +```csharp +[require(spvShaderClockKHR)] +[require(glsl, GL_EXT_shader_realtime_clock)] +[require(hlsl_nvapi)] +uint2 getClock() {...} +``` + +Each `[require]` attribute declares a conjunction of capability atoms, and all `[require]` attributes form the final requirement of the `getClock()` function as a disjunction of capabilities: +``` +(spvShaderClockKHR | glsl + GL_EXT_shader_realtime_clock | hlsl_nvapi) +``` + +A capability can __imply__ other capabilities. Here `spvShaderClockKHR` is a capability that implies `SPV_KHR_shader_clock`, which represents the SPIRV `SPV_KHR_shader_clock` extension, and the `SPV_KHR_shader_clock` capability implies `spirv_1_0`, which stands for the spirv code generation target. + +When evaluating capability requirements, Slang will expand all implications. Therefore the final capability requirement for `getClock` is: +``` + spirv_1_0 + SPV_KHR_shader_clock + spvShaderClockKHR +| glsl + _GL_EXT_shader_realtime_clock +| hlsl + hlsl_nvapi +``` +Which means the function can be called from locations where the `spvShaderClockKHR` capability is available (when targeting SPIRV), or where the `GL_EXT_shader_realtime_clock` extension is available when targeting GLSL, +or where `nvapi` is available when targeting HLSL. + +## Conflicting Capabilities + +Certain groups of capabilities are mutually exclusive such that only one capability in the group is allowed to exist. For example, all stage capabilities are mutual exclusive: a requirement for both `fragment` and `vertex` is impossible to satisfy. Currently, capabilities that model different code generation targets (e.g. `hlsl`, `glsl`) or different shader stages (`vertex`, `fragment`, etc.) are mutually exclusive within +their corresponding group. + +If two capability requirements contain different atoms that are conflicting with each other, these two requirements are considered __incompatible__. +For example, requirement `spvShaderClockKHR + fragment` and requirement `spvShaderClockKHR + vertex` are incompatible, because `fragment` conflicts with `vertex`. + +## Capabilities Between Parent and Members + +The capability requirement of a member is always merged with the requirements declared in its parent(s). If the member declares requirements for additional compilation targets, they are added to the requirement set as a separate disjunction. +For example, given: +```csharp +[require(glsl)] +[require(hlsl)] +struct MyType +{ + [require(hlsl, hlsl_nvapi)] + [require(spirv)] + static void method() { ... } +} +``` +`MyType.method` will have requirement `glsl | hlsl + hlsl_nvapi | spirv`. + +The `[require]` attribute can also be used on module declarations, so that the requirement will +apply to all members within the module. For example: +```csharp +[require(glsl)] +[require(hlsl)] +[require(spirv)] +module myModule; + +// myFunc has requirement glsl|hlsl|spirv +public void myFunc() +{ +} +``` + +## Capabilities Between Subtype and Supertype + +For inheritance/implementing-interfaces the story is a bit different. +We require that the subtype (`Foo1`) have a subset of capabilities to the supertype (`IFoo1`). + +For example: +```csharp +[require(sm_4_0)] +interface IFoo1 +{ +} +[require(sm_6_0)] +struct Foo1 : IFoo1 +{ +} +``` +We error here since `Foo1` is not a subset to `IFoo1`. `Foo1` has `sm_6_0`, which includes capabilities `sm_4_0` does not have. + +```csharp +[require(sm_6_0)] +interface IFoo2 +{ +} +[require(sm_4_0)] +interface IFoo1 +{ +} +[require(sm_4_0)] +struct Foo1 : IFoo1, IFoo2 +{ +} +``` +We do not error here since `IFoo2` and `IFoo1` are supersets to `Foo1`. + +Additionally, any supertype to subtype relationship must share the same shader stage and shader target support. + +```csharp +// Error, Foo1 is missing `spirv` +[require(hlsl)] +[require(spirv)] +interface IFoo1 +{ +} +[require(hlsl)] +struct Foo1 : IFoo1 +{ +} + +// Error, IFoo1 is missing `hlsl` +[require(hlsl)] +interface IFoo1 +{ +} +[require(hlsl)] +[require(spirv)] +struct Foo1 : IFoo1 +{ +} +``` + +## Capabilities Between Requirement and Implementation + +We require that all requirement capabilities are supersets of their implementation (only required if capabilities are explicitly annotated). + +```csharp +public interface IAtomicAddable_Pass +{ + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, This value); +} +public extension int64_t : IAtomicAddable_Pass +{ + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, int64_t value) { buf.InterlockedAddI64(addr, value); } +} + +public interface IAtomicAddable_Error +{ + [require(glsl, sm_4_0)] + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, This value); +} +public extension uint : IAtomicAddable_Error +{ + // Error: implementation has superset of capabilites, sm_6_0 vs. sm_4_0 + // Note: sm_6_0 is inferred from `InterlockedAddI64` + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, int64_t value) { buf.InterlockedAddI64(addr, value); } +} +``` + +Requirment and implementation must also share the same shader stage and shader target support. + +```csharp +public interface IAtomicAddable_Error +{ + [require(glsl)] + [require(hlsl)] + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, This value); +} +public extension uint : IAtomicAddable_Error +{ + [require(glsl)] // Error, missing `hlsl` + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, int64_t value) { buf.InterlockedAddI64(addr, value); } +} + +public interface IAtomicAddable_Error +{ + [require(glsl)] + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, This value); +} +public extension uint : IAtomicAddable_Error +{ + [require(glsl)] + [require(hlsl)] // Error, has additional capability `hlsl` + public static void atomicAdd(RWByteAddressBuffer buf, uint addr, int64_t value) { buf.InterlockedAddI64(addr, value); } +} +``` + +## Capabilities of Functions + +### Inference of Capability Requirements + +By default, Slang will infer the capability requirements of a function given its definition, as long as the function has `internal` or `private` visibility. For example, given: +```csharp +void myFunc() +{ + if (getClock().x % 1000 == 0) + discard; +} +``` +Slang will automatically deduce that `myFunc` has capability +``` + spirv_1_0 + SPV_KHR_shader_clock + spvShaderClockKHR + fragment +| glsl + _GL_EXT_shader_realtime_clock + fragment +| hlsl + hlsl_nvapi + fragment +``` +Since `discard` statement requires capability `fragment`. + +### Inference on target_switch + +A `__target_switch` statement will introduce disjunctions in its inferred capability requirement. For example: +```csharp +void myFunc() +{ + __target_switch + { + case spirv: ...; + case hlsl: ...; + } +} +``` +The capability requirement of `myFunc` is `(spirv | hlsl)`, meaning that the function can be called from a context where either `spirv` or `hlsl` capability +is available. + +### Capability Incompatabilities + +The function declaration must be a superset of the capabilities the function body uses **for any shader stage/target the function declaration implicitly/explicitly requires**. + +```csharp +[require(sm_5_0)] +public void requires_sm_5_0() +{ + +} +[require(sm_4_0)] +public void logic_sm_5_0_error() // Error, missing `sm_5_0` support +{ + requires_sm_5_0(); +} + +public void logic_sm_5_0__pass() // Pass, no requirements +{ + requires_sm_5_0(); +} + +[require(hlsl, vertex)] +public void logic_vertex() +{ + +} +[require(hlsl, fragment)] +public void logic_fragment() +{ + +} +[require(hlsl, vertex, fragment)] +public void logic_stage_pass_1() // Pass, `vertex` and `fragment` supported +{ + __stage_switch + { + case vertex: + logic_vertex(); + case fragment: + logic_fragment(); + } +} + +[require(hlsl, vertex, fragment, mesh, hull, domain)] +public void logic_many_stages() +{ + +} +[require(hlsl, vertex, fragment)] +public void logic_stage_pass_2() // Pass, function only requires that the body implements the stages `vertex` & `fragment`, the rest are irelevant +{ + logic_many_stages(); +} + +[require(hlsl, any_hit)] +public void logic_stage_fail_1() // Error, function requires `any_hit`, body does not support `any_hit` +{ + logic_many_stages(); +} +``` + +## Capability Aliases + +To make it easy to specify capabilities on different platforms, Slang also defines many aliases that can be used in `[require]` attributes. +For example, Slang declares in `slang-capabilities.capdef`: +``` +alias sm_6_6 = _sm_6_6 + | glsl_spirv_1_5 + sm_6_5 + + GL_EXT_shader_atomic_int64 + atomicfloat2 + | spirv_1_5 + sm_6_5 + + GL_EXT_shader_atomic_int64 + atomicfloat2 + + SPV_EXT_descriptor_indexing + | cuda + | cpp; +``` +So user code can write `[require(sm_6_6)]` to mean that the function requires shader model 6.6 on D3D or equivalent set of GLSL/SPIRV extensions when targeting GLSL or SPIRV. +Note that in the above definition, `GL_EXT_shader_atomic_int64` is also an alias that is defined as: +``` +alias GL_EXT_shader_atomic_int64 = _GL_EXT_shader_atomic_int64 | spvInt64Atomics; +``` +Where `_GL_EXT_shader_atomic_int64` is the atom that represent the true `GL_EXT_shader_atomic_int64` GLSL extension. +The `GL_EXT_shader_atomic_int64` alias is defined as a disjunction of `_GL_EXT_shader_atomic_int64` and the `Int64Atomics` SPIRV capability so that +it can be used in both the contexts of GLSL and SPIRV target. + +When aliases are used in a `[require]` attribute, the compiler will expand the alias to evaluate the capability set, and remove all incompatible conjunctions. +For example, `[require(hlsl, sm_6_6)]` will be evaluated to `(hlsl+_sm_6_6)` because all other conjunctions in `sm_6_6` are incompatible with `hlsl`. + +## Validation of Capability Requirements + +Slang requires all public methods and interface methods to have explicit capability requirements declarations. Omitting capability declaration on a public method means that the method does not require any +specific capability. Functions with explicit requirement declarations will be verified by the compiler to ensure that it does not use any capability beyond what is declared. + +Slang recommends but does not require explicit declaration of capability requirements for entrypoints. If explicit capability requirements are declared on an entrypoint, they will be used to validate the entrypoint the same way as other public methods, providing assurance that the function will work on all intended targets. If an entrypoint does not define explicit capability requirements, Slang will infer the requirements, and only issue a compiler error when the inferred capability is incompatible with the current code generation target. diff --git a/lib/All/slang/share/doc/slang/user-guide/06-interfaces-generics.md b/lib/All/slang/share/doc/slang/user-guide/06-interfaces-generics.md new file mode 100644 index 0000000..f3b87b5 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/06-interfaces-generics.md @@ -0,0 +1,1143 @@ +--- +layout: user-guide +permalink: /user-guide/interfaces-generics +--- + +Interfaces and Generics +=========================== + +This chapter covers two interrelated Slang language features: interfaces and generics. We will talk about what they are, how they relate to similar features in other languages, how they are parsed and translated by the compiler, and show examples on how these features simplify and modularize shader code. + +Interfaces +---------- + +Interfaces are used to define the methods and services a type should provide. You can define a interface as the following example: +```csharp +interface IFoo +{ + int myMethod(float arg); +} +``` + +Slang's syntax for defining interfaces are similar to `interface`s in C# and `protocol`s in Swift. In this example, the `IFoo` interface establishes a contract that any type conforming to this interface must provide a method named `myMethod` that accepts a `float` argument and returns an `int` value. + +A `struct` type may declare its conformance to an `interface` via the following syntax: +```csharp +struct MyType : IFoo +{ + int myMethod(float arg) + { + return (int)arg + 1; + } +} +``` +By declaring the conformance to `IFoo`, the definition of `MyType` must include a method named `myMethod` with a matching signature to that defined in the `IFoo` interface to satisfy the declared conformance. If a type misses any methods required by the interface, the Slang compiler will generate an error message. + +A `struct` type may declare multiple interface conformances: +```csharp +interface IBar { uint myMethod2(uint2 x); } + +struct MyType : IFoo, IBar +{ + int myMethod(float arg) {...} + uint myMethod2(uint2 x) {...} +} +``` + +In this case, the definition of `MyType` must satisfy the requirements from both the `IFoo` and `IBar` interfaces by providing both the `myMethod` and `myMethod2` methods. + +Interface methods can have a default implementation, which will be used if a conforming type doesn't provide an overriding implementation. For example: + +```slang +interface IFoo +{ + int getVal() { return 0; } +} + +// OK, MyType.getVal() will use the default implementation provided in `IFoo`. +struct MyType : IFoo {} +``` + +A concrete type that provides its overriding implementation to an interface method requirement that has a default implementation must be explicitly marked as 'override'. For example: + +```slang +struct MyType2 : IFoo +{ + // Explicitly mark `getVal` as `override` is needed + // because `IFoo.getVal` has a body. + override int getVal() { return 1; } +} +``` + +Generics +--------------------- + +Generics can be used to eliminate duplicate code for shared logic that operates on different types. The following example shows how to define a generic method in Slang. + +```csharp +int myGenericMethod(T arg) where T : IFoo +{ + return arg.myMethod(1.0); +} +``` + +The above listing defines a generic method named `myGenericMethod`, which accepts an argument that can be of any type `T` as long as `T` conforms to the `IFoo` interface. The `T` here is called a _generic type parameter_, and it is associated with an _type constraint_ in the following `where` clause to indicate that any type represented by `T` must conform to the interface `IFoo`. + +The following listing shows how to invoke a generic method: +```csharp +MyType obj; +int a = myGenericMethod(obj); // OK, explicit type argument +int b = myGenericMethod(obj); // OK, automatic type deduction +``` + +You may explicitly specify the concrete type to used for the generic type argument, by providing the types in angular brackets after the method name, or leave it to the compiler to automatically deduce the type from the argument list. + +Note that it is important to associate a generic type parameter with a type constraint. In the above example, although the definition of `myGenericMethod` is agnostic of the concrete type `T` will stand for, knowing that `T` conforms to `IFoo` allows the compiler to type-check and pre-compile `myGenericMethod` without needing to substitute `T` with any concrete types first. Similar to languages like C#, Rust, Swift and Java, leaving out the type constraint declaration on type parameter `T` will result in a compile error at the line calling `arg.myMethod` since the compiler cannot verify that `arg` has a member named `myMethod` without any knowledge on `T`. This is a major difference of Slang's generics compared to _templates_ in C++. + +While C++ templates are a powerful language mechanism, Slang has followed the path of many other modern programming languages to adopt the more structural and restricted generics feature instead. This enables the Slang compiler to perform type checking early to give more readable error messages, and to speed-up compilation by reusing a lot of work for different instantiations of `myGenericMethod`. + +A generic parameter can also be a value. Currently, integer, bool and enum types are allowed as the type for a generic value parameter. Generic value parameters are declared with the `let` keyword. For example: + +```csharp +void g1() { ... } + +enum MyEnum { A, B, C } +void g2() { ... } + +void g3() { ... } +``` + +### Alternative Syntax + +Alternatively, you can use `__generic` keyword to define generic parameters before the method: +```csharp +__generic // `typename` is optional. +int myGenericMethod(T arg) where T : IFoo +{ + return arg.myMethod(1.0); +} +``` + +The same method can be defined in an alternative simplified syntax without the `where` clause: +```csharp +int myGenericMethod(T arg) { ... } +``` + +Generic value parameters can also be defined using the traditional C-style syntax: +```csharp +void g1() { ... } +``` + +Slang allows multiple `where` clauses, and multiple interface types in a single `where` clause: +```csharp +struct MyType + where T: IFoo, IBar + where U : IBaz +{ +} +// equivalent to: +struct MyType + where T: IFoo + where T : IBar + where U : IBaz +{ +} +``` + +Optional conformances can be expressed compactly using the `where optional` syntax: +```csharp +// Together, these two overloads... +int myGenericMethod(T arg) +{ +} + +int myGenericMethod(T arg) where T: IFoo +{ + arg.myMethod(1.0); +} + +// ... are equivalent to: +int myGenericMethod(T arg) where optional T: IFoo +{ + if (T is IFoo) + { + arg.myMethod(1.0); // OK in a block that checks for T: IFoo conformance. + } +} +``` + +### Using Generic Parameters in Attributes + +Slang allows referencing generic parameters in bracket attributes. This is particularly useful for shader entry points where you want to control attributes like workgroup sizes at compile time. + +For example: +```csharp +[numthreads(blockSize, blockSize, 1)] +void computeMain() +{ + // Shader implementation +} +``` + +In this example, the generic parameter `blockSize` is used in the `numthreads` attribute. This allows the host application to control the workgroup size by compiling a specialization of the entry point with a specific value for `blockSize`, instead of by resorting to preprocessor macros. + +Supported Constructs in Interface Definitions +----------------------------------------------------- + +Slang supports many other constructs in addition to ordinary methods as a part of an interface definition. + +### Properties + +```csharp +interface IFoo +{ + property int count {get; set;} +} + +struct MyObject : IFoo +{ + int myCount = 0; + property int count + { + get { return myCount; } + set { myCount = newValue; } + } +} +``` +The above listing declares that any conforming type must define a property named `count` with both a `getter` and a `setter` method. You can then access the concrete value stored in the property as you would normally. + +```csharp +MyObject obj; +obj.count = 2; + +int count2 = obj.count; // count2 = 2 +``` + +### Generic Methods + +```csharp +interface IFoo +{ + int compute(T val) where T : IBar; +} +``` +The above listing declares that any conforming type must define a generic method named `compute` that has one generic type parameter conforming to the `IBar` interface. + +### Static Methods + +```csharp +interface IFoo +{ + static int compute(int val); +}; +``` + +The above listing declares that any conforming type must define a static method named `compute`. This allows the following generic method to pass type-checking: +```csharp +void f() where T : IFoo +{ + T.compute(5); // OK, T has a static method `compute`. +} +``` + +### Static Constants + +You can define static constant requirements in an interface. The constants can be accessed in places where a compile-time constant is needed. +```csharp +interface IMyValue +{ + static const int value; +} +struct MyObject2 : IMyValue +{ + static const int value = 2; +} +struct GetValuePlus1 +{ + static const int value = T.value + 1; +} + +static const int result = GetValuePlus1.value; // result == 3 +``` + +### `This` Type + +You may use a special keyword `This` in interface definitions to refer to the type that is conforming to the interface. The following examples demonstrate a use of `This` type: +```csharp +interface IComparable +{ + int comparesTo(This other); +} +struct MyObject : IComparable +{ + int val; + int comparesTo(MyObject other) + { + return val < other.val ? -1 : 1; + } +} +``` +In this example, the `IComparable` interface declares that any conforming type must provide a `comparesTo` method that performs a comparison between an object to another object of the same type. The `MyObject` type satisfies this requirement by providing a `comparesTo` method that accepts a `MyObject` typed argument, since in the scope of `MyObject`, `This` type is equivalent to `MyObject`. + +### Initializers + +Consider a generic method that wants to create and initialize a new instance of generic type `T`: +```csharp +void f() +{ + T obj = /*a newly initialized T*/ +} +``` +One way to implement this is to introduce a static method requirement in `IFoo`: +```csharp +interface IFoo +{ + static This create(); +} +``` +With this interface definition, we can define `f` as following: +```csharp +void f() +{ + T obj = T.create(); +} +``` + +This solution works just fine, but it would be nicer if you can just write: +```csharp +T obj = T(); +``` +Or simply +```csharp +T obj; +``` +And let the compiler invoke the default initializer defined in the type. +To enable this, you can include an initializer requirement in the interface definition: +```csharp +interface IFoo +{ + __init(); +} +``` + +Initializers with parameters are supported as well. For example: +```csharp +interface IFoo +{ + __init(int a, int b); +} +void g() +{ + T obj = {1, 2}; // OK, invoking the initializer on T. +} +``` + +Associated Types +------------------------- + +When writing code using interfaces and generics, there are some situations where an interface method needs to return an object whose type is implementation-dependent. For example, consider the following `IFloatContainer` interface that represents a container of `float` values: +```csharp +// Represents a container of float values. +interface IFloatContainer +{ + // Returns the number of elements in this container. + uint getCount(); + // Returns an iterator representing the start of the container. + Iterator begin(); + // Returns an iterator representing the end of the container. + Iterator end(); + // Return the element at the location represented by `iter`. + float getElementAt(Iterator iter); +} +``` +An implementation of the `IFloatContainer` interface may use different types of iterators. For example, an implementation that is simply an array of `float`s can expose `Iterator` as a simple integer index: +```csharp +struct ArrayFloatContainer : IFloatContainer +{ + float content[10]; + uint getCount() { return 10; } + uint begin() { return 0; } + uint end() { return 10; } + float getElementAt(uint iter) { return content[iter]; } +} +``` +On the other hand, an implementation that uses multiple buffers as the backing storage may use a more complex type to locate an element: +```csharp +// Exposes values in two `StructuredBuffer`s as a single container. +struct MultiArrayFloatContainer : IFloatContainer +{ + StructuredBuffer firstBuffer; + StructuredBuffer secondBuffer; + uint getCount() { return getBufferSize(firstBuffer) + getBufferSize(secondBuffer); } + + // `uint2.x` indicates which buffer, `uint2.y` indicates the index within the buffer. + uint2 begin() { return uint2(0,0); } + uint2 end() { return uint2 (1, getBufferSize(secondBuffer)); } + float getElementAt(uint2 iter) + { + if (iter.x == 0) return firstBuffer[iter.y]; + else return secondBuffer[iter.y]; + } +} +``` + +Ideally, a generic function that wishes to enumerate values in a `IFloatContainer` shouldn't need to care about the implementation details on what the concrete type of `Iterator` is, and we would like to be able to write the following: +```csharp +float sum(T container) +{ + float result = 0.0f; + for (T.Iterator iter = container.begin(); iter != container.end(); iter=iter.next()) + { + float val = container.getElementAt(iter); + result += val; + } + return result; +} +``` +Here the `sum` function simply wants to access all the elements and sum them up. The details of what the `Iterator` type actually is does not matter to the definition of `sum`. + +The problem is that the `IFloatContainer` interface definition requires methods like `begin()`, `end()` and `getElementAt()` to refer to a iterator type that is implementation dependent. How should the signature of these methods be defined in the interface? The answer is to use _associated types_. + +In addition to constructs listed in the previous section, Slang also supports defining associated types in an `interface` definition. An associated type can be defined as following. +```csharp +// The interface for an iterator type. +interface IIterator +{ + // An iterator needs to know how to move to the next element. + This next(); +} + +interface IFloatContainer +{ + // Requires an implementation to define a typed named `Iterator` that + // conforms to the `IIterator` interface. + associatedtype Iterator : IIterator; + + // Returns the number of elements in this container. + uint getCount(); + // Returns an iterator representing the start of the container. + Iterator begin(); + // Returns an iterator representing the end of the container. + Iterator end(); + // Return the element at the location represented by `iter`. + float getElementAt(Iterator iter); +}; +``` + +This `associatedtype` definition in `IFloatContainer` requires that all types conforming to this interface must also define a type in its scope named `Iterator`, and this iterator type must conform to the `IIterator` interface. An implementation to the `IFloatContainer` interface by using either a `typedef` declaration or a `struct` definition inside its scope to satisfy the associated type requirement. For example, the `ArrayFloatContainer` can be implemented as following: +```csharp +struct ArrayIterator : IIterator +{ + uint index; + __init(int x) { index = x; } + ArrayIterator next() + { + return ArrayIterator(index + 1); + } +} +struct ArrayFloatContainer : IFloatContainer +{ + float content[10]; + + // Specify that the associated `Iterator` type is `ArrayIterator`. + typedef ArrayIterator Iterator; + + Iterator getCount() { return 10; } + Iterator begin() { return ArrayIterator(0); } + Iterator end() { return ArrayIterator(10); } + float getElementAt(Iterator iter) { return content[iter.index]; } +} +``` + +Alternatively, you may also define the `Iterator` type directly inside a `struct` implementation, as in the following definition for `MultiArrayFloatContainer`: +```csharp +// Exposes values in two `StructuredBuffer`s as a single container. +struct MultiArrayFloatContainer : IFloatContainer +{ + // Represents an iterator of this container + struct Iterator : IIterator + { + // `index.x` indicates which buffer the element is located in. + // `index.y` indicates which the index of the element inside the buffer. + uint2 index; + + // We also need to keep a size of the first buffer so we know when to + // switch to the second buffer. + uint firstBufferSize; + + // Implementation of IIterator.next() + Iterator next() + { + Iterator result; + result.index.x = index.x; + result.index.y = index.y + 1; + // If we are at the end of the first buffer, + // move to the head of the second buffer + if (result.index.x == 0 && result.index.y == firstBufferSize) + { + result.index = uint2(1, 0); + } + return result; + } + } + + StructuredBuffer firstBuffer; + StructuredBuffer secondBuffer; + uint getCount() { return getBufferSize(firstBuffer) + getBufferSize(secondBuffer); } + + Iterator begin() + { + Iterator iter; + iter.index = uint2(0, 0); + iter.firstBufferSize = getBufferSize(firstBuffer); + return iter; + } + Iterator end() + { + Iterator iter; + iter.index = uint2(1, getBufferSize(secondBuffer)); + iter.firstBufferSize = 0; + return iter; + } + float getElementAt(Iterator iter) + { + if (iter.index.x == 0) return firstBuffer[iter.index.y]; + else return secondBuffer[iter.index.y]; + } +} +``` + +In summary, an `associatedtype` requirement in an interface is similar to other types of requirements: a method requirement means that an implementation must provide a method matching the interface signature, while an `associatedtype` requirement means that an implementation must provide a type in its scope with the matching name and interface constraint. In general, when defining an interface that is producing and consuming an object whose actual type is implementation-dependent, the type of this object can often be modeled as an associated type in the interface. + + +### Comparing Generics to C++ Templates +Readers who are familiar with C++ could easily relate the `Iterator` example in previous subsection to the implementation of STL. In C++, the `sum` function can be easily written with templates: +```C++ +template +float sum(const TContainer& container) +{ + float result = 0.0f; + // Assumes `TContainer` has a type `Iterator` that supports `operator++`. + for (TContainer::Iterator iter = container.begin(); iter != container.end(); ++iter) + { + result += container.getElementAt(iter); + } + return result; +} +``` + +A C++ programmer can implement `ArrayFloatContainer` as following: +```C++ +struct ArrayFloatContainer +{ + float content[10]; + + typedef uint32_t Iterator; + + Iterator getCount() { return 10; } + Iterator begin() { return 0; } + Iterator end() { return 10; } + float getElementAt(Iterator iter) { return content[iter]; } +}; +``` +Because C++ does not require a template function to define _constraints_ on the templated type, there are no interfaces or inheritances involved in the definition of `ArrayFloatContainer`. However `ArrayFloatContainer` still needs to define what its `Iterator` type is, so the `sum` function can be successfully specialized with an `ArrayFloatContainer`. + +Note that the biggest difference between C++ templates and generics is that templates are not type-checked prior to specialization, and therefore the code that consumes a templated type (`TContainer` in this example) can simply assume `container` has a method named `getElementAt`, and the `TContainer` scope provides a type definition for `TContainer::Iterator`. Compiler error only arises when the programmer is attempting to specialize the `sum` function with a type that does not meet these assumptions. Contrarily, Slang requires all possible uses of a generic type be declared through an interface. By stating that `TContainer:IContainer` in the generics declaration, the Slang compiler can verify that `container.getElementAt` is calling a valid function. Similarly, the interface also tells the compiler that `TContainer.Iterator` is a valid type and enables the compiler to fully type check the `sum` function without specializing it first. + +### Similarity to Swift and Rust + +Slang's `associatedtype` shares the same semantic meaning with `associatedtype` in a Swift `protocol` or `type` in a Rust `trait`. C# does not have an equivalent to `associatedtype`, and programmers need to resort to generic interfaces to achieve similar goals. + +Generic Value Parameters +------------------------------- + +So far we have demonstrated generics with _type parameters_. Additionally, Slang also supports generic _value_ parameters. +The following listing shows an example of generic value parameters. +```csharp +struct Array +{ + T arrayContent[N]; +} +``` +In this example, the `Array` type has a generic type parameter, `T`, that is used as the element type of the `arrayContent` array, and a generic value parameter `N` of integer type. + +Note that the builtin `vector` type also has an generic value parameter `N`. + +> #### Note #### +> The only type of generic value parameters are `int`, `uint` and `bool`. `float` and +> other types cannot be used in a generic value parameter. Computations in a type +> expression are supported as long as they can be evaluated at compile time. For example, +`vector` is allowed and considered equivalent to `vector`. + + +Type Equality Constraints +------------------------- + +In addition to type conformance constraints as in `where T : IFoo`, Slang also supports type equality constraints. This is mostly useful in specifying additional constraints for +associated types. For example: +```csharp +interface IFoo { associatedtype A; } + +// Access all T that conforms to IFoo, and T.A is `int`. +void foo(T v) + where T : IFoo + where T.A == int +{ +} + +struct X : IFoo +{ + typealias A = int; +} + +struct Y : IFoo +{ + typealias A = float; +} + +void test() +{ + foo(X()); // OK + foo(Y()); // Error, `Y` cannot be used for `T`. +} +``` + +Interface-typed Values +------------------------------- + +So far we have been using interfaces as constraints to generic type parameters. For example, the following listing defines a generic function with a type parameter `TTransform` constrained by interface `ITransform`: + +```csharp +interface ITransform +{ + int compute(MyObject obj); +} + +// Defining a generic method: +int apply(TTransform transform, MyObject object) +{ + return transform.compute(object); +} +``` + +While Slang's syntax for defining generic methods bears similarity to generics in C#/Java and templates in C++ and should be easy to users who are familiar with these languages, codebases that make heavy use of generics can quickly become verbose and difficult to read. To reduce the amount of boilerplate, Slang supports an alternate way to define the `apply` method by using the interface type `ITransform` as parameter type directly: + +```csharp +// A method that is equivalent to `apply` but uses simpler syntax: +int apply_simple(ITransform transform, MyObject object) +{ + return transform.compute(object); +} +``` + +Instead of defining a generic type parameter `TTransform` and a method parameter `transform` that has `TTransform` type, you can simply define the same `apply` function like a normal method, with a `transform` parameter whose type is an interface. From the Slang compiler's view, `apply` and `apply_simple` will be compiled to the same target code. + +In addition to parameters, Slang allows variables, and function return values to have an interface type as well: +```csharp +ITransform test(ITransform arg) +{ + ITransform v = arg; + return v; +} +``` + +### Restrictions and Caveats + +The Slang compiler always attempts to determine the actual type of an interface-typed value at compile time and specialize the code with the actual type. As long as the compiler can successfully determine the actual type, code that uses interface-typed values are equivalent to code written in the generics syntax. However, when interface types are used in function return values, the compiler will not be able to trivially propagate type information. For example: +```csharp +ITransform getTransform(int x) +{ + if (x == 0) + { + Type1Transform rs = {}; + return rs; + } + else + { + Type2Transform rs = {}; + return rs; + } +} +``` +In this example, the actual type of the return value is dependent on the value of `x`, which may not be known at compile time. This means that the concrete type of the return value at invocation sites of `getTransform` may not be statically determinable. When the Slang compiler cannot infer the concrete type of an interface-type value, it will generate code that performs a dynamic dispatch based on the concrete type of the value at runtime, which may introduce performance overhead. Note that this behavior applies to function return values in the form of `out` parameters as well: + +```csharp +void getTransform(int x, out ITransform transform) +{ + if (x == 0) + { + Type1Transform rs = {}; + transform = rs; + } + else + { + Type2Transform rs = {}; + transform = rs; + } +} +``` +This `getTransform` definition can also result in dynamic dispatch code since the type of `transform` may not be statically determinable. + +When the compiler is generating dynamic dispatch code for interface-typed values, it requires the concrete type of the interface-typed value to be free of any opaque-typed fields (e.g. resources and buffer types). A compiler error will generated upon such attempts: +```csharp +struct MyTransform : ITransform +{ + StructuredBuffer buffer; + int compute(MyObject obj) + { + return buffer[0]; + } +} + +ITransform getTransform(int x) +{ + MyTransform rs; + // Error: cannot use an opaque value as an interface-typed return value. + return rs; +} +``` + +Assigning different values to a mutable interface-typed variable also undermines the compiler's ability to statically determine the type of the variable, and is not supported by the Slang compiler today: +```csharp +void test(int x) +{ + ITransform t = Type1Transform(); + // Do something ... + // Assign a different type of transform to `t`: + // (Not supported by Slang today) + t = Type2Transform(); + // Do something else... +} +``` + +In general, if the use of interface-typed values is restricted to function parameters only, then the all code that involves interface-typed values will be compiled the same way as if the code is written using standard generics syntax. + + +Extending a Type with Additional Interface Conformances +----------------------------- +In the previous chapter, we introduced the `extension` feature that lets you define new members to an existing type in a separate location outside the original definition of the type. + +`extensions` can be used to make an existing type conform to additional interfaces. Suppose we have an interface `IFoo` and a type `MyObject` that implements the interface: + +```csharp +interface IFoo +{ + int foo(); +}; + +struct MyObject : IFoo +{ + int foo() { return 0; } +} +``` + +Now we introduce another interface, `IBar`: +```csharp +interface IBar +{ + float bar(); +} +``` + +We can define an `extension` to make `MyObject` conform to `IBar` as well: +```csharp +extension MyObject : IBar +{ + float bar() { return 1.0f } +} +``` + +With this extension, we can use `MyObject` in places that expects an `IBar` as well: +```csharp +void use(IBar b) +{ + b.bar(); +} + +void test() +{ + MyObject obj; + use(obj); // OK, `MyObject` is extended to conform to `IBar`. +} +``` + +You may define more than one interface conformances in a single `extension`: +```csharp +interface IBar2 +{ + float bar2(); +} +extension MyObject : IBar, IBar2 +{ + float bar() { return 1.0f } + float bar2() { return 2.0f } +} +``` + +`is` and `as` Operator +---------------------------- + +You can use `is` operator to test if an interface-typed value is of a specific concrete type, and use `as` operator to downcast the value into a specific type. +The `as` operator returns an `Optional` that is not `none` if the downcast succeeds. + +```csharp +interface IFoo +{ + int foo(); +} +struct MyImpl : IFoo +{ + int foo() { return 0; } +} +void test(IFoo foo) +{ + bool t = foo is MyImpl; // true + Optional optV = foo as MyImpl; + if (t == (optV != none)) + printf("success"); + else + printf("fail"); +} +void main() +{ + MyImpl v; + test(v); +} +// Result: +// "success" +``` + +In addition to casting from an interface type to a concrete type, `as` and `is` operator can be used on generic types as well to cast a generic type into a concrete type. For example: +```csharp +T compute(T a1, T a2) +{ + if (a1 is float) + { + return reinterpret((a1 as float).value + (a2 as float).value); + } + else if (T is int) + { + return reinterpret((a1 as int).value - (a2 as int).value); + } + return T(); +} +// compute(1.0f, 2.0f) == 3.0f +// compute(3, 1) == 2 +``` + +Since `as` operator returns a `Optional` type, it can also be used in the `if` predicate to test if an object can be +casted to a specific type, once the cast test is successful, the object can be used in the `if` block as the casted type +without the need to retrieve the `Optional::value` property, for example: + +```csharp +interface IFoo +{ + void foo(); +} + +struct MyImpl1 : IFoo +{ + void foo() { printf("MyImpl1");} +} + +struct MyImpl2 : IFoo +{ + void foo() { printf("MyImpl2");} +} + +struct MyImpl3 : IFoo +{ + void foo() { printf("MyImpl3");} +} + +void test(IFoo foo) +{ + // This syntax will be desugared to the following: + // { + // Optional optVar = foo as MyImpl1; + // if (optVar.hasValue) + // { + // MyImpl1 t = optVar.value; + // t.foo(); + // } + // else if ... + // } + if (let t = foo as MyImpl1) // t is of type MyImpl1 + { + t.foo(); + } + else if (let t = foo as MyImpl2) // t is of type MyImpl2 + { + t.foo(); + } + else + printf("fail"); +} + +void main() +{ + MyImpl1 v1; + test(v1); + + MyImpl2 v2; + test(v2); +} + +``` +See [if-let syntax](03-convenience-features.md#if_let-syntax) for more details. + + +Generic Interfaces +------------------ + +Slang allows interfaces themselves to be generic. A common use of generic interfaces is to define the `IEnumerable` type: +```csharp +interface IEnumerator +{ + This moveNext(); + bool isEnd(); + T getValue(); +} + +interface IEnumerable +{ + associatedtype Enumerator : IEnumerator; + Enumerator getEnumerator(); +} +``` + +You can constrain a generic type parameter to conform to a generic interface: +```csharp +void traverse(TCollection c) + where TCollection : IEnumerable +{ + ... +} +``` + + +Generic Extensions +---------------------- +You can use generic extensions to extend a generic type. For example, +```csharp +interface IFoo { void foo(); } +interface IBar { void bar(); } + +struct MyType +{ + void foo() { ... } +} + +// Extend `MyType` so it conforms to `IBar`. +extension MyType : IBar +{ + void bar() { ... } +} +// Equivalent to: +__generic +extension MyType : IBar +{ + void bar() { ... } +} +``` + + +Extensions to Interfaces +----------------------------- + +In addition to extending ordinary types, you can define extensions on all types that conforms to some interface: + +```csharp +// An example interface. +interface IFoo +{ + int foo(); +} + +// Extend any type `T` that conforms to `IFoo` with a `bar` method. +extension T +{ + int bar() { return 0; } +} + +int use(IFoo foo) +{ + // With the extension, all uses of `IFoo` typed values + // can assume there is a `bar` method. + return foo.bar(); +} +``` + +Note that `interface` types cannot be extended, because extending an `interface` with new requirements would make all existing types that conforms +to the interface no longer valid. + +In the presence of extensions, it is possible for a type to have multiple ways to +conform to an interface. In this case, Slang will always prefer the more specific conformance +over the generic one. For example, the following code illustrates this behavior: + +```csharp +interface IBase{} +interface IFoo +{ + int foo(); +} + +// MyObject directly implements IBase: +struct MyObject : IBase, IFoo +{ + int foo() { return 0; } +} + +// Generic extension that applies to all types that conforms to `IBase`: +extension T : IFoo +{ + int foo() { return 1; } +} + +int helper(T obj) +{ + return obj.foo(); +} + +int test() +{ + MyObject obj; + + // Returns 0, the conformance defined directly by the type + // is preferred. + return helper(obj); +} +``` + +This feature is similar to extension traits in Rust. + + +Variadic Generics +------------------------- + +Slang supports variadic generic type parameters: +```csharp +struct MyType +{} +``` + +Here `each T` defines a generic type pack parameter that can be a list of zero or more types. Therefore, the following instantiation of `MyType` is valid: +``` +MyType // OK +MyType // OK +MyType // OK +``` + +A common use of variadic generics is to define `printf`: +```csharp +void printf(String message, expand each T args) { ... } +``` + +The type syntax `expand each T` represents a expansion of the type pack `T`. Therefore, the type of `args` parameter is an expanded type pack. +The `expand` expression can be thought of a map operation of a type pack. For example, +give type pack `T = int, float, bool`, `expand each T` evaluates to the type pack of the same types, i.e. `expand each T ==> int, float, bool`. +As a more interesting example, `expand S` will evaluate to `S, S, S`. + +You can use `expand` expression on tuple or type-pack values to compute an expression for each element of the tuple or type pack. +For example: + +```csharp +void printNumbers(expand each T args) where T == int +{ + // An single expression statement whose type will be `(void, void, ...)`. + // where each `void` is the result of evaluating expression `printf(...)` with + // each corresponding element in `args` passed as print operand. + // + expand printf("%d\n", each args); + + // The above statement is equivalent to: + // ``` + // (printf("%d\n", args[0]), printf("%d\n", args[1]), ..., printf("%d\n", args[n-1])); + // ``` +} +void compute(expand each T args) where T == int +{ + // Maps every element in `args` to `elementValue + 1`, and forwards the + // new values as arguments to `printNumbers`. + printNumbers(expand (each args) + 1); + + // The above statement is equivalent to: + // ``` + // printNumbers(args[0] + 1, args[1] + 1, ..., args[n-1] + 1); + // ``` +} +void test() +{ + compute(1,2,3); + // Prints: + // 2 + // 3 + // 4 +} +``` + +As another example, you can use `expand` expression to sum up elements in a variadic argument pack: +```csharp +void accumulateHelper(inout int dest, int value) { dest += value; } + +void sum(expand each T args) where T == int +{ + int result = 0; + expand accumulateHelper(result, each args); + + // The above statement is equivalent to: + // ``` + // (accumulateHelper(result, args[0]), accumulateHelper(result, args[1]), ..., accumulateHelper(result, args[n-1])); + // ``` + + return result; +} + +void test() +{ + int x = sum(1,2,3); // x == 6 +} +``` + +Note that a variadic type pack parameter must appear at the end of a parameter list. If a generic type contains more than one +type pack parameters, then each type pack must contain the same number of arguments at instantiation sites. + +Builtin Interfaces +----------------------------- + +Slang supports the following builtin interfaces: + +- `IComparable`, provides methods for comparing two values of the conforming type. Supported by all basic data types, vector types and matrix types. +- `IRangedValue`, provides methods for retrieving the minimum and maximum value expressed by the range of the type. Supported by all integer and floating-point scalar types. +- `IArithmetic`, provides methods for the `+`, `-`, `*`, `/`, `%` and negating operations. Also provide a method for explicit conversion from `int`. Implemented by all builtin integer and floating-point scalar, vector and matrix types. +- `ILogical`, provides methods for all bit operations and logical `and`, `or`, `not` operations. Also provide a method for explicit conversion from `int`. Implemented by all builtin integer scalar, vector and matrix types. +- `IInteger`, represents a logical integer that supports both `IArithmetic` and `ILogical` operations. Implemented by all builtin integer scalar types. +- `IDifferentiable`, represents a value that is differentiable. +- `IFloat`, represents a logical float that supports both `IArithmetic`, `ILogical` and `IDifferentiable` operations. Also provides methods to convert to and from `float`. Implemented by all builtin floating-point scalar, vector and matrix types. +- `IArray`, represents a logical array that supports retrieving an element of type `T` from an index. Implemented by array types, vectors, matrices and `StructuredBuffer`. +- `IRWArray`, represents a logical array whose elements are mutable. Implemented by array types, vectors, matrices, `RWStructuredBuffer` and `RasterizerOrderedStructuredBuffer`. +- `IFunc` represent a callable object (with `operator()`) that returns `TResult` and takes `TParams...` as argument. +- `IMutatingFunc`, similar to `IFunc`, but the `operator()` method is `[mutating]`. +- `IDifferentiableFunc`, similar to `IFunc`, but the `operator()` method is `[Differentiable]`. +- `IDifferentiableMutatingFunc`, similar to `IFunc,` but the `operator()` method is `[Differentiable]` and `[mutating]`. +- `__EnumType`, implemented by all enum types. +- `__BuiltinIntegerType`, implemented by all integer scalar types. +- `__BuiltinFloatingPointType`, implemented by all floating-point scalar types. +- `__BuiltinArithmeticType`, implemented by all integer and floating-point scalar types. +- `__BuiltinLogicalType`, implemented by all integer types and the `bool` type. + +Operator overloads are defined for `IArithmetic`, `ILogical`, `IInteger`, `IFloat`, `__BuiltinIntegerType`, `__BuiltinFloatingPointType`, `__BuiltinArithmeticType` and `__BuiltinLogicalType` types, so the following code is valid: + +```csharp +T f(T x, T y) +{ + if (x > T(0)) + return x + y; + else + return x - y; +} +void test() +{ + let rs = f(float3(4), float3(5)); // rs = float3(9,9,9) +} +``` diff --git a/lib/All/slang/share/doc/slang/user-guide/07-autodiff.html b/lib/All/slang/share/doc/slang/user-guide/07-autodiff.html new file mode 100644 index 0000000..b82e23b --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/07-autodiff.html @@ -0,0 +1,9 @@ + + + + + + +

    This page has been relocated. Click here for the new page.

    + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/07-autodiff.md b/lib/All/slang/share/doc/slang/user-guide/07-autodiff.md new file mode 100644 index 0000000..2752500 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/07-autodiff.md @@ -0,0 +1,864 @@ +--- +layout: user-guide +permalink: /user-guide/autodiff +--- + +# Automatic Differentiation + +To support differentiable graphics systems such as Gaussian splatters, neural radiance fields, differentiable path tracers, and more, +Slang provides first class support for differentiable programming. +An overview: +- Slang supports the `fwd_diff` and `bwd_diff` operators that can generate the forward and backward-mode derivative propagation functions for any valid Slang function annotated with the `[Differentiable]` attribute. +- The `DifferentialPair` built-in generic type is used to pass derivatives associated with each function input. +- The `IDifferentiable`, and the experimental `IDifferentiablePtrType`, interfaces denote differentiable value and pointer types respectively, and allow finer control over how types behave under differentiation. +- Further, Slang allows for user-defined derivative functions through the `[ForwardDerivative(custom_fn)]` and `[BackwardDerivative(custom_fn)]` +- All Slang features, such as control-flow, generics, interfaces, extensions, and more are compatible with automatic differentiation, though the bottom of this chapter documents some sharp edges & known issues. + +## Auto-diff operations `fwd_diff` and `bwd_diff` + +In Slang, `fwd_diff` and `bwd_diff` are higher-order functions used to transform Slang functions into their forward or backward derivative methods. To better understand what these methods do, here is a small refresher on differentiable calculus: +### Mathematical overview: Jacobian and its vector products +Forward and backward derivative methods are two different ways of computing a dot product with the Jacobian of a given function. +Parts of this overview are based on JAX's excellent auto-diff cookbook [here](https://jax.readthedocs.io/en/latest/notebooks/autodiff_cookbook.html#how-it-s-made-two-foundational-autodiff-functions). The relevant [wikipedia article](https://en.wikipedia.org/wiki/Automatic_differentiation) is also a great resource for understanding auto-diff. + +The [Jacobian](https://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant) (also called the total derivative) of a function $$\mathbf{f}(\mathbf{x})$$ is represented by $$D\mathbf{f}(\mathbf{x})$$. + +For a general function with multiple scalar inputs and multiple scalar outputs, the Jacobian is a _matrix_ where $$D\mathbf{f}_{ij}$$ represents the [partial derivative](https://en.wikipedia.org/wiki/Partial_derivative) of the $$i^{th}$$ output element w.r.t the $$j^{th}$$ input element $$\frac{\partial f_i}{\partial x_j}$$ + +As an example, consider a polynomial function + +$$ f(x, y) = x^3 + x^2 - y $$ + +Here, $$f$$ has 1 output and 2 inputs. $$Df$$ is therefore the row matrix: + +$$ Df(x, y) = [\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}] = [3x^2 + 2x, -1] $$ + +Another, more complex example with a function that has multiple outputs (for clarity, denoted by $$f_1$$, $$f_2$$, etc..) + +$$ \mathbf{f}(x, y) = \begin{bmatrix} f_0(x, y) & f_1(x, y) & f_2(x, y) \end{bmatrix} = \begin{bmatrix} x^3 & y^2x & y^3 \end{bmatrix} $$ + +Here, $$D\mathbf{f}$$ is a 3x2 matrix with each element containing a partial derivative: + +$$ D\mathbf{f}(x, y) = \begin{bmatrix} +\partial f_0 / \partial x & \partial f_0 / \partial y \\ +\partial f_1 / \partial x & \partial f_1 / \partial y \\ +\partial f_2 / \partial x & \partial f_2 / \partial y +\end{bmatrix} = +\begin{bmatrix} +3x^2 & 0 \\ +y^2 & 2yx \\ +0 & 3y^2 +\end{bmatrix} $$ + +Computing full Jacobians is often unnecessary and expensive. Instead, auto-diff offers ways to compute _products_ of the Jacobian with a vector, which is a much faster operation. +There are two basic ways to compute this product: + 1. the Jacobian-vector product $$ \langle D\mathbf{f}(\mathbf{x}), \mathbf{v} \rangle $$, also called forward-mode autodiff, and can be computed using `fwd_diff` operator in Slang, and + 2. the vector-Jacobian product $$ \langle \mathbf{v}^T, D\mathbf{f}(\mathbf{x}) \rangle $$, also called reverse-mode autodiff, and can be computed using `bwd_diff` operator in Slang. From a linear algebra perspective, this is the transpose of the forward-mode operator. + +#### Propagating derivatives with forward-mode auto-diff +The products described above allow the _propagation_ of derivatives forward and backward through the function $$f$$ + +The forward-mode derivative (Jacobian-vector product) can convert a derivative of the inputs to a derivative of the outputs. +For example, let's say inputs $$\mathbf{x}$$ depend on some scalar $$\theta$$, and $$\frac{\partial \mathbf{x}}{\partial \theta}$$ is a vector of partial derivatives describing that dependency. + +Invoking forward-mode auto-diff with $$\mathbf{v} = \frac{\partial \mathbf{x}}{\partial \theta}$$ converts this into a derivative of the outputs w.r.t the same scalar $$\theta$$. +This can be verified by expanding the Jacobian and applying the [chain rule](https://en.wikipedia.org/wiki/Chain_rule) of derivatives: + +$$\langle D\mathbf{f}(\mathbf{x}), \frac{\partial \mathbf{x}}{\partial \theta} \rangle = \langle \begin{bmatrix} \frac{\partial f_0}{\partial x_0} & \frac{\partial f_0}{\partial x_1} & \cdots \\ \frac{\partial f_1}{\partial x_0} & \frac{\partial f_1}{\partial x_1} & \cdots \\ \cdots & \cdots & \cdots \end{bmatrix}, \begin{bmatrix} \frac{\partial x_0}{\partial \theta} \\ \frac{\partial x_1}{\partial \theta} \\ \cdots \end{bmatrix} \rangle = \begin{bmatrix} \frac{\partial f_0}{\partial \theta} \\ \frac{\partial f_1}{\partial \theta} \\ \cdots \end{bmatrix} = \frac{\partial \mathbf{f}}{\partial \theta}$$ + +#### Propagating derivatives with reverse-mode auto-diff +The reverse-mode derivative (vector-Jacobian product) can convert a derivative w.r.t outputs into a derivative w.r.t inputs. +For example, let's say we have some scalar $$\mathcal{L}$$ that depends on the outputs $$\mathbf{f}$$, and $$\frac{\partial \mathcal{L}}{\partial \mathbf{f}}$$ is a vector of partial derivatives describing that dependency. + +Invoking forward-mode auto-diff with $$\mathbf{v} = \frac{\partial \mathcal{L}}{\partial \mathbf{f}}$$ converts this into a derivative of the same scalar $$\mathcal{L}$$ w.r.t the inputs $$\mathbf{x}$$. +To provide more intuition for this, we can expand the Jacobian in a same way we did above: + +$$\langle \frac{\partial \mathcal{L}}{\partial \mathbf{f}}^T, D\mathbf{f}(\mathbf{x}) \rangle = \langle \begin{bmatrix}\frac{\partial \mathcal{L}}{\partial f_0} & \frac{\partial \mathcal{L}}{\partial f_1} & \cdots \end{bmatrix}, \begin{bmatrix} \frac{\partial f_0}{\partial x_0} & \frac{\partial f_0}{\partial x_1} & \cdots \\ \frac{\partial f_1}{\partial x_0} & \frac{\partial f_1}{\partial x_1} & \cdots \\ \cdots & \cdots & \cdots \end{bmatrix} \rangle = \begin{bmatrix} \frac{\partial \mathcal{L}}{\partial x_0} & \frac{\partial \mathcal{L}}{\partial x_1} & \cdots \end{bmatrix} = \frac{\partial \mathcal{L}}{\partial \mathbf{x}}^T$$ + +This mode is the most popular, since machine learning systems often construct their differentiable pipeline with multiple inputs (which can number in the millions or billions), and a single scalar output often referred to as the 'loss' denoted by $$\mathcal{L}$$. The desired derivative can be constructed with a single reverse-mode invocation. + +### Invoking auto-diff in Slang +With the mathematical foundations established, we can describe concretely how to compute derivatives using Slang. + +In Slang derivatives are computed using `fwd_diff`/`bwd_diff` which each correspond to Jacobian-vector and vector-Jacobian products. +For forward-diff, to pass the vector $$\mathbf{v}$$ and receive the outputs, we use the `DifferentialPair` type. We use pairs of inputs because every input element $$x_i$$ has a corresponding element $$v_i$$ in the vector, and each original output element has a corresponding output element in the product. + +Example of `fwd_diff`: +```csharp +[Differentiable] // Auto-diff requires that functions are marked differentiable +float2 foo(float a, float b) +{ + return float2(a * b * b, a * a); +} + +void main() +{ + DifferentialPair dp_a = diffPair( + 1.0, // input 'a' + 1.0 // vector 'v' for vector-Jacobian product input (for 'a') + ); + + DifferentialPair dp_b = diffPair(2.4, 0.0); + + // fwd_diff to compute output and d_output w.r.t 'a'. + // Our output is also a differential pair. + // + DifferentialPair dp_output = fwd_diff(foo)(dp_a, dp_b); + + // Extract output's primal part, which is just the standard output when foo is called normally. + // Can also use `.getPrimal()` + // + float2 output_p = dp_output.p; + + // Extract output's derivative part. Can also use `.getDifferential()` + float2 output_d = dp_output.d; + + printf("foo(1.0, 2.4) = (%f %f)\n", output_p.x, output_p.y); + printf("d(foo)/d(a) at (1.0, 2.4) = (%f, %f)\n", output_d.x, output_d.y); +} +``` + +Note that all the inputs and outputs to our function become 'paired'. This only applies to differentiable types, such as `float`, `float2`, etc. See the section on differentiable types for more info. + +`diffPair(primal_val, diff_val)` is a built-in utility function that constructs the pair from the primal and differential values. + +Additionally, invoking forward-mode also computes the regular (or 'primal') output value (can be obtained from `output.getPrimal()` or `output.p`). The same is _not_ true for reverse-mode. + +For reverse-mode, the example proceeds in a similar way, and we still use `DifferentialPair` type. However, note that each input gets a corresponding _output_ and each output gets a corresponding _input_. Thus, all inputs become `inout` differential pairs, to allow the function to write into the derivative part (the primal part is still accepted as an input in the same pair data-structure). +The one extra rule is that the derivative corresponding to the return value of the function is accepted as the last argument (an extra input). This value does not need to be a pair. + +Example: +```csharp +[Differentiable] // Auto-diff requires that functions are marked differentiable +float2 foo(float a, float b) +{ + return float2(a * b * b, a * a); +} + +void main() +{ + DifferentialPair dp_a = diffPair( + 1.0 // input 'a' + ); // Calling diffPair without a derivative part initializes to 0. + + DifferentialPair dp_b = diffPair(2.4); + + // Derivatives of scalar L w.r.t output. + float2 dL_doutput = float2(1.0, 0.0); + + // bwd_diff to compute dL_da and dL_db + // The derivative of the output is provided as an additional _input_ to the call + // Derivatives w.r.t inputs are written into dp_a.d and dp_b.d + // + bwd_diff(foo)(dp_a, dp_b, dL_doutput); + + // Extract the derivatives of L w.r.t input + float dL_da = dp_a.d; + float dL_db = dp_b.d; + + printf("If dL/dOutput = (1.0, 0.0), then (dL/da, dL/db) at (1.0, 2.4) = (%f, %f)", dL_da, dL_db); +} +``` + +## Differentiable Type System + +Slang will only generate differentiation code for values that has a *differentiable* type. +Differentiable types are defining through conformance to one of two built-in interfaces: +1. `IDifferentiable`: For value types (e.g. `float`, structs of value types, etc..) +2. `IDifferentiablePtrType`: For buffer, pointer & reference types that represent locations rather than values. + +### Differentiable Value Types +All basic types (`float`, `int`, `double`, etc..) and all aggregate types (i.e. `struct`) that use any combination of these are considered value types in Slang. + +Slang uses the `IDifferentiable` interface to define differentiable types. Basic types that describe a continuous value (`float`, `double` and `half`) and their vector/matrix versions (`float3`, `half2x2`, etc..) are defined as differentiable by the standard library. For all basic types, the type used for the differential (can be obtained with `T.Differential`) is the same as the primal. + +#### Builtin Differentiable Value Types +The following built-in types are differentiable: +- Scalars: `float`, `double` and `half`. +- Vector/Matrix: `vector` and `matrix` of `float`, `double` and `half` types. +- Arrays: `T[n]` is differentiable if `T` is differentiable. +- Tuples: `Tuple` is differentiable if `T` is differentiable. + + +#### User-defined Differentiable Value Types + +However, it is easy to define your own differentiable types. +Typically, all you need is to implement the `IDifferentiable` interface. + +```csharp +struct MyType : IDifferentiable +{ + float x; + float y; +}; +``` + +The main requirement of a type implementing `IDifferentiable` is the `Differential` associated type that the compiler uses to carry the corresponding derivative. +In most cases the `Differential` of a type can be itself, though it can be different if necessary. +You can access the differential of any differentiable type through `Type.Differential` + +Example: +```csharp +MyType obj; +obj.x = 1.f; + +MyType.Differential d_obj; +// Differentiable fields will have a corresponding field in the diff type +d_obj.x = 1.f; +``` + +Slang can automatically derive the `Differential` type in the majority of cases. +For instance, for `MyType`, Slang can infer the differential trivially: +```csharp +struct MyType : IDifferentiable +{ + // Automatically inserted by Slang from the fact that + // MyType has 2 floats which are both differentiable + // + typealias Differential = MyType; + // ... +} +``` + +For more complex types that aren't fully differentiable, a new type is synthesized automatically: + +```csharp +struct MyPartialDiffType : IDifferentiable +{ + // Automatically inserted by Slang based on which fields are differentiable. + typealias MyPartialDiffType = syn_MyPartialDiffType_Differential; + + float x; + uint y; +}; + +// Synthesized +struct syn_MyPartialDiffType_Differential +{ + // Only one field since 'y' does not conform to IDifferentiable + float x; +}; +``` + +You can make existing types differentiable through Slang's extension mechanism. +For instance, `extension MyType : IDifferentiable { }` will make `MyType` differentiable retroactively. + +See the `IDifferentiable` [reference documentation](https://shader-slang.org/stdlib-reference/interfaces/idifferentiable-01/index) for more information on how to override the default behavior. + +#### DifferentialPair: Pairs of differentiable value types + +The `DifferentialPair` type is used to pass derivatives to a derivative call by representing a pair of values of type `T` and `T.Differential`. Note that `T` must conform to `IDifferentiable`. + +`DifferentialPair` can either be created via constructor calls or the `diffPair` utility method. + +Example: + +```csharp +MyType obj = {1.f, 2.f}; + +MyType.Differential d_obj = {0.4f, 3.f}; + +// The differential part of a differentiable-pair is of the diff type. +DifferentialPair dp_obj = diffPair(obj, d_obj); + +// Use .p to extract the primal part +MyType new_p_obj = dp_obj.p; + +// Use .d to extract the differential part +MyType.Differential new_d_obj = dp_obj.d; +``` + +### Differentiable Ptr types +Pointer types are any type that represents a location or reference to a value rather than the value itself. +Examples include resource types (`RWStructuredBuffer`, `Texture2D`), pointer types (`Ptr`) and references. + +The `IDifferentiablePtrType` interface can be used to denote types that need to transform into pairs during auto-diff. However, unlike +an `IDifferentiable` type whose derivative portion is an _output_ under `bwd_diff`, the derivative part of `IDifferentiablePtrType` remains an input. This is because only the value is returned as an output, while the location where it needs to be written to, is still effectively an input to the derivative methods. + +> #### Note #### +> Support for `IDifferentiablePtrType` is still experimental. There are no built-in types conforming to this interface, though we plan to add stdlib support in the near future. + +`IDifferentiablePtrType` only requires a `Differential` associated type to be specified. + +#### DifferentialPtrPair: Pairs of differentiable ptr types +For types conforming to `IDifferentiablePtrType`, the corresponding pair to use for passing the derivative counterpart is `DifferentialPtrPair`, which represents a pair of `T` and `T.Differential`. Objects of this type can be created using a constructor. + +#### Example of defining and using an `IDifferentiablePtrType` object. +Here is an example of create a differentiable buffer pointer type, and using it within a differentiable function. +You can find an interactive sample on the Slang playground [here](https://shader-slang.org/slang-playground/?target=WGSL&code=eJy1VF1v2kAQfPevWEWKYhfkmFdMkBrRSpHKhyBSpdIIHfgcTjFn9z4gEeK_d-_ONsZp1L6UF8MxOzszuz62K3KhoMjI27PINU9iTyqhNwrGb_c6TamY5YwrKqAPDyNmDihXjKwzOlPi8a2g3tED_NzewuOWQnKGZFAQpGYSCM_VFikYl4rwDYU8bdOHlkQhH8kYkTBq8ty10bFn4fPvC6tVC5q4_wdplhM1hLVOYwvRiMd2qaQq9k5Yhzq_Mf4CBDZaqnwHCRVsTxTbU295TzYvByKSUX3mI1-yWh-S4Mmz3GAO_HY4Rdd1Yjyhr0EZiaCojEMRopplEToV0HGgJ5Rj1UxyRUFtkRkzgnWpoCELJHvmxJg0WUrFsgwThRvGb9pxM8xxn7MEKtV-M0cc2Awhg5b44aX6LjifyVSryknbrmm7KpTAyRRh4pKuzqzb-kfLNHTuLLE1v7zcpypgqXfTdPFLE0HlIMPiCe4e9h2-T73SVxbmEgVFYVqux3JMXh8QJ_0JTs_icgG-s2qQMT4GMMFHpxNYgKM7U-5JtjJQO3SMiQVxjTDt0I6DfHJP9-_Ja84fcc7u-SXr9-efJyO_F6Guj5eY8UIrrL2s_PFlPl38rdRujym121AItDwmjPsfDdTN8ug6diE6OSO20L_6yoRU0IuMR01lH37yqzKIPybaixqRNniukz5cp1iMQXbLTJUwqQblyErgQu_MHSHdEpivaVtCyXOxLL1oaAhrtndra1Ip9_boInJeqxtsRiTeVvZFMk0LV4dH0g3D3VL4Xq3Mgvvt5oFfO_6X986Zr0UF3bq6F0Zlvs1UzreSEYc9dabgEIrQXR3_ZT61unJKp98JDfhi). +```csharp +struct MyBufferPointer : IDifferentiablePtrType +{ + // The differential part is another instance of MyBufferPointer. + typealias Differential = MyBufferPointer; + + RWStructuredBuffer buf; + uint offset; +}; + +// Link a custom derivative +[BackwardDerivative(load_bwd)] +float load(MyBufferPointer p, uint index) +{ + return p.buf[p.offset + index]; +} + +// Note that the backward derivative signature is still an 'in' differential pair. +void load_bwd(DifferentialPtrPair p, uint index, float dOut) +{ + MyBufferPointer diff_ptr = p.d; + diff_ptr.buf[diff_ptr.offset + index] += dOut; +} + +[Differentiable] +float sumOfSquares(MyBufferPointer p) +{ + float sos = 0.f; + + [MaxIters(N)] + for (uint i = 0; i < N; i++) + { + float val_i = load(p, i); + sos += val_i * val_i; + } + + return sos; +} + +RWStructuredBuffer inputs; +RWStructuredBuffer derivs; + +void main() +{ + MyBufferPointer ptr = {inputs, 0}; + print("Sum of squares of first 10 values: ", sumOfSquares<10>(ptr)); + + MyBufferPointer deriv_ptr = {derivs, 0}; + + // Pass a pair of pointers as input. + bwd_diff(sumOfSquares<10>)( + DifferentialPtrPair(ptr, deriv_ptr), + 1.0); + + print("Derivative of result w.r.t the 10 values: \n"); + for (uint i = 0; i < 10; i++) + print("%d: %f\n", i, load(deriv_ptr, i)); +} +``` + +## User-Defined Derivative Functions + +As an alternative to compiler-generated derivatives, you can choose to provide an implementation for the derivative, which the compiler will use instead of attempting to generate one. + +This can be performed on a per-function basis by using the decorators `[ForwardDerivative(fwd_deriv_func)]` and `[BackwardDerivative(bwd_deriv_func)]` to reference the derivative from the primal function. + +For instance, it often makes little sense to differentiate the body of a `sin(x)` implementation, when we know that the derivative is `cos(x) * dx`. In Slang, this can be represented in the following way: +```csharp +DifferentialPair sin_fwd(DifferentialPair dpx) +{ + float x = dpx.p; + float dx = dpx.d; + return DifferentialPair(dpx.p, cos(x) * dx); +} + +// sin() is now considered differentiable (atleast for forward-mode) since it provides +// a derivative implementation. +// +[ForwardDerivative(sin_fwd)] +float sin(float x) +{ + // Calc sin(X) using Taylor series.. +} + +// Any uses of sin() in a `[Differentiable]` will automaticaly use the sin_fwd implementation when differentiated. +``` + +A similar example for a backward derivative. +```csharp +void sin_bwd(inout DifferentialPair dpx, float dresult) +{ + float x = dpx.p; + + // Write-back the derivative to each input (the primal part must be copied over as-is) + dpx = DifferentialPair(x, cos(x) * dresult); +} + +[BackwardDerivative(sin_bwd)] +float sin(float x) +{ + // Calc sin(X) using Taylor series.. +} +``` + +> Note that the signature of the provided forward or backward derivative function must match the expected signature from invoking `fwd_diff(fn)`/`bwd_diff(fn)` +> For a full list of signature rules, see the reference section for the [auto-diff operators](#fwd_difff--slang_function---slang_function). + +### Back-referencing User Derivative Attributes. +Sometimes, the original function's definition might be inaccessible, so it can be tricky to add an attribute to create the association. + +For such cases, Slang provides the `[ForwardDerivativeOf(primal_fn)]` and `[BackwardDerivativeOf(primal_fn)]` attributes that can be used +on the derivative function and contain a reference to the function for which they are providing a derivative implementation. +As long as both the derivative function is in scope, the primal function will be considered differentiable. + +Example: +```csharp +// Module A +float sin(float x) { /* ... */ } + +// Module B +import A; +[BackwardDerivativeOf(sin)] // Add a derivative implementation for sin() in module A. +void sin_bwd(inout DifferentialPair dpx, float dresult) { /* ... */ } +``` + +User-defined derivatives also work for generic functions, member functions, accessors, and more. +See the reference section for the [`[ForwardDerivative(fn)]`](https://shader-slang.org/stdlib-reference/attributes/forwardderivative-07.html) and [`[BackwardDerivative(fn)]`](https://shader-slang.org/stdlib-reference/attributes/backwardderivative-08) attributes for more. + +## Using Auto-diff with Generics +Automatic differentiation works seamlessly with generically-defined types and methods. +For generic methods, differentiability of a type is defined either through an explicit `IDifferentiable` constraint or any other +interface that extends `IDifferentiable`. + +Example for generic methods: +```csharp +[Differentiable] +T calcFoo(T x) { /* ... */ } + +[Differentiable] +T calcBar(T x) { /* ... */ } + +[Differentiable] +void main() +{ + DifferentialPair dpa = /* ... */; + + // Can call with any type that is IDifferentiable. Generic parameters + // are inferred like any other call. + // + bwd_diff(calcFoo)(dpa, float4(1.f)); + + // But you can also be explicit with < > + bwd_diff(calcFoo)(dpa, float4(1.f)); + + // x is differentiable for calcBar because + // __BuiltinFloatingPointType : IDifferentiable + // + DifferentialPair dpb = /* .. */; + bwd_diff(calcBar)(dpb, 1.0); +} +``` + +You can implement `IDifferentiable` on a generic type. Automatic synthesis still applies and will use +generic constraints to resolve whether a field is differentiable or not. +```csharp +struct Foo : IDifferentiable +{ + T t; + U u; +}; + +// The synthesized Foo.Differential will contain a field for +// 't' but not 'U' +// +``` + +## Using Auto-diff with Interface Requirements and Interface Types +For interface requirements, using `[Differentiable]` attribute enforces that any implementation of that method must also be +differentiable. You can, of course, provide a manual derivative implementation to satisfy the requirement. + +The following is a sample snippet. You can run the full sample on the playground [here](https://shader-slang.org/slang-playground/?target=HLSL&code=eJyVVMtu2zAQvOsrFgEKy4Wq1C7QQ1330AYBcujjnhbBWiRjphQpUJQjI8i_d0mRquLYASLYtLwc7sySs5R1Y6yDRuH-1ppOs1UmteNWYMXh6tKY7CEDeq4vpBDccu0kbhT_E4JCGXRQoary4bWfr7LHLGud7SoHtPqqbhR8miYagJTeGbvKQuj8HDyO15QdnTQadhIBO2dq-lsB-0_tZ8tXCQrxgdo_lrvOaujhLXwoBY1RCQTE43P1y5fk-8gLJdSoO1RqD401O8mkvgXGrdwRYseh5m5rWBvLuTT2Hi27GOdzX8aNuGfzobbrr1j9PQbZjJBXlb-clh-rDz-TjVW_UNrPIdcXSHryU4BTbP78PC7vy2YgLiJ7X7JRw_yJiJ2RDFJ5udSmcyeF9UWsnFnedsodyuhhfWqtl1SkdQebMgoiSd4BcMvdz81d3lGDgNnc3Ug2j66QAvIhAus1LA4FpEaQfljDw6L8KB5Xh9vkZxOlH7lq-fFEyzET6X05EWl_1inRJqZuOseTUwo4UtfxZv1mOToOSEy6dajppjACuHRbbpPEBZjxfRkWhi0U9F2njYxcsfdS9ou9xjp0fdugq7bgDGBDHdRY6Wln3hWzMsLTqh-GptzWqyUK6VquBMgWtNHv2JP6CxLORrYtesz0ilHA0GEBG3LcrJ8F9GwwyCytupdKkTut3U8aui3bqagdWoi-WntRZehLf0Nmk7MaEOHWDJanIrX7jlLn6QxOuZ41SInH3lqW76NhqWFufDiPJzzPCVrAgj6lSPSBJz97I37rs8LnKpm_u_8BU5nW2Q). +```csharp +interface IFoo +{ + [Differentiable] + float calc(float x); +} + +struct FooImpl : IFoo +{ + // Implementation via automatic differentiation. + [Differentiable] + float calc(float x) + { /* ... */ } +} + +struct FooImpl2 : IFoo +{ + // Implementation via manually providing derivative methods. + [ForwardDerivative(calc_fwd)] + [BackwardDerivative(calc_bwd)] + float calc(float x) + { /* ... */ } + + DifferentialPair calc_fwd(DifferentialPair x) + { /* ... */ } + + void calc_bwd(inout DifferentialPair x, float dresult) + { /* ... */ } +} + +[Differentiable] +float compute(float x, uint obj_id) +{ + // Create an instance of either FooImpl1 or FooImpl2 + IFoo foo = createDynamicObject(obj_id); + + // Dynamic dispatch to appropriate 'calc'. + // + // Note that foo itself is non-differentiable, and + // has no differential data, but 'x' and 'result' + // will carry derivatives.s + // + var result = foo.calc(x); + return result; +} +``` + +### Differentiable Interface (and Associated) Types +> Note: This is an advanced use-case and support is currently experimental. + +You can have an interface or an interface associated type extend `IDifferentiable` and use that in differentiable interface requirement functions. This is often important in large code-bases with modular components that are all differentiable (one example is the material system in large production renderers) + +Here is a snippet of how to make an interface and associated type (and by consequence all its implementations) differentiable. +For a full working sample, check out the Slang playground [here](https://shader-slang.org/slang-playground/?target=WGSL&code=eJylVVFvmzAQfudXnCpVgoXRhK4vpdnLuodIq9pqe9umygGzuXPANaYjqvLfd8bgmIR0a-eHcHfcnT9_38WwlSilAsHJ-ocs6yJLPI8VisqcpBQWHwhPa04UKws4h8Uly3MqaaEYWXLqPXmA6-sw-r0N5rwkCogQfO0buw4SbzPs_kWSospLuTrYm1RVmTKiaKbWgsIOHMfFxgexuFUr8ov6HZJKyTpV8IkVlMibkq-LcsUI3-ncIekOlDjO0jgvIaEJ4AkkVbUsgMAbaGCCbWDjbSyc25pkEndOX4_IOOlznDwPzbfYgs5IhyANZwstpSi3glhBO4haNMIZqQYazPcod2ELNRu68cu0bcNme7321CUpAnjy1U9WRdgc3kJnzoLQmpvENujVSk1oVKpXEzEitjNUhwnZuiuW3Qn1XxSNTdxDy5JN0SvGUdCETeBda82QOm0ZBOEgdxvHpDObjuXDPAxbf5_zB5fzvbM514c-1vXy3q_xcgGWhR03j4TPHDsOOjVYDj7LYD6H6fi4DPXkTHNhmuk2-0A564HqX8oreojiYeeHnc4h-JplHUCaW8hwAqdRPsINe46b7gZA5Q0nev56JoTlRMS91fTUOKSWy3tE11NrOuhaEQfduA0-D3pgsCTqb1gHaxqZi6bRF6_nPZZIvpCI64qwwu-3boFeXV9-_Iyd-hkvJXSqYnCa4OPC5KA5meyqZw7TfmHEDU4clkRxcuB1jK9P3dctJP9oKNFVmVE4zsBv5tPoLDiH4_xbcRQCCw29-LT7bU0kVmf3ROnlSMRvCJMXLZr3kIkGgWT4Vkd9XZb8Q9HCOaQttkhe1CIeaxE7LZa_szud4OsTB_rIzv6uE2unCWEWTd2jd8RmvqRVzVVwkuEoWCaxIsqCPRncbH05O_l277_XxWN1sa3Df88fIn-viQ) + +```csharp +interface IFoo : IDifferentiable +{ + associatedtype BaseType : IDifferentiable; + + [Differentiable] + BaseType foo(BaseType x); +}; + +[Differentiable] +float calc(float x) +{ + // Note that since IFoo is differentiable, + // any data in the IFoo implementation is differentiable + // and will carry derivatives. + // + IFoo obj = makeObj(/* ... */); + return obj.foo(x); +} +``` + +Under the hood, Slang will automatically construct an anonymous abstract type to represent the differentials. +However, on targets that don't support true dynamic dispatch, these are lowered into tagged unions. +While we are working to improve the implementation, this union can currently include all active differential +types, rather than just the relevant ones. This can lead to increased memory use. + +## Primal Substitute Functions + +Sometimes it is desirable to replace a function with another when generating derivative code. +Most often, this is because a lot of shader operations may just not have a function body, such hardware intrinsics for +texture sampling. In such cases, Slang provides a `[PrimalSubstitute(fn)]` attribute that can be used to provide +a reference implementation that Slang can differentiate to generate the derivative function. + +The following is a small snippet with bilinear texture sampling. For a full example application that uses this concept, see the [texture differentiation sample](https://github.com/shader-slang/slang/tree/master/examples/autodiff-texture) in the Slang repository. + +```csharp +[PrimalSubstitute(sampleTextureBiliear_reference)] +float4 sampleTextureBilinear(Texture2D x, float2 loc) +{ + // HW-accelerated sampling intrinsics. + // Slang does not have access to body, so cannot differentiate. + // + x.Sample(/*...*/) +} + +// Since the substitute is differentiable, so is `sampleTextureBilinear`. +[Differentiable] +float4 sampleTextureBilinear_reference(Texture2D x, float2 loc) +{ + // Reference SW interpolation, that is differentiable. +} + +[Differentiable] +float computePixel(Texture2D x, float a, float b) +{ + // Slang will use HW-accelerated sampleTextureBilinear for standard function + // call, but differentiate the SW reference interpolation during backprop. + // + float4 sample1 = sampleTextureBilinear(x, float2(a, 1)); +} +``` + +Similar to `[ForwardDerivativeOf(fn)]` and `[BackwardDerivativeOf(fn)]` attributes, Slang provides a `[PrimalSubstituteOf(fn)]` attribute that can be used on the substitute function to reference the primal one. + +## Working with Mixed Differentiable and Non-Differentiable Code + +Introducing differentiability to an existing system often involves dealing with code that mixes differentiable and non-differentiable logic. +Slang provides type checking and code analysis features to allow users to clarify the intention and guard against unexpected behaviors involving when to propagate derivatives through operations. + +### Excluding Parameters from Differentiation + +Sometimes we do not wish a parameter to be considered differentiable despite it has a differentiable type. We can use the `no_diff` modifier on the parameter to inform the compiler to treat the parameter as non-differentiable and skip generating differentiation code for the parameter. The syntax is: + +```csharp +// Only differentiate this function with regard to `x`. +float myFunc(no_diff float a, float x); +``` + +The forward derivative and backward propagation functions of `myFunc` should have the following signature: +```csharp +DifferentialPair fwd_derivative(float a, DifferentialPair x); +void back_prop(float a, inout DifferentialPair x, float dResult); +``` + +In addition, the `no_diff` modifier can also be used on the return type to indicate the return value should be considered non-differentiable. For example, the function +```csharp +no_diff float myFunc(no_diff float a, float x, out float y); +``` +Will have the following forward derivative and backward propagation function signatures: + +```csharp +float fwd_derivative(float a, DifferentialPair x); +void back_prop(float a, inout DifferentialPair x, float d_y); +``` + +By default, the implicit `this` parameter will be treated as differentiable if the enclosing type of the member method is differentiable. If you wish to exclude `this` parameter from differentiation, use `[NoDiffThis]` attribute on the method: +```csharp +struct MyDifferentiableType : IDifferentiable +{ + [NoDiffThis] // Make `this` parameter `no_diff`. + float compute(float x) { ... } +} +``` + +### Excluding Struct Members from Differentiation + +When using automatic `IDifferentiable` conformance synthesis for a `struct` type, Slang will by-default treat all struct members that have a differentiable type as differentiable, and thus include a corresponding field in the generated `Differential` type for the struct. +For example, given the following definition +```csharp +struct MyType : IDifferentiable +{ + float member1; + float2 member2; +} +``` +Slang will generate: +```csharp +struct MyType.Differential : IDifferentiable +{ + float member1; // derivative for MyType.member1 + float2 member2; // derivative for MyType.member2 +} +``` +If the user does not want a certain member to be treated as differentiable despite it has a differentiable type, a `no_diff` modifier can be used on the struct member to exclude it from differentiation. +For example, the following code excludes `member1` from differentiation: +```csharp +struct MyType : IDifferentiable +{ + no_diff float member1; // excluded from differentiation + float2 member2; +} +``` +The generated `Differential` in this case will be: +```csharp +struct MyType.Differential : IDifferentiable +{ + float2 member2; +} +``` + +### Assigning Differentiable Values into a Non-Differentiable Location + +When a value with derivatives is being assigned to a location that is not differentiable, such as a struct member that is marked as `no_diff`, the derivative info is discarded and any derivative propagation is stopped at the assignment site. +This may lead to unexpected results. For example: +```csharp +struct MyType : IDifferentiable +{ + no_diff float member; + float someOtherMember; +} +[Differentiable] +float f(float x) +{ + MyType t; + t.member = x * x; // Error: assigning value with derivative into a non-differentiable location. + return t.member; +} +``` +In this case, we are assigning the value `x*x`, which carries a derivative, into a non-differentiable location `MyType.member`, thus throwing away any derivative info. When `f` returns `t.member`, there will be no derivative associated with it, so the function will not propagate the derivative through. This code is most likely not intending to discard the derivative through the assignment. To help avoid this kind of unintentional behavior, Slang will treat any assignments of a value with derivative info into a non-differentiable location as a compile-time error. To eliminate this error, the user should either make `t.member` differentiable, or to force the assignment by clarifying the intention to discard any derivatives using the built-in `detach` method. +The following code will compile, and the derivatives will be discarded: +```csharp +[Differentiable] +float f(float x) +{ + MyType t; + // OK: the code has expressed clearly the intention to discard the derivative and perform the assignment. + t.member = detach(x * x); + return t.member; +} +``` + +### Calling Non-Differentiable Functions from a Differentiable Function +Calling non-differentiable function from a differentiable function is allowed. However, derivatives will not be propagated through the call. The user is required to clarify the intention by prefixing the call with the `no_diff` keyword. An un-clarified call to non-differentiable function will result in a compile-time error. + +For example, consider the following code: +```csharp +float g(float x) +{ + return 2*x; +} + +[Differentiable] +float f(float x) +{ + // Error: implicit call to non-differentiable function g. + return g(x) + x * x; +} +``` +The derivative will not propagate through the call to `g` in `f`. As a result, `fwd_diff(f)(diffPair(1.0, 1.0))` will return +`{3.0, 2.0}` instead of `{3.0, 4.0}` as the derivative from `2*x` is lost through the non-differentiable call. To prevent unintended error, it is treated as a compile-time error to call `g` from `f`. If such a non-differentiable call is intended, a `no_diff` prefix is required in the call: +```csharp +[Differentiable] +float f(float x) +{ + // OK. The intention to call a non-differentiable function is clarified. + return no_diff g(x) + x * x; +} +``` + +However, the `no_diff` keyword is not required in a call if a non-differentiable function does not take any differentiable parameters, or if the result of the differentiable function is not dependent on the derivative being propagated through the call. + +### Treat Non-Differentiable Functions as Differentiable +Slang allows functions to be marked with a `[TreatAsDifferentiable]` attribute for them to be considered as differentiable functions by the type-system. When a function is marked as `[TreatAsDifferentiable]`, the compiler will not generate derivative propagation code from the original function body or perform any additional checking on the function definition. Instead, it will generate trivial forward and backward propagation functions that returns 0. + +This feature can be useful if the user marked an `interface` method as forward or backward differentiable, but only wish to provide non-trivial derivative propagation functions for a subset of types that implement the interface. For other types that does not actually need differentiation, the user can simply put `[TreatAsDifferentiable]` on the method implementations for them to satisfy the interface requirement. + +See the following code for an example of `[TreatAsDifferentiable]`: +```csharp +interface IFoo +{ + [Differentiable] + float f(float v); +} + +struct B : IFoo +{ + [TreatAsDifferentiable] + float f(float v) + { + return v * v; + } +} + +[Differentiable] +float use(IFoo o, float x) +{ + return o.f(x); +} + +// Test: +B obj; +float result = fwd_diff(use)(obj, diffPair(2.0, 1.0)).d; +// result == 0.0, since `[TreatAsDifferentiable]` causes a trivial derivative implementation +// being generated regardless of the original code. +``` + +## Higher-Order Differentiation + +Slang supports generating higher order forward and backward derivative propagation functions. It is allowed to use `fwd_diff` and `bwd_diff` operators inside a forward or backward differentiable function, or to nest `fwd_diff` and `bwd_diff` operators. For example, `fwd_diff(fwd_diff(sin))` will have the following signature: + +```csharp +DifferentialPair> sin_diff2(DifferentialPair> x); +``` + +The input parameter `x` contains four fields: `x.p.p`, `x.p.d,`, `x.d.p`, `x.d.d`, where `x.p.p` specifies the original input value, both `x.p.d` and `x.d.p` store the first order derivative if `x`, and `x.d.d` stores the second order derivative of `x`. Calling `fwd_diff(fwd_diff(sin))` with `diffPair(diffPair(pi/2, 1.0), DiffPair(1.0, 0.0))` will result `{ { 1.0, 0.0 }, { 0.0, -1.0 } }`. + +User defined higher-order derivative functions can be specified by using `[ForwardDerivative]` or `[BackwardDerivative]` attribute on the derivative function, or by using `[ForwardDerivativeOf]` or `[BackwardDerivativeOf]` attribute on the higher-order derivative function. + +## Restrictions and Known Issues + +The compiler can generate forward derivative and backward propagation implementations for most uses of array and struct types, including arbitrary read and write access at dynamic array indices, and supports uses of all types of control flows, mutable parameters, generics and interfaces. This covers the set of operations that is sufficient for a lot of functions. However, the user needs to be aware of the following restrictions when using automatic differentiation: + +- All operations to global resources, global variables and shader parameters, including texture reads or atomic writes, are treated as a non-differentiable operation. Slang provides support for special data-structures (such as `Tensor`) through libraries such as `SlangPy`, which come with custom derivative implementations +- If a differentiable function contains calls that cause side-effects such as updates to global memory, there is currently no guarantee on how many times side-effects will occur during the resulting derivative function or back-propagation function. +- Loops: Loops must have a bounded number of iterations. If this cannot be inferred statically from the loop structure, the attribute `[MaxIters()]` can be used specify a maximum number of iterations. This will be used by compiler to allocate space to store intermediate data. If the actual number of iterations exceeds the provided maximum, the behavior is undefined. You can always mark a loop with the `[ForceUnroll]` attribute to instruct the Slang compiler to unroll the loop before generating derivative propagation functions. Unrolled loops will be treated the same way as ordinary code and are not subject to any additional restrictions. +- Double backward derivatives (higher-order differentiation): The compiler does not currently support multiple backward derivative calls such as `bwd_diff(bwd_diff(fn))`. The vast majority of higher-order derivative applications can be acheived more efficiently via multiple forward-derivative calls or a single layer of `bwd_diff` on functions that use one or more `fwd_diff` passes. + +The above restrictions do not apply if a user-defined derivative or backward propagation function is provided. + +## Reference + +This section contains some additional information for operators that are not currently included in the [standard library reference](https://shader-slang.org/stdlib-reference/) + +### `fwd_diff(f : slang_function) -> slang_function` +The `fwd_diff` operator can be used on a differentiable function to obtain the forward derivative propagation function. + +A forward derivative propagation function computes the derivative of the result value with regard to a specific set of input parameters. +Given an original function, the signature of its forward propagation function is determined using the following rules: +- If the return type `R` implements `IDifferentiable` the forward propagation function will return a corresponding `DifferentialPair` that consists of both the computed original result value and the (partial) derivative of the result value. Otherwise, the return type is kept unmodified as `R`. +- If a parameter has type `T` that implements `IDifferentiable`, it will be translated into a `DifferentialPair` parameter in the derivative function, where the differential component of the `DifferentialPair` holds the initial derivatives of each parameter with regard to their upstream parameters. +- If a parameter has type `T` that implements `IDifferentiablePtrType`, it will be translated into a `DifferentialPtrPair` parameter where the differential component references the differential component. +- All parameter directions are unchanged. For example, an `out` parameter in the original function will remain an `out` parameter in the derivative function. +- Differentiable methods cannot have a type implementing `IDifferentiablePtrType` as an `out` or `inout` parameter, or a return type. Types implementing `IDifferentiablePtrType` can only be used for input parameters to a differentiable method. Marking such a method as `[Differentiable]` will result in a compile-time diagnostic error. + +For example, given original function: +```csharp +[Differentiable] +R original(T0 p0, inout T1 p1, T2 p2, T3 p3); +``` +Where `R`, `T0`, `T1 : IDifferentiable`, `T2` is non-differentiable, and `T3 : IDifferentiablePtrType`, the forward derivative function will have the following signature: +```csharp +DifferentialPair derivative(DifferentialPair p0, inout DifferentialPair p1, T2 p2, DifferentialPtrPair p3); +``` + +This forward propagation function takes the initial primal value of `p0` in `p0.p`, and the partial derivative of `p0` with regard to some upstream parameter in `p0.d`. It takes the initial primal and derivative values of `p1` and updates `p1` to hold the newly computed value and propagated derivative. Since `p2` is not differentiable, it remains unchanged. + +### `bwd_diff(f : slang_function) -> slang_function` + +A backward derivative propagation function propagates the derivative of the function output to all the input parameters simultaneously. + +Given an original function `f`, the general rule for determining the signature of its backward propagation function is that a differentiable output `o` becomes an input parameter holding the partial derivative of a downstream output with regard to the differentiable output, i.e. $$\partial y/\partial o$$; an input differentiable parameter `i` in the original function will become an output in the backward propagation function, holding the propagated partial derivative $$\partial y/\partial i$$; and any non-differentiable outputs are dropped from the backward propagation function. This means that the backward propagation function never returns any values computed in the original function. + +More specifically, the signature of its backward propagation function is determined using the following rules: +- A backward propagation function always returns `void`. +- A differentiable `in` parameter of type `T : IDifferentiable` will become an `inout DifferentialPair` parameter, where the original value part of the differential pair contains the original value of the parameter to pass into the back-prop function. The original value will not be overwritten by the backward propagation function. The propagated derivative will be written to the derivative part of the differential pair after the backward propagation function returns. The initial derivative value of the pair is ignored as input. +- A differentiable `out` parameter of type `T : IDifferentiable` will become an `in T.Differential` parameter, carrying the partial derivative of some downstream term with regard to the return value. +- A differentiable `inout` parameter of type `T : IDifferentiable` will become an `inout DifferentialPair` parameter, where the original value of the argument, along with the downstream partial derivative with regard to the argument is passed as input to the backward propagation function as the original and derivative part of the pair. The propagated derivative with regard to this input parameter will be written back and replace the derivative part of the pair. The primal value part of the parameter will *not* be updated. +- A differentiable return value of type `R` will become an additional `in R.Differential` parameter at the end of the backward propagation function parameter list, carrying the result derivative of a downstream term with regard to the return value of the original function. +- A non-differentiable return value of type `NDR` will be dropped. +- A non-differentiable `in` parameter of type `ND` will remain unchanged in the backward propagation function. +- A non-differentiable `out` parameter of type `ND` will be removed from the parameter list of the backward propagation function. +- A non-differentiable `inout` parameter of type `ND` will become an `in ND` parameter. +- Types implemented `IDifferentiablePtrType` work the same was as the forward-mode case. They can only be used with `in` parameters, and are converted into `DifferentialPtrPair` types. Their directions are **not** affected. + +For example consider the following original function: +```csharp +struct T : IDifferentiable {...} +struct R : IDifferentiable {...} +struct P : IDifferentiablePtrType {...} +struct ND {} // Non differentiable + +[Differentiable] +R original(T p0, out T p1, inout T p2, ND p3, out ND p4, inout ND p5, P p6); +``` +The signature of its backward propagation function is: +```csharp +void back_prop( + inout DifferentialPair p0, + T.Differential p1, + inout DifferentialPair p2, + ND p3, + ND p5, + DifferentialPtrPair

    p6, + R.Differential dResult); +``` +Note that although `p2` is still `inout` in the backward propagation function, the backward propagation function will only write propagated derivative to `p2.d` and will not modify `p2.p`. + +### Built-in Differentiable Functions + +The following built-in functions are differentiable and both their forward and backward derivative functions are already defined in the standard library's core module: + +- Arithmetic functions: `abs`, `max`, `min`, `sqrt`, `rcp`, `rsqrt`, `fma`, `mad`, `fmod`, `frac`, `radians`, `degrees` +- Interpolation and clamping functions: `lerp`, `smoothstep`, `clamp`, `saturate` +- Trigonometric functions: `sin`, `cos`, `sincos`, `tan`, `asin`, `acos`, `atan`, `atan2` +- Hyperbolic functions: `sinh`, `cosh`, `tanh` +- Exponential and logarithmic functions: `exp`, `exp2`, `pow`, `log`, `log2`, `log10` +- Vector functions: `dot`, `cross`, `length`, `distance`, `normalize`, `reflect`, `refract` +- Matrix transforms: `mul(matrix, vector)`, `mul(vector, matrix)`, `mul(matrix, matrix)` +- Matrix operations: `transpose`, `determinant` +- Legacy blending and lighting intrinsics: `dst`, `lit` \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/08-compiling.md b/lib/All/slang/share/doc/slang/user-guide/08-compiling.md new file mode 100644 index 0000000..c857a65 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/08-compiling.md @@ -0,0 +1,996 @@ +--- +layout: user-guide +permalink: /user-guide/compiling +--- + +Compiling Code with Slang +========================= + +This chapter presents the ways that the Slang system supports compiling and composing shader code. +We will start with a discussion of the mental model that Slang uses for compilation. +Next we will cover the command-line Slang compiler, `slangc`, and how to use it to perform offline compilation. +Finally we will discuss the Slang compilation API, which can be used to integrate Slang compilation into an application at runtime, or to build custom tools that implement application-specific compilation policy. + +## Concepts + +For simple scenarios it may be enough to think of a shader compiler as a box where source code goes in and compiled kernels come out. +Most real-time graphics applications end up needing more control over shader compilation, and/or more information about the results of compilation. +In order to make use of the services provided by the Slang compilation system, it is useful to start with a clear model of the concepts that are involved in compilation. + +### Source Units + +At the finest granularity, code is fed to the compiler in _source units_ which are most often stored as files on disk or strings of text in memory. +The compilation model largely does not care whether source units have been authored by human programmers or automatically assembled by other tools. + +If multiple source units are specified as part of the same compile, they will be preprocessed and parsed independently. +However, a source unit might contain `#include` directives, so that the preprocessed text of that source unit includes the content of other files. +Note that the `#include`d files do not become additional source units; they are just part of the text of a source unit that was fed to the compiler. + +### Translation Units and Modules + +Source units (such as files) are grouped into _translation units_, and each translation unit will produce a single _module_ when compiled. + +While the source units are all preprocessed and parsed independently, semantic checking is applied to a translation unit as a whole. +One source file in a translation unit may freely refer to declarations in another source file from the same translation unit without any need for forward declarations. For example: + +```hlsl +// A.slang + +float getFactor() { return 10.0; } +``` + +```hlsl +// B.slang + +float scaleValue(float value) +{ + return value * getFactor(); +} +``` + +In this example, the `scaleValue()` function in `B.slang` can freely refer to the `getFactor()` function in `A.slang` because they are part of the same translation unit. + +It is allowed, and indeed common, for a translation unit to contain only a single source unit. +For example, when adapting an existing codebase with many `.hlsl` files, it is appropriate to compile each `.hlsl` file as its own translation unit. +A modernized codebase that uses modular `include` feature as documented in [Modules and Access Control](modules) might decide to compile multiple `.slang` files in a single directory as a single translation unit. + +The result of compiling a translation unit is a module in Slang's internal intermediate representation (IR). The compiled module can then be serialized to a `.slang-module` binary file. The binary file can then be loaded via the +`ISession::loadModuleFromIRBlob` function or `import`ed in slang code the same way as modules written in `.slang` files. + +### Entry Points + +A translation unit / module may contain zero or more entry points. +Slang supports two models for identifying entry points when compiling. + +#### Entry Point Attributes + +By default, the compiler will scan a translation unit for function declarations marked with the `[shader(...)]` attribute; each such function will be identified as an entry point in the module. +Developers are encouraged to use this model because it directly documents intention and makes source code less dependent on external compiler configuration options. + +#### Explicit Entry Point Options + +For compatibility with existing code, the Slang compiler also supports explicit specification of entry point functions using configuration options external to shader source code. +When these options are used the compiler will *ignore* all `[shader(...)]` attributes and only use the explicitly-specified entry points instead. + +### Shader Parameters + +A translation unit / module may contain zero or more global shader parameters. +Similarly, each entry point may define zero or more entry-point `uniform` shader parameters. + +The shader parameters of a module or entry point are significant because they describe the interface between host application code and GPU code. +It is important that both the application and generated GPU kernel code agree on how parameters are laid out in memory and/or how they are assigned to particular API-defined registers, locations, or other "slots." + +### Targets + +Within the Slang system a _target_ represents a particular platform and set of capabilities that output code can be generated for. +A target includes information such as: + +* The _format_ that code should be generated in: SPIR-V, DXIL, etc. + +* A _profile_ that specifies a general feature/capability level for the target: D3D Shader Model 5.1, GLSL version 4.60, etc. + +* Optional _capabilities_ that should be assumed available on the target: for example, specific Vulkan GLSL extensions + +* Options that impact code generation: floating-point strictness, level of debug information to generate, etc. + +Slang supports compiling for multiple targets in the same compilation session. +When using multiple targets at a time, it is important to understand the distinction between the _front-end_ of the compiler, and the _back-end_: + +* The compiler front-end comprises preprocessing, parsing, and semantic checking. The front-end runs once for each translation unit and its results are shared across all targets. + +* The compiler back-end generates output code, and thus runs once per target. + +> #### Note #### +> Because front-end actions, including preprocessing, only run once, across all targets, the Slang compiler does not automatically provide any target-specific preprocessor `#define`s that can be used for preprocessor conditionals. +> Applications that need target-specific `#define`s should always compile for one target at a time, and set up their per-target preprocessor state manually. + +### Layout + +While the front-end of the compiler determines what the shader parameters of a module or entry point are, the _layout_ for those parameters is dependent on a particular compilation target. +A `Texture2D` might consume a `t` register for Direct3D, a `binding` for Vulkan, or just plain bytes for CUDA. + +The details of layout in Slang will come in a later chapter. +For the purposes of the compilation model it is important to note that the layout computed for shader parameters depends on: + +* What modules and entry points are being used together; these define which parameters are relevant. + +* Some well-defined ordering of those parameters; this defines which parameters should be laid out before which others. + +* The rules and constraints that the target imposes on layout. + +An important design choice in Slang is give the user of the compiler control over these choices. + +### Composition + +The user of the Slang compiler communicates the modules and entry points that will be used together, as well as their relative order, using a system for _composition_. + +A _component type_ is a unit of shader code composition; both modules and entry points are examples of component types. +A _composite_ component type is formed from a list of other component types (for example, one module and two entry points) and can be used to define a unit of shader code that is meant to be used together. + +Once a programmer has formed a composite of all the code they intend to use together, they can query the layout of the shader parameters in that composite, or invoke the linking step to +resolve all cross module references. + +### Linking + +A user-composed program may have transitive module dependencies and cross references between module boundaries. The linking step in Slang is to resolve all the cross references in the IR and produce a +new self-contained IR module that has everything needed for target code generation. The user will have an opportunity to specialize precompiled modules or provide additional compiler backend options +at the linking step. + +### Kernels + +Once a program is linked, the user can request generation of the _kernel_ code for an entry point. +The same entry point can be used to generate many different kernels. +First, an entry point can be compiled for different targets, resulting in different kernels in the appropriate format for each target. +Second, different compositions of shader code can result in different layouts, which leads to different kernels being required. + +## Command-Line Compilation with `slangc` + +The `slangc` tool, included in binary distributions of Slang, is a command-line compiler that can handle most simple compilation tasks. +`slangc` is intended to be usable as a replacement for tools like `fxc` and `dxc`, and covers most of the same use cases. + +### All Available Options + +See [slangc command line reference](https://github.com/shader-slang/slang/blob/master/docs/command-line-slangc-reference.md) for a complete list of compiler options supported by the `slangc` tool. + + +### A Simple `slangc` Example + +Here we will repeat the example used in the [Getting Started](01-get-started.md) chapter. +Given the following Slang code: + +```hlsl +// hello-world.slang +StructuredBuffer buffer0; +StructuredBuffer buffer1; +RWStructuredBuffer result; + +[shader("compute")] +[numthreads(1,1,1)] +void computeMain(uint3 threadId : SV_DispatchThreadID) +{ + uint index = threadId.x; + result[index] = buffer0[index] + buffer1[index]; +} +``` + +we can compile the `computeMain()` entry point to SPIR-V using the following command line: + +```bat +slangc hello-world.slang -target spirv -o hello-world.spv +``` + +> #### Note #### +> Some targets require additional parameters. See [`slangc` Entry Points](#slangc-entry-points) for details. For example, to target HLSL, the equivalent command is: +> +> ```bat +> slangc hello-world.slang -target hlsl -entry computeMain -o hello-world.hlsl +> ``` + +### Source Files and Translation Units + +The `hello-world.slang` argument here is specifying an input file. +Each input file specified on the command line will be a distinct source unit during compilation. +Slang supports multiple file-name extensions for input files, but the most common ones will be `.hlsl` for existing HLSL code, and `.slang` for files written specifically for Slang. + +If multiple source files are passed to `slangc`, they will be grouped into translation units using the following rules: + +* If there are any `.slang` files, then all of them will be grouped into a single translation unit + +* Each `.hlsl` file will be grouped into a distinct translation unit of its own. + +* Each `.slang-module` file forms its own translation unit. + +### `slangc` Entry Points + +When using `slangc`, you will typically want to identify which entry point(s) you intend to compile. +The `-entry computeMain` option selects an entry point to be compiled to output code in this invocation of `slangc`. + +Because the `computeMain()` entry point in this example has a `[shader(...)]` attribute, the compiler is able to deduce that it should be compiled for the `compute` stage. + +```bat +slangc hello-world.slang -target spirv -o hello-world.spv +``` + +In code that does not use `[shader(...)]` attributes, a `-entry` option should be followed by a `-stage` option to specify the stage of the entry point: + +```bat +slangc hello-world.slang -entry computeMain -stage compute -target spirv -o hello-world.spv +``` + +> #### Note #### +> The `slangc` CLI [currently](https://github.com/shader-slang/slang/issues/5541) cannot automatically deduce `-entrypoint` and `-stage`/`-profile` options from `[shader(...)]` attributes when generating code for targets other than SPIRV, Metal, CUDA, or Optix. For targets such as HLSL, please continue to specify `-entry` and `-stage` options, even when compiling a file with the `[shader(...)]` attribute on its entry point. + +### `slangc` Targets + +Our example uses the option `-target spirv` to introduce a compilation target; in this case, code will be generated as SPIR-V. +The argument of a `-target` option specified the format to use for the target; common values are `dxbc`, `dxil`, and `spirv`. + +Additional options for a target can be specified after the `-target` option. +For example, a `-profile` option can be used to specify a profile that should be used. +Slang provides two main kinds of profiles for use with `slangc`: + +* Direct3D "Shader Model" profiles have names like `sm_5_1` and `sm_6_3` + +* GLSL versions can be used as profile with names like `glsl_430` and `glsl_460` + +### `slangc` Kernels + +A `-o` option indicates that kernel code should be written to a file on disk. +In our example, the SPIR-V kernel code for the `computeMain()` entry point will be written to the file `hello-world.spv`. + +### Working with Multiples + +It is possible to use `slangc` with multiple input files, entry points, or targets. +In these cases, the ordering of arguments on the command line becomes significant. + +When an option modifies or relates to another command-line argument, it implicitly applies to the most recent relevant argument. +For example: + +* If there are multiple input files, then an `-entry` option applies to the preceding input file + +* If there are multiple entry points, then a `-stage` option applies to the preceding `-entry` option + +* If there are multiple targets, then a `-profile` option applies to the preceding `-target` option + +Kernel `-o` options are the most complicated case, because they depend on both a target and entry point. +A `-o` option applies to the preceding entry point, and the compiler will try to apply it to a matching target based on its file extension. +For example, a `.spv` output file will be matched to a `-target spirv`. + +The compiler makes a best effort to support complicated cases with multiple files, entry points, and targets. +Users with very complicated compilation requirements will probably be better off using multiple `slangc` invocations or migrating to the compilation API. + +### Additional Options + +The main other options are: + +* `-D` or `-D=` can be used to introduce preprocessor macros. + +* `-I` or `-I ` can be used to introduce a _search path_ to be used when resolving `#include` directives and `import` declarations. + +* `-g` can be used to enable inclusion of debug information in output files (where possible and implemented) + +* `-O` can be used to control optimization levels when the Slang compiler invokes downstream code generator + +See [slangc command line reference](https://github.com/shader-slang/slang/blob/master/docs/command-line-slangc-reference.md) for a complete list of compiler options supported by the `slangc` tool. + +### Downstream Arguments + +`slangc` may leverage a 'downstream' tool like 'dxc', 'fxc', 'glslang', or 'gcc' for some target compilations. Rather than replicate every possible downstream option, arguments can be passed directly to the downstream tool using the "-X" option in `slangc`. + +The mechanism used here is based on the `-X` mechanism used in GCC, to specify arguments to the linker. + +``` +-Xlinker option +``` + +When used, `option` is not interpreted by GCC, but is passed to the linker once compilation is complete. Slang extends this idea in several ways. First there are many more 'downstream' stages available to Slang than just `linker`. These different stages are known as `SlangPassThrough` types in the API and have the following names + +* `fxc` - FXC HLSL compiler +* `dxc` - DXC HLSL compiler +* `glslang` - GLSLANG GLSL compiler +* `visualstudio` - Visual Studio C/C++ compiler +* `clang` - Clang C/C++ compiler +* `gcc` - GCC C/C++ compiler +* `genericcpp` - A generic C++ compiler (can be any one of visual studio, clang or gcc depending on system and availability) +* `nvrtc` - NVRTC CUDA compiler + +The Slang command line allows you to specify an argument to these downstream compilers, by using their name after the `-X`. So for example to send an option `-Gfa` through to DXC you can use + +``` +-Xdxc -Gfa +``` + +Note that if an option is available via normal Slang command line options then these should be used. This will generally work across multiple targets, but also avoids options clashing which is undefined behavior currently. The `-X` mechanism is best used for options that are unavailable through normal Slang mechanisms. + +If you want to pass multiple options using this mechanism the `-Xdxc` needs to be in front of every options. For example + +``` +-Xdxc -Gfa -Xdxc -Vd +``` + +Would reach `dxc` as + +``` +-Gfa -Vd +``` + +This can get a little repetitive especially if there are many parameters, so Slang adds a mechanism to have multiple options passed by using an ellipsis `...`. The syntax is as follows + +``` +-Xdxc... -Gfa -Vd -X. +``` + +The `...` at the end indicates all the following parameters should be sent to `dxc` until it reaches the matching terminating `-X.` or the end of the command line. + +It is also worth noting that `-X...` options can be nested. This would allow a GCC downstream compilation to control linking, for example with + +``` +-Xgcc -Xlinker --split -X. +``` + +In this example gcc would see + +``` +-Xlinker --split +``` + +And the linker would see (as passed through by gcc) + +``` +--split +``` + +Setting options for tools that aren't used in a Slang compilation has no effect. This allows for setting `-X` options specific for all downstream tools on a command line, and they are only used as part of a compilation that needs them. + +NOTE! Not all tools that Slang uses downstream make command line argument parsing available. `FXC` and `GLSLANG` currently do not have any command line argument passing as part of their integration, although this could change in the future. + +The `-X` mechanism is also supported by render-test tool. In this usage `slang` becomes a downstream tool. Thus you can use the `dxc` option `-Gfa` in a render-test via + +``` +-Xslang... -Xdxc -Gfa -X. +``` + +Means that the dxc compilation in the render test (assuming dxc is invoked) will receive + +``` +-Gfa +``` + +Some options are made available via the same mechanism for all downstream compilers. + +* Use `-I` to specify include path for downstream compilers + +For example to specify an include path "somePath" to DXC you can use... + +``` +-Xdxc -IsomePath +``` + + +### Convenience Features + +The `slangc` compiler provides a few conveniences for command-line compilation: + +* Most options can appear out of order when they are unambiguous. For example, if there is only a single translation unit a `-entry` option can appear before or after any file. + +* A `-target` option can be left out if it can be inferred from the only `-o` option present. For example, `-o hello-world.spv` already implies `-target spirv`. + +* If a `-o` option is left out then kernel code will be written to the standard output. This output can be piped to a file, or can be printed to a console. In the latter case, the compiler will automatically disassemble binary formats for printing. + +### Precompiled Modules + +You can compile a `.slang` file into a binary IR module. For example, given the following source: + +```hlsl +// my_library.slang +float myLibFunc() { return 5.0; } +``` + +You can compile it into `my_library.slang-module` with the following slangc command line: + +```bat +slangc my_library.slang -o my_library.slang-module +``` + +This allows you to deploy just the `my_library.slang-module` file to users of the module, and it can be consumed in the user code with the same `import` syntax: +```hlsl +import my_library; +``` + +### Limitations + +The `slangc` tool is meant to serve the needs of many developers, including those who are currently using `fxc`, `dxc`, or similar tools. +However, some applications will benefit from deeper integration of the Slang compiler into application-specific code and workflows. +Notable features that Slang supports which cannot be accessed from `slangc` include: + +* Slang can provide _reflection_ information about shader parameters and their layouts for particular targets; this information is not currently output by `slangc`. + +* Slang allows applications to control the way that shader modules and entry points are composed (which in turn influences their layout); `slangc` currently implements a single default policy for how to generate a composition of shader code. + +Applications that need more control over compilation are encouraged to use the C++ compilation API described in the next section. + +### Examples of `slangc` usage + +#### Multiple targets and multiple entrypoints + +In this example, there are two shader entrypoints defined in one source file. + +```hlsl +// targets.slang + +struct VertexOutput +{ + nointerpolation int a : SOME_VALUE; + float3 b : SV_Position; +}; + +[shader("pixel")] +float4 psMain() : SV_Target +{ + return float4(1, 0, 0, 1); +} + +[shader("vertex")] +VertexOutput vsMain() +{ + VertexOutput out; + out.a = 0; + out.b = float4(0, 1, 0, 1); + return out; +} +``` + +A single entrypoint from the preceding shader can be compiled to both SPIR-V Assembly and HLSL targets in one command: +```bat +slangc targets.slang -entry psMain -target spirv-asm -o targets.spv-asm -target hlsl -o targets.hlsl +``` + +The following command compiles both entrypoints to SPIR-V: + +```bat +slangc targets.slang -entry vsMain -entry psMain -target spirv -o targets.spv +``` + +#### Creating a standalone executable example + +This example compiles and runs a CPU host-callable style Slang unit. + +```hlsl +// cpu.slang + +class MyClass +{ + int intMember; + __init() + { + intMember = 0; + } + int method() + { + printf("method\n"); + return intMember; + } +} + +export __extern_cpp int main() +{ + MyClass obj = new MyClass(); + return obj.method(); +} + +``` + +Compile the above code as standalone executable, using -I option to find dependent header files: +```bat +slangc cpu.slang -target executable -o cpu.exe -Xgenericcpp -I./include -Xgenericcpp -I./external/unordered_dense/include/ +``` + +Execute the resulting executable: +```bat +C:\slang> cpu +method + +``` + +#### Compiling and linking slang-modules + +This example demonstrates the compilation of a slang-module, and linking to a shader which uses that module. +Two scenarios are provided, one in which the entry-point is compiled in the same `slangc` invocation that links in the dependent slang-module, and another scenario where linking is a separate invocation. + +```hlsl +// lib.slang +public int foo(int a) +{ + return a + 1; +} +``` + +```hlsl +// entry.slang +import "lib"; + +RWStructuredBuffer outputBuffer; + +[shader("compute")] +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int index = (int)dispatchThreadID.x; + outputBuffer[index] = foo(index); +} +``` + +Compile lib.slang to lib.slang-module: +```bat +slangc lib.slang -o lib.slang-module +``` + +Scenario 1: Compile entry.slang and link lib and entry together in one step: +```bat +slangc entry.slang -target spirv -o program.spv # Compile and link +``` + +Scenario 2: Compile entry.slang to entry.slang-module and then link together lib and entry in a second invocation: +```bat +slangc entry.slang -o entry.slang-module # Compile +slangc lib.slang-module entry.slang-module -target spirv -o program.spv # Link +``` + +#### Compiling with debug symbols + +Debug symbols can be added with the "-g" option. + +Adding '-g1' (or higher) to a SPIR-V compilation will emit extended 'DebugInfo' instructions. +```bat +slangc vertex.slang -target spirv-asm -o v.spv-asm -g0 # Omit debug symbols +slangc vertex.slang -target spirv-asm -o v.spv-asm -g1 # Add debug symbols +``` + + +#### Compiling with additional preprocessor macros + +User-defined macros can be set on the command-line with the "-D" or "-D=" option. + +```hlsl +// macrodefine.slang + +[shader("pixel")] +float4 psMain() : SV_Target +{ +#if defined(mymacro) + return float4(1, 0, 0, 1); +#else + return float4(0, 1, 0, 1); +#endif +} +``` + +* Setting a user-defined macro "mymacro" +```bat +slangc macrodefine.slang -entry psMain -target spirv-asm -o targets.spvasm -Dmymacro +``` + +## Using the Compilation API + +The C++ API provided by Slang is meant to provide more complete control over compilation for applications that need it. +The additional level of control means that some tasks require more individual steps than they would when using a one-size-fits-all tool like `slangc`. + +### "COM-lite" Components + +Many parts of the Slang C++ API use interfaces that follow the design of COM (the Component Object Model). +Some key Slang interfaces are binary-compatible with existing COM interfaces. +However, the Slang API does not depend on any runtime aspects of the COM system, even on Windows; the Slang system can be seen as a "COM-lite" API. + +The `ISlangUnknown` interface is equivalent to (and binary-compatible with) the standard COM `IUnknown`. +Application code is expected to correctly maintain the reference counts of `ISlangUnknown` objects returned from API calls; the `Slang::ComPtr` "smart pointer" type is provided as an optional convenience for applications that want to use it. + +Many Slang API calls return `SlangResult` values; this type is equivalent to (and binary-compatible with) the standard COM `HRESULT` type. +As a matter of convention, Slang API calls return a zero value (`SLANG_OK`) on success, and a negative value on errors. + +> #### Note #### +> Slang API interfaces may be named with the suffix "_Experimental", indicating that the interface is not complete, may have known bugs, and may change or be removed between Slang API releases. + +### Creating a Global Session + +A Slang _global session_ uses the interface `slang::IGlobalSession` and it represents a connection from an application to a particular implementation of the Slang API. +A global session is created using the function `slang::createGlobalSession()`: + +```c++ +using namespace slang; + +Slang::ComPtr globalSession; +SlangGlobalSessionDesc desc = {}; +createGlobalSession(&desc, globalSession.writeRef()); +``` + +When a global session is created, the Slang system will load its internal representation of the _core module_ that the compiler provides to user code. +The core module can take a significant amount of time to load, so applications are advised to use a single global session if possible, rather than creating and then disposing of one for each compile. + +If you want to enable GLSL compatibility mode, you need to set `SlangGlobalSessionDesc::enableGLSL` to `true` when calling `createGlobalSession()`. This will load the necessary GLSL intrinsic module +for compiling GLSL code. Without this setting, compiling GLSL code will result in an error. + +> #### Note #### +> Currently, the global session type is *not* thread-safe. +> Applications that wish to compile on multiple threads will need to ensure that each concurrent thread compiles with a distinct global session. + +> #### Note #### +> Currently, the global session should be freed after any objects created from it. +> See [issue 6344](https://github.com/shader-slang/slang/issues/6344). + +### Creating a Session + +A _session_ uses the interface `slang::ISession`, and represents a scope for compilation with a consistent set of compiler options. +In particular, all compilation with a single session will share: + +* A list of enabled compilation targets (with their options) + +* A list of search paths (for `#include` and `import`) + +* A list of pre-defined macros + +In addition, a session provides a scope for the loading and re-use of modules. +If two pieces of code compiled in a session both `import` the same module, then that module will only be loaded and compiled once. + +To create a session, use the `IGlobalSession::createSession()` method: + +```c++ +SessionDesc sessionDesc; +/* ... fill in `sessionDesc` ... */ +Slang::ComPtr session; +globalSession->createSession(sessionDesc, session.writeRef()); +``` + +The definition of `SessionDesc` structure is: +```C++ +struct SessionDesc +{ + /** The size of this structure, in bytes. + */ + size_t structureSize = sizeof(SessionDesc); + + /** Code generation targets to include in the session. + */ + TargetDesc const* targets = nullptr; + SlangInt targetCount = 0; + + /** Flags to configure the session. + */ + SessionFlags flags = kSessionFlags_None; + + /** Default layout to assume for variables with matrix types. + */ + SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + /** 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; + + ISlangFileSystem* fileSystem = nullptr; + + bool enableEffectAnnotations = false; + bool allowGLSLSyntax = false; + + /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. + */ + CompilerOptionEntry* compilerOptionEntries = nullptr; + + /** Number of additional compiler option entries. + */ + uint32_t compilerOptionEntryCount = 0; +}; +``` +The user can specify a set of commonly used compiler options directly in the `SessionDesc` struct, such as `searchPath` and `preprocessMacros`. +Additional compiler options can be specified via the `compilerOptionEntries` field, which is an array of `CompilerOptionEntry` that defines a key-value +pair of a compiler option setting, see the [Compiler Options](#compiler-options) section. + +#### Targets + +The `SessionDesc::targets` array can be used to describe the list of targets that the application wants to support in a session. +Often, this will consist of a single target. + +Each target is described with a `TargetDesc` which includes options to control code generation for the target. +The most important fields of the `TargetDesc` are the `format` and `profile`; most others can be left at their default values. + +The `format` field should be set to one of the values from the `SlangCompileTarget` enumeration. +For example: + +```c++ +TargetDesc targetDesc; +targetDesc.format = SLANG_SPIRV; +``` + +The `profile` field must be set with the ID of one of the profiles supported by the Slang compiler. +The exact numeric value of the different profiles is not currently stable across compiler versions, so applications should look up a chosen profile using `IGlobalSession::findProfile`. +For example: + +```c++ +targetDesc.profile = globalSession->findProfile("glsl_450"); +``` + +Once the chosen `TargetDesc`s have been initialized, they can be attached to the `SessionDesc`: + +```c++ +sessionDesc.targets = &targetDesc; +sessionDesc.targetCount = 1; +``` + +#### Search Paths + +The search paths on a session provide the paths where the compiler will look when trying to resolve a `#include` directive or `import` declaration. +The search paths can be set in the `SessionDesc` as an array of `const char*`: + +```c++ +const char* searchPaths[] = { "myapp/shaders/" }; +sessionDesc.searchPaths = searchPaths; +sessionDesc.searchPathCount = 1; +``` + +#### Pre-Defined Macros + +The pre-defined macros in a session will be visible at the start of each source unit that is compiled, including source units loaded via `import`. +Each pre-defined macro is described with a `PreprocessorMacroDesc`, which has `name` and `value` fields: + +```c++ +PreprocessorMacroDesc fancyFlag = { "ENABLE_FANCY_FEATURE", "1" }; +sessionDesc.preprocessorMacros = &fancyFlag; +sessionDesc.preprocessorMacroCount = 1; +``` + +#### More Options + +You can specify other compiler options for the session or for a specific target through the `compilerOptionEntries` and `compilerOptionEntryCount` fields +of the `SessionDesc` or `TargetDesc` structures. See the [Compiler Options](#compiler-options) section for more details on how to encode such an array. + +### Loading a Module + +The simplest way to load code into a session is with `ISession::loadModule()`: + +```c++ +IModule* module = session->loadModule("MyShaders"); +``` + +Executing `loadModule("MyShaders")` in host C++ code is similar to using `import MyShaders` in Slang code. +The session will search for a matching module (usually in a file called `MyShaders.slang`) and will load and compile it (if it hasn't been done already). + +Note that `loadModule()` does not provide any ways to customize the compiler configuration for that specific module. +The preprocessor environment, search paths, and targets will always be those specified for the session. + +### Capturing Diagnostic Output + +Compilers produce various kinds of _diagnostic_ output when compiling code. +This includes not only error messages when compilation fails, but also warnings and other helpful messages that may be produced even for successful compiles. + +Many operations in Slang, such as `ISession::loadModule()` can optionally produce a _blob_ of diagnostic output. +For example: + +```c++ +Slang::ComPtr diagnostics; +Slang::ComPtr module(session->loadModule("MyShaders", diagnostics.writeRef())); +``` + +In this example, if any diagnostic messages were produced when loading `MyShaders`, then the `diagnostics` pointer will be set to a blob that contains the textual content of those diagnostics. + +The content of a blob can be accessed with `getBufferPointer()`, and the size of the content can be accessed with `getBufferSize()`. +Diagnostic blobs produces by the Slang compiler are always null-terminated, so that they can be used with C-style string APIs: + +```c++ +if(diagnostics) +{ + fprintf(stderr, "%s\n", (const char*) diagnostics->getBufferPointer()); +} +``` + +> #### Note #### +> The `slang::IBlob` interface is binary-compatible with the `ID3D10Blob` and `ID3DBlob` interfaces used by some Direct3D compilation APIs. + +### Entry Points + +When using `loadModule()` applications should ensure that entry points in their shader code are always marked with appropriate `[shader(...)]` attributes. +For example, if `MyShaders.slang` contained: + +```hlsl +[shader("compute")] +void myComputeMain(...) { ... } +``` + +then the Slang system will automatically detect and validate this entry point as part of a `loadModule("MyShaders")` call. + +After a module has been loaded, the application can look up entry points in that module using `IModule::findEntryPointByName()`: + +```c++ +Slang::ComPtr computeEntryPoint; +module->findEntryPointByName("myComputeMain", computeEntryPoint.writeRef()); +``` + +### Composition + +An application might load any number of modules with `loadModule()`, and those modules might contain any number of entry points. +Before GPU kernel code can be generated it is first necessary to decide which pieces of GPU code will be used together. + +Both `slang::IModule` and `slang::IEntryPoint` inherit from `slang::IComponentType`, because both can be used as components when composing a shader program. +A composition can be created with `ISession::createCompositeComponentType()`: + +```c++ +IComponentType* components[] = { module, entryPoint }; +Slang::ComPtr program; +session->createCompositeComponentType(components, 2, program.writeRef()); +``` + +As discussed earlier in this chapter, the composition operation serves two important purposes. +First, it establishes which code is part of a compiled shader program and which is not. +Second, it established an ordering for the code in a program, which can be used for layout. + +### Layout and Reflection + +Some applications need to perform reflection on shader parameters and their layout, whether at runtime or as part of an offline compilation tool. +The Slang API allows layout to be queried on any `IComponentType` using `getLayout()`: + +```c++ +slang::ProgramLayout* layout = program->getLayout(); +``` + +> #### Note #### +> In the current Slang API, the `ProgramLayout` type is not reference-counted. +> Currently, the lifetime of a `ProgramLayout` is tied to the `IComponentType` that returned it. +> An application must ensure that it retains the given `IComponentType` for as long as it uses the `ProgramLayout`. + +Note that because both `IModule` and `IEntryPoint` inherit from `IComponentType`, they can also be queried for their layouts individually. +The layout for a module comprises just its global-scope parameters. +The layout for an entry point comprises just its entry-point parameters (both `uniform` and varying). + +The details of how Slang computes layout, what guarantees it makes, and how to inspect the reflection information will be discussed in a later chapter. + +Because the layout computed for shader parameters may depend on the compilation target, the `getLayout()` method actually takes a `targetIndex` parameter that is the zero-based index of the target for which layout information is being queried. +This parameter defaults to zero as a convenience for the common case where applications use only a single compilation target at runtime. + +See [Using the Reflection API](reflection) chapter for more details on the reflection API. + +### Linking + +Before generating code, you must link the program to resolve all cross-module references. This can be done by calling +`IComponentType::link` or `IComponentType::linkWithOptions` if you wish to specify additional compiler options for the program. +For example: +```c++ +Slang::ComPtr linkedProgram; +Slang::ComPtr diagnosticBlob; +program->link(linkedProgram.writeRef(), diagnosticBlob.writeRef()); +``` + +The linking step is also used to perform link-time specialization, which is a recommended approach for shader specialization +compared to preprocessor based specialization. Please see [Link-time Specialization and Precompiled Modules](10-link-time-specialization.md) for more details. + +Any diagnostic messages related to linking (for example, if an external symbol cannot be resolved) will be written to `diagnosticBlob`. + +### Kernel Code + +Given a linked `IComponentType`, an application can extract kernel code for one of its entry points using `IComponentType::getEntryPointCode()`: + +```c++ +int entryPointIndex = 0; // only one entry point +int targetIndex = 0; // only one target +Slang::ComPtr kernelBlob; +linkedProgram->getEntryPointCode( + entryPointIndex, + targetIndex, + kernelBlob.writeRef(), + diagnostics.writeRef()); +``` + +Any diagnostic messages related to back-end code generation (for example, if the chosen entry point requires features not available on the chosen target) will be written to `diagnostics`. +The `kernelBlob` output is a `slang::IBlob` that can be used to access the generated code (whether binary or textual). +In many cases `kernelBlob->getBufferPointer()` can be passed directly to the appropriate graphics API to load kernel code onto a GPU. + + +## Multithreading + +The only functions which are currently thread safe are + +```C++ +SlangSession* spCreateSession(const char* deprecated); +SlangResult slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession); +SlangResult slang_createGlobalSession2(const SlangGlobalSessionDesc* desc, slang::IGlobalSession** outGlobalSession); +SlangResult slang_createGlobalSessionWithoutCoreModule(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession); +ISlangBlob* slang_getEmbeddedCoreModule(); +SlangResult slang::createGlobalSession(slang::IGlobalSession** outGlobalSession); +const char* spGetBuildTagString(); +``` + +This assumes Slang has been built with the C++ multithreaded runtime, as is the default. + +All other functions and methods are not [reentrant](https://en.wikipedia.org/wiki/Reentrancy_(computing)) and can only execute on a single thread. More precisely, functions and methods can only be called on a *single* thread at *any one time*. This means for example a global session can be used across multiple threads, as long as some synchronization enforces that only one thread can be in a Slang call at any one time. + +Much of the Slang API is available through [COM interfaces](https://en.wikipedia.org/wiki/Component_Object_Model). In strict COM, interfaces should be atomically reference counted. Currently *MOST* Slang API COM interfaces are *NOT* atomic reference counted. One exception is the `ISlangSharedLibrary` interface when produced from [host-callable](../cpu-target.md#host-callable). It is atomically reference counted, allowing it to persist and be used beyond the original compilation and be freed on a different thread. + + +## Compiler Options + +Both the `SessionDesc`, `TargetDesc` structures contain fields that encodes a `CompilerOptionEntry` array for additional compiler options to apply on the session or the target. In addition, +the `IComponentType::linkWithOptions()` method allow you to specify additional compiler options when linking a program. All these places accepts the same encoding of compiler options, which is +documented in this section. + +The `CompilerOptionEntry` structure is defined as follows: +```c++ +struct CompilerOptionEntry +{ + CompilerOptionName name; + CompilerOptionValue value; +}; +``` +Where `CompilerOptionName` is an `enum` specifying the compiler option to set, and `value` encodes the value of the option. +`CompilerOptionValue` is a structure that allows you to endcode up to two integer or string values for a compiler option: +```c++ +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; +}; +``` +The meaning of each integer or string value is dependent on the compiler option. The following table lists all available compiler options that can be set and +meanings of their `CompilerOptionValue` encodings. + +|CompilerOptionName | Description | +|:------------------ |:----------- | +| MacroDefine | Specifies a preprocessor macro define entry. `stringValue0` encodes macro name, `stringValue1` encodes the macro value. +| Include | Specifies an additional search path. `stringValue0` encodes the additional path. | +| Language | Specifies the input language. `intValue0` encodes a value defined in `SlangSourceLanguage`. | +| MatrixLayoutColumn | Use column major matrix layout as default. `intValue0` encodes a bool value for the setting. | +| MatrixLayoutRow | Use row major matrix layout as default. `intValue0` encodes a bool value for the setting. | +| Profile | Specifies the target profile. `intValue0` encodes the raw profile representation returned by `IGlobalSession::findProfile()`. | +| Stage | Specifies the target entry point stage. `intValue0` encodes the stage defined in `SlangStage` enum. | +| Target | Specifies the target format. Has same effect as setting TargetDesc::format. | +| WarningsAsErrors | Specifies a list of warnings to be treated as errors. `stringValue0` encodes a comma separated list of warning codes or names, or can be "all" to indicate all warnings. | +| DisableWarnings | Specifies a list of warnings to disable. `stringValue0` encodes comma separated list of warning codes or names. | +| EnableWarning | Specifies a list of warnings to enable. `stringValue0` encodes comma separated list of warning codes or names. | +| DisableWarning | Specify a warning to disable. `stringValue0` encodes the warning code or name. | +| ReportDownstreamTime | Turn on/off downstream compilation time report. `intValue0` encodes a bool value for the setting. | +| ReportPerfBenchmark | Turn on/off reporting of time spend in different parts of the compiler. `intValue0` encodes a bool value for the setting. | +| SkipSPIRVValidation | Specifies whether or not to skip the validation step after emitting SPIRV. `intValue0` encodes a bool value for the setting. | +| Capability | Specify an additional capability available in the compilation target. `intValue0` encodes a capability defined in the `CapabilityName` enum. | +| DefaultImageFormatUnknown | Whether or not to use `unknown` as the image format when emitting SPIRV for a texture/image resource parameter without a format specifier. `intValue0` encodes a bool value for the setting. | +| DisableDynamicDispatch | (Internal use only) Disables generation of dynamic dispatch code. `intValue0` encodes a bool value for the setting. | +| DisableSpecialization | (Internal use only) Disables specialization pass. `intValue0` encodes a bool value for the setting. | +| FloatingPointMode | Specifies the floating point mode. `intValue0` encodes the floating mode point defined in the `SlangFloatingPointMode` enum. | +| DebugInformation | Specifies the level of debug information to include in the generated code. `intValue0` encodes an value defined in the `SlangDebugInfoLevel` enum. | +| LineDirectiveMode | Specifies the line directive mode to use the generated textual code such as HLSL or CUDA. `intValue0` encodes an value defined in the `SlangLineDirectiveMode` enum. | +| Optimization | Specifies the optimization level. `intValue0` encodes the value for the setting defined in the `SlangOptimizationLevel` enum. | +| Obfuscate | Specifies whether or not to turn on obfuscation. When obfuscation is on, Slang will strip variable and function names from the target code and replace them with hash values. `intValue0` encodes a bool value for the setting. | +| VulkanBindShift | Specifies the `-fvk-bind-shift` option. `intValue0` (higher 8 bits): kind, `intValue0` (lower bits): set; `intValue1`: shift. | +| VulkanBindGlobals | Specifies the `-fvk-bind-globals` option. `intValue0`: index, `intValue`: set. | +| VulkanInvertY | Specifies the `-fvk-invert-y` option. `intValue0` specifies a bool value for the setting. | +| VulkanUseDxPositionW | Specifies the `-fvk-use-dx-position-w` option. `intValue0` specifies a bool value for the setting. | +| VulkanUseEntryPointName | When set, will keep the original name of entrypoints as they are defined in the source instead of renaming them to `main`. `intValue0` specifies a bool value for the setting. | +| VulkanUseGLLayout | When set, will use std430 layout instead of D3D buffer layout for raw buffer load/stores. `intValue0` specifies a bool value for the setting. | +| VulkanEmitReflection | Specifies the `-fspv-reflect` option. When set will include additional reflection instructions in the output SPIRV. `intValue0` specifies a bool value for the setting. | +| GLSLForceScalarLayout | Specifies the `-force-glsl-scalar-layout` option. When set will use `scalar` layout for all buffers when generating SPIRV. `intValue0` specifies a bool value for the setting. | +| EnableEffectAnnotations | When set will turn on compatibility mode to parse legacy HLSL effect annotation syntax. `intValue0` specifies a bool value for the setting. | +| EmitSpirvViaGLSL | When set will emit SPIRV by emitting GLSL first and then use glslang to produce the final SPIRV code. `intValue0` specifies a bool value for the setting. | +| EmitSpirvDirectly | When set will use Slang's direct-to-SPIRV backend to generate SPIRV directly from Slang IR. `intValue0` specifies a bool value for the setting. | +| SPIRVCoreGrammarJSON | When set will use the provided SPIRV grammar file to parse SPIRV assembly blocks. `stringValue0` specifies a path to the spirv core grammar json file. | +| IncompleteLibrary | When set will not issue an error when the linked program has unresolved extern function symbols. `intValue0` specifies a bool value for the setting. | +| DownstreamArgs | Provide additional arguments to the downstream compiler. `stringValue0` encodes the downstream compiler name, `stringValue1` encodes the argument list, one argument per line. | +| DumpIntermediates | When set will dump the intermediate source output. `intValue0` specifies a bool value for the setting. | +| DumpIntermediatePrefix | The file name prefix for the intermediate source output. `stringValue0` specifies a string value for the setting. | +| DebugInformationFormat | Specifies the format of debug info. `intValue0` a value defined in the `SlangDebugInfoFormat` enum. | +| VulkanBindShiftAll | Specifies the `-fvk-bind-shift` option for all spaces. `intValue0`: kind, `intValue1`: shift. | +| GenerateWholeProgram | When set will emit target code for the entire program instead of for a specific entrypoint. `intValue0` specifies a bool value for the setting. | +| UseUpToDateBinaryModule | When set will only load precompiled modules if it is up-to-date with its source. `intValue0` specifies a bool value for the setting. | +| ValidateUniformity | When set will perform [uniformity analysis](a1-05-uniformity.md).| + +## Debugging + +Slang's SPIRV backend supports generating debug information using the [NonSemantic Shader DebugInfo Instructions](https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc). +To enable debugging information when targeting SPIRV, specify the `-emit-spirv-directly` and the `-g2` argument when using `slangc` tool, or set `EmitSpirvDirectly` to `1` and `DebugInformation` to `SLANG_DEBUG_INFO_LEVEL_STANDARD` when using the API. +Debugging support has been tested with RenderDoc. diff --git a/lib/All/slang/share/doc/slang/user-guide/09-reflection.md b/lib/All/slang/share/doc/slang/user-guide/09-reflection.md new file mode 100644 index 0000000..1fc48b3 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/09-reflection.md @@ -0,0 +1,1632 @@ +--- +layout: user-guide +permalink: /user-guide/reflection +--- + +Using the Reflection API +========================= + +This chapter provides an introduction to the Slang reflection API. +Our goals in this chapter are to: + +* Demonstrate the recommended types and operations to use for the most common reflection scenarios + +* Provide an underlying mental model for how Slang's reflection information represents the structure of a program + +We will describe the structure of a program that traverses all of the parameters of a shader program and prints information (including binding locations) for them. +The code shown here is derived from the [reflection-api](https://github.com/shader-slang/slang/tree/master/examples/reflection-api) example that is included in the Slang repository. +Readers may find it helpful to follow along with that code, to see a more complete picture of what is presented here. + +Compiling a Program +------------------- + +The first step in reflecting a shader program is, unsurprisingly, to compile it. +Currently reflection information cannot be queried from code compiled via the command-line `slangc` tool, so applications that want to perform reflection on Slang shader code should use the [compilation API](08-compiling.md#using-the-compilation-api) to compile a program, and then use `getLayout()` to extract reflection information: + +```c++ +slang::IComponentType* program = ...; +slang::ProgramLayout* programLayout = program->getLayout(targetIndex); +``` + +For more information, see the [relevant section](08-compiling.md#layout-and-reflection) of the chapter on compilation. + +Types and Variables +------------------- + +We start our discussion of the reflection API with two of the fundamental building blocks used to represent the structure of a program: types and variables. + +A key property of GPU shader programming is that the same type may be laid out differently, depending on how it is used. +For example, a user-defined `struct` type `Stuff` will often be laid out differently if it is used in a `ConstantBuffer` than in a `StructuredBuffer`. + +Because the same thing can be laid out in multiple ways (even within the same program), the Slang reflection API represents types and variables as distinct things from the *layouts* applied to them. +This section focuses only on the underlying types/variables, while later sections will build on these concepts to show how layouts can be reflected. + +### Variables + +A `VariableReflection` represents a variable declaration in the input program. +Variables include global shader parameters, fields of `struct` types, and entry-point parameters. + +Because a `VariableReflection` does not include layout information, the main things that can be queried on it are just its name and type: + +```c++ +void printVariable( + slang::VariableReflection* variable) +{ + const char* name = variable->getName(); + slang::TypeReflection* type = variable->getType(); + + print("name: "); printQuotedString(name); + print("type: "); printType(type); +} +``` + +### Types + +A `TypeReflection` represents some type in the input program. +There are various different *kinds* of types, such as arrays, user-defined `struct` types, and built-in types like `int`. +The reflection API represents these different cases with the `TypeReflection::Kind` enumeration. + +On its own, a `TypeReflection` does not include layout information. + +We will now start building a function for printing information about types: + +```c++ +void printType(slang::TypeReflection* type) +{ + const char* name = type->getName(); + slang::TypeReflection::Kind kind = type->getKind(); + + print("name: "); printQuotedString(name); + print("kind: "); printTypeKind(kind); + + // ... +} +``` + +Given what has been presented so far, if we have a Slang variable declaration like the following: + +```hlsl +float x; +``` + +then applying `printVariable()` to a `VariableReflection` for `x` would yield: + +``` +name: "x" +type: + name: "float" + kind: Scalar +``` + +Additional information can be queried from a `TypeReflection`, depending on its kind: + +```c++ +void printType(slang::TypeReflection* type) +{ + // ... + + switch(type->getKind()) + { + default: + break; + + // ... + } +} +``` + +The following subsections will show examples of what can be queried for various kinds of types. + +#### Scalar Types + +Scalar types store an additional enumerant to indicate which of the built-in scalar types is being represented: + +```c++ +case slang::TypeReflection::Kind::Scalar: + { + print("scalar type: "); + printScalarType(type->getScalarType()); + } + break; +``` + +The `slang::ScalarType` enumeration includes cases for the built-in integer and floating-point types (for example, `slang::ScalarType::UInt64` and `slang::ScalarType::Float16`), as well as the basic `bool` type (`slang::ScalarType::Bool`). +The `void` type is also considered a scalar type (`slang::ScalarType::Void`); + +#### Structure Types + +A structure type may have zero or more *fields*. +Each field is represented as a `VariableReflection`. +A `TypeReflection` allows the fields to be enumerated using `getFieldCount()` and `getFieldByIndex()`. + +```c++ +case slang::TypeReflection::Kind::Struct: + { + print("fields:"); + int fieldCount = type->getFieldCount(); + for (int f = 0; f < fieldCount; f++) + { + print("- "); + slang::VariableReflection* field = + type->getFieldByIndex(f); + printVariable(field); + } + } + break; +``` + +For the purposes of the reflection API, the fields of a `struct` type are its non-static members (both `public` and non-`public`). + +Given Slang code like the following: + +```hlsl +struct S +{ + int a; + float b; +} +``` + +Reflection on type `S` would yield: + +``` +name: "S" +kind: Struct +fields: + - name: "a" + type: + name: "int" + kind: Scalar + - name: "b" + type: + name: "float" + kind: Scalar +``` + +#### Arrays + +An array type like `int[3]` is defined by the number and type of elements in the array, which can be queried with `getElementCount()` and `getElementType`, respectively: + +```c++ +case slang::TypeReflection::Kind::Array: + { + print("element count: "); + printPossiblyUnbounded(type->getElementCount()); + + print("element type: "); + printType(type->getElementType()); + } + break; +``` + +Some array types, like `Stuff[]`, have *unbounded* size. +The Slang reflection API represents this case using the maximum value possible for the `size_t` result from `getElementCount()`: + +```c++ +void printPossiblyUnbounded(size_t value) +{ + if (value == ~size_t(0)) + { + printf("unbounded"); + } + else + { + printf("%u", unsigned(value)); + } +} +``` + +#### Vectors + +Vector types like `int3` are similar to arrays, in that they are defined by their element type and number of elements: + +```c++ +case slang::TypeReflection::Kind::Vector: + { + print("element count: "); + printCount(type->getElementCount()); + + print("element type: "); + printType(type->getElementType()); + } + break; +``` + +#### Matrices + +Matrix types like `float3x4` are defined by the number of rows, the number of columns, and the element type: + +```c++ +case slang::TypeReflection::Kind::Matrix: + { + print("row count: "); + printCount(type->getRowCount()); + + print("column count: "); + printCount(type->getColumnCount()); + + print("element type: "); + printType(type->getElementType()); + } + break; +``` + +#### Resources + +There are a wide range of resource types, including simple cases like `TextureCube` and `StructuredBuffer`, as well as quite complicated ones like `RasterizerOrderedTexture2DArray` and `AppendStructuredBuffer`. + +The Slang reflection API breaks down the properties of a resource type into its shape, access, and result type: + +```c++ +case slang::TypeReflection::Kind::Resource: + { + key("shape"); + printResourceShape(type->getResourceShape()); + + key("access"); + printResourceAccess(type->getResourceAccess()); + + key("result type"); + printType(type->getResourceResultType()); + } + break; +``` + +The *result type* of a resource is simply whatever would be returned by a basic read operation on that resource. +For resource types in Slang code, the result type is typically written as a generic type parameter after the type name. +For a `StructuredBuffer` the result type is `Thing`, while for a `Texture2D` it is `int3`. +A texture type like `Texture2D` that does not give an explicit result type has a default result type of `float4`. + +The *access* of a resource (`SlangResourceAccess`) represents how the elements of the resource may be accessed by shader code. +For Slang resource types, access is typically encoded as a prefix on the type name. +For example, an unprefixed `Texture2D` has read-only access (`SLANG_RESOURCE_ACCESS_READ`), while a `RWTexture2D` has read-write access (`SLANG_RESOURCE_ACCESS_READ_WRITE`). + +The *shape* of a resource (`SlangResourceShape`) represents the conceptual rank/dimensionality of the resource and how it is indexed. +For Slang resource type names, everything after the access prefix is typically part of the shape. + +A resource shape breaks down into a *base shape* along with a few possible suffixes like array-ness: + +```c++ +void printResourceShape(SlangResourceShape shape) +{ + print("base shape:"); + switch(shape & SLANG_BASE_SHAPE_MASK) + { + case SLANG_TEXTURE1D: printf("TEXTURE1D"); break; + case SLANG_TEXTURE2D: printf("TEXTURE2D"); break; + // ... + } + + if(shape & SLANG_TEXTURE_ARRAY_FLAG) printf("ARRAY"); + if(shape & SLANG_TEXTURE_MULTISAMPLE_FLAG) printf("MULTISAMPLE"); + // ... +} +``` + +#### Single-Element Containers + +Types like `ConstantBuffer` and `ParameterBlock` represent a grouping of parameter data, and behave like an array or structured buffer with only a single element: + +```c++ +case slang::TypeReflection::Kind::ConstantBuffer: +case slang::TypeReflection::Kind::ParameterBlock: +case slang::TypeReflection::Kind::TextureBuffer: +case slang::TypeReflection::Kind::ShaderStorageBuffer: + { + key("element type"); + printType(type->getElementType()); + } + break; +``` + +Layout for Types and Variables +------------------------------ + +The Slang reflection API provides `VariableLayoutReflection` and `TypeLayoutReflection` to represent a *layout* of a given variable or type. +As discussed earlier, the same type might have multiple different layouts used for it in the same program. + +### Layout Units + +A key challenge that the Slang reflection API has to address is how to represent the offset of a variable (or struct field, etc.) or the size of a type when `struct` types are allowed to mix various kinds of data together. + +For example, consider the following Slang code: + +```hlsl +struct Material +{ + Texture2D albedoMap; + SamplerState sampler; + float2 uvScale; + float2 uvBias; +} +struct Uniforms +{ + TextureCube environmentMap; + SamplerState environmentSampler; + float3 sunLightDirection; + float3 sunLightIntensity; + Material material; + // ... +} +ParameterBlock uniforms; +``` + +When laid out in the given parameter block, what is the offset of the field `Uniforms::material`? What is the size of the `Material` type? + +The key insight is that layout is multi-dimensional: the same type can have a size in multiple distinct units. +For example, when compiling the above code for D3D12/DXIL, the answer is that the `Uniforms::material` has an offset of one `t` register, one `s` register, and 32 bytes. +Similarly, the size of the `Material` type is one `t` register, one `s` register, and 16 bytes. + +We refer to these distinct units of measure used in layouts (including bytes, `t` registers, and `s` registers) as *layout units*. +Layout units are represented in the Slang reflection API with the `slang::ParameterCategory` enumeration. +(We will avoid the term "parameter category," despite that being the name currently exposed in the public API; that name has turned out to be a less-than-ideal choice). + +### Variable Layouts + +A `VariableLayoutReflection` represents a layout computed for a given variable (itself a `VariableReflection`). +The underlying variable can be accessed with `getVariable()`, but the variable layout also provides accessors for the most important properties. + +A variable layout stores the offsets of that variable (possibly in multiple layout units), and also a type layout for the data stored in the variable. + +```c++ +void printVarLayout(slang::VariableLayoutReflection* varLayout) +{ + print("name"); printQuotedString(varLayout->getName()); + + printRelativeOffsets(varLayout); + + key("type layout"); + printTypeLayout(varLayout->getTypeLayout()); +} +``` + +#### Offsets + +The offsets stored by a `VariableLayoutReflection` are always *relative* to the enclosing `struct` type, scope, or other context that surrounds the variable. + +The `VariableLayoutReflection::getOffset` method can be used to query the relative offset of a variable for any given layout unit: + +```c++ +void printOffset( + slang::VariableLayoutReflection* varLayout, + slang::ParameterCategory layoutUnit) +{ + size_t offset = varLayout->getOffset(layoutUnit); + + print("value: "); print(offset); + print("unit: "); printLayoutUnit(layoutUnit); + + // ... +} +``` + +If an application knows what unit(s) it expects a variable to be laid out in, it can directly query those. +However, in a case like our systematic traversal of all shader parameters, it is not always possible to know what units a given variable uses. + +The Slang reflection API can be used to query layout units used by a given variable layout with `getCategoryCount()` and `getCategoryByIndex()`: + +```c++ +void printRelativeOffsets( + slang::VariableLayoutReflection* varLayout) +{ + print("relative offset: "); + int usedLayoutUnitCount = varLayout->getCategoryCount(); + for (int i = 0; i < usedLayoutUnitCount; ++i) + { + auto layoutUnit = varLayout->getCategoryByIndex(i); + printOffset(varLayout, layoutUnit); + } +} +``` + +#### Spaces / Sets + +For certain target platforms and layout units, the offset of a variable for that unit might include an additional dimension that represents a Vulkan/SPIR-V descriptor set, D3D12/DXIL register space, or a WebGPU/WGSL binding group. +In this chapter, we will uniformly refer to all of these concepts as *spaces*. + +The relative space offset of a variable layout for a given layout unit can be queried with `getBindingSpace()`: + +```c++ +void printOffset( + slang::VariableLayoutReflection* varLayout, + slang::ParameterCategory layoutUnit) +{ + // ... + + size_t spaceOffset = varLayout->getBindingSpace(layoutUnit); + + switch(layoutUnit) + { + default: + break; + + case slang::ParameterCategory::ConstantBuffer: + case slang::ParameterCategory::ShaderResource: + case slang::ParameterCategory::UnorderedAccess: + case slang::ParameterCategory::SamplerState: + case slang::ParameterCategory::DescriptorTableSlot: + print("space: "); print(spaceOffset); + } +} +``` + +The code above only prints the space offset for the layout units where a space is semantically possible and meaningful. + +### Type Layouts + +A `TypeLayoutReflection` represents a layout computed for a type. +The underlying type that layout was computed for can be accessed using `TypeLayoutReflection::getType()`, but accessors are provided so that the most common properties of types can be queried on type layouts. + +The main thing that a type layout stores is the size of the type: + +```c++ +void printTypeLayout(slang::TypeLayoutReflection* typeLayout) +{ + print("name: "); printQuotedString(typeLayout->getName()); + print("kind: "); printTypeKind(typeLayout->getKind()); + + printSizes(typeLayout); + + // ... +} +``` + +#### Size + +Similarly to variable layouts, the size of a type layout can be queried given a chosen layout unit: + +```c++ +void printSize( + slang::TypeLayoutReflection* typeLayout, + slang::ParameterCategory layoutUnit) +{ + size_t size = typeLayout->getSize(layoutUnit); + + key("value"); printPossiblyUnbounded(size); + key("unit"); writeLayoutUnit(layoutUnit); +} +``` + +Note that the size of a type may be *unbounded* for a particular layout unit; this case is encoded just like the unbounded case for the element count of an array type (`~size_t(0)`). + +The layout units used by a particular type layout can be iterated over using `getCategoryCount()` and `getCategoryByIndex()`: + +```c++ +void printSizes(slang::TypeLayoutReflection* typeLayout) +{ + print("size: "); + int usedLayoutUnitCount = typeLayout->getCategoryCount(); + for (int i = 0; i < usedLayoutUnitCount; ++i) + { + auto layoutUnit = typeLayout->getCategoryByIndex(i); + print("- "); printSize(typeLayout, layoutUnit); + } + + // ... +} +``` + +#### Alignment and Stride + +For any given layout unit, a type layout can also reflect the alignment of the type for that unit with `TypeLayoutReflection::getAlignment()`. +Alignment is typically only interesting when the layout unit is bytes (`slang::ParameterCategory::Uniform`). + +Note that, unlike in C/C++, a type layout in Slang may have a size that is not a multiple of its alignment. +The *stride* of a type layout (for a given layout unit) is its size rounded up to its alignment, and is used as the distance between consecutive elements in arrays. +The stride of a type layout can be queried for any chosen layout unit with `TypeLayoutReflection::getStride()`. + +Note that all of the `TypeLayoutReflection` methods `getSize()`, `getAlignment()`, and `getStride()` default to returning information in bytes, if a layout unit is not specified. +The same is true of the `VariableLayoutReflection::getOffset()` method. + +The alignment and stride of a type layout can be reflected when it is relevant with code like: + +```c++ +void printTypeLayout(slang::TypeLayoutReflection* typeLayout) +{ + // ... + + if(typeLayout->getSize() != 0) + { + print("alignment in bytes: "); + print(typeLayout->getAlignment()); + + print("stride in bytes: "); + print(typeLayout->getStride()); + } + + // ... +} +``` + +#### Kind-Specific Information + +Just as with the underlying types, a type layout may store additional information depending on the kind of type: + +```c++ +void printTypeLayout(slang::TypeLayoutReflection* typeLayout) +{ + // ... + + switch(typeLayout->getKind()) + { + default: + break; + + // ... + } +} +``` + +The following subsections will cover the important kinds to handle when reflecting type layouts. + +#### Structure Type Layouts + +A type layout for a `struct` type provides access to the fields of the `struct`, with each field represented as a variable layout: + +```c++ +case slang::TypeReflection::Kind::Struct: + { + print("fields: "); + + int fieldCount = typeLayout->getFieldCount(); + for (int f = 0; f < fieldCount; f++) + { + auto field = typeLayout->getFieldByIndex(f); + printVarLayout(field); + } + } + break; +``` + +The offset information stored on the type layout for each field will always be relative to the start of the `struct` type. + +#### Array Type Layouts + +Array type layouts store a layout for the element type of the array, which can be accessed with `getElementTypeLayout()`: + +```c++ +case slang::TypeReflection::Kind::Array: + { + print("element count: "); + printPossiblyUnbounded(typeLayout->getElementCount()); + + print("element type layout: "); + printTypeLayout(typeLayout->getElementTypeLayout()); + } + break; +``` + +#### Matrix Type Layouts + +A layout for a matrix type stores a matrix layout *mode* (`SlangMatrixLayoutMode`) to record whether the type was laid out in row-major or column-major layout: + +```c++ +case slang::TypeReflection::Kind::Matrix: + { + // ... + + print("matrix layout mode: "); + printMatrixLayoutMode(typeLayout->getMatrixLayoutMode()); + } + break; +``` + +Note that the concepts of "row" and "column" as employed by Slang are the opposite of how Vulkan, SPIR-V, GLSL, and OpenGL use those terms. +When Slang reflects a matrix as using row-major layout, the corresponding matrix in generated SPIR-V will have a `ColMajor` decoration. +For an explanation of why these conventions differ, please see the relevant [appendix](./a1-01-matrix-layout.md). + +#### Single-Element Containers + +Constant buffers, parameter blocks, and other types representing grouping of parameters are the most subtle cases to handle for reflection. +The Slang reflection API aspires to provide complete and accurate information for these cases, but understanding *why* the provided data is what it is requires an appropriate mental model. + +##### Simple Cases + +In simple cases, a constant buffer has only ordinary data in it (things where the only used layout unit is bytes): + +``` +struct DirectionalLight +{ + float3 direction; + float3 intensity; +} +ConstantBuffer light; +``` + +When this case is laid out for D3D12, the `DirectionalLight` type will consume 28 bytes, but the `light` parameter will instead consume one `b` register. +We thus see that the `ConstantBuffer<>` type effectively "hides" the number of bytes used by its element. + +Similarly, when a parameter block only has opaque types in it: + +``` +struct Material +{ + Texture2D albedoMap; + Texture2D glossMap; + SamplerState sampler; +} +ParameterBlock material; +``` + +When this is laid out for Vulkan, the `Material` type will consume 3 bindings, but the `material` parameter will instead consume one space. +A `ParameterBLock<>` type hides the bindings/registers/slots used by its element. + +##### When Things Leak + +If the element type of a constant buffer includes any data that isn't just measured in bytes, that usage will "leak" into the size of the constant buffer. +For example: + +``` +struct ViewParams +{ + float3 cameraPos; + float3 cameraDir; + TextureCube envMap; +} +ConstantBuffer view; +``` + +If this example is laid out for D3D12, the `ViewParams` type will have a size of 28 bytes (according to D3D constant buffer layout rules) and one `t` register. +The size of the `view` parameter will be one `b` register and one `t` register. +The `ConstantBuffer<>` type can hide the bytes used by `ViewParams`, but the used `t` register leaks out and becomes part of the size of `view`. + +If the same example is laid out for Vulkan, the `ViewParams` type will have a size of 28 bytes (according to `std140` layout rules) and one `binding`. +The size of the `view` parameter will be two `binding`s. + +An important question a user might have in the Vulkan case, is whether the `binding` for `view` comes before that for `view.envMap`, or the other way around. +The answer is that the Slang compiler always lays out the "container" part of a parameter like `view` (the constant buffer) before the element, but a client of the reflection API shouldn't have to know such things to understand the information that gets reflected. + +Note that in the Vulkan case, the offset of the `envMap` field within `ViewParams` is zero `binding`s, but the offset of `view.envMap` field relative to `view` is one `binding`. +Computing the cumulative offset of `view.envMap` requires more information than just that available on the variable layouts for `view` and `view.envMap`. + +Similar cases of usage leaking can occur for parameter blocks, when one parameter block is nested within another. + +##### A `ConstantBuffer<>` Without a Constant Buffer + +While it is an uncommon case, it is possible to use a `ConstantBuffer<>` with an element type that contains no ordinary data (nothing with a layout unit of bytes): + +``` +struct Material +{ + Texture2D albedoMap; + Texture2D glossMap; + SamplerState sampler; +} +ConstantBuffer material; +``` + +If this case is compiled for Vulkan, the `material` parameter will consume 3 `binding`s, but none of those will be for a constant buffer. +In this case, unlike in the preceding example with `view.envMap`, the offset of `material.albedoMap` relative to `material` will be zero `binding`s. + +##### Implicitly-Allocated Constant Buffers + +A common use case for parameter blocks is to wrap up all of the parameters of a shader, or of some subsystem. +In such cases, there are likely to be both ordinary-type and opaque-type fields: + +``` +struct PointLight +{ + float3 position; + float3 intensity; +} +struct LightingEnvironment +{ + TextureCube envMap; + PointLight pointLights[10]; +} +ParameterBlock lightEnv; +``` + +If this example is compiled for Vulkan, the `LightingEnvironment` type uses 316 bytes and one `binding` (ParameterCategory::DescriptorTableSlot), while `lightEnv` uses one descriptor `set` (ParameterCategory::SubElementRegisterSpace). + +What is not clear in the above description, however, is that because `LightingEnvironment` uses ordinary bytes, the Slang compiler will have to implicitly allocate a `binding` for a constant buffer to hold those bytes. +Conceptually, the layout is similar to what would be produced for `ParameterBlock>`. + +Furthermore, that constant buffer `binding` will be the first binding within the descriptor `set` for `lightEnv`, so that the cumulative `binding` offset for `lightEnv.envMap` will be one `binding` (even though `LightingEnvironment::envMap` has a relative offset of zero `binding`s). + +##### Container and Element + +In order to properly handle all of the nuances described here, the layout for a type like `ConstantBuffer` or `ParameterBlock` includes both layout information for the element of the container (a `Thing`) as well as layout information for the *container* itself. +Furthermore, the layout information for both the element and container need to support storing offset information (not just size), relative to the overall `ConstantBuffer<>` or `ParameterBlock<>`. + +The breakdown is thus: + +* The size information for the complete container type layout reflects whatever usage "leaks" out, such that it would need to be accounted for when further aggregating the overall type. + +* Information about the allocated container is stored as a variable layout, queried with `getContainerVarLayout()` + + * The type layout for that variable layout shows what was allocated to represent the container itself, including any implicitly-allocated constant buffer + + * The offsets of that variable layout show where the container is situated relative to the overall type. + With the current layout strategies used by the Slang compiler, all of these offsets will be zero. + +* Information about the element is stored as a variable layout, queried with `getElementVarLayout()` + + * The type layout of that variable layout shows how the element type is laid out inside container. + + * The offsets on that variable layout show where the element is situated relative to the overall type. + These offsets will be non-zero in cases where there is some layout unit used by both the element type and the container itself. + +Given this understanding, we can now look at the logic to reflect a type layout for a constant buffer, parameter block, or similar type. + +```c++ +case slang::TypeReflection::Kind::ConstantBuffer: +case slang::TypeReflection::Kind::ParameterBlock: +case slang::TypeReflection::Kind::TextureBuffer: +case slang::TypeReflection::Kind::ShaderStorageBuffer: + { + print("container: "); + printOffsets(typeLayout->getContainerVarLayout()); + + auto elementVarLayout = typeLayout->getElementVarLayout(); + print("element: "); + printOffsets(elementVarLayout); + + print("type layout: "); + printTypeLayout( + elementVarLayout->getTypeLayout(); + } + break; +``` + +Note that the application logic here does not simply make use of `printVarLayout()` on the results of both `getContainerVarLayout()` and `getElementVarLayout()`, even though it technically could. +While these sub-parts of the overall type layout are each represented as a `VariableLayoutReflection`, many of the properties of those variable layouts are uninteresting or null; they primarily exist to convey offset information. + +##### Example + +Given input code like the following: + +```hlsl +struct Material +{ + Texture2D albedoMap; + SamplerState sampler; + float2 uvScale; + float2 uvBias; +} + +struct FrameParams +{ + ConstantBuffer material; + + float3 cameraPos; + float3 cameraDir; + + TextureCube envMap; + float3 sunLightDir; + float3 sunLightIntensity; + + Texture2D shadowMap; + SamplerComparisonState shadowMapSampler; +} + +ParameterBlock params; +``` + +We will look at the kind of output our example application prints for `params` when compiling for Vulkan. +The basic information for the variable and its type layout looks like: + +``` +- name: "params" + offset: + relative: + - value: 1 + unit: SubElementRegisterSpace # register spaces / descriptor sets + type layout: + name: "ParameterBlock" + kind: ParameterBlock + size: + - value: 1 + unit: SubElementRegisterSpace # register spaces / descriptor sets +``` + +As we would expect, the size of the parameter block is one register space (aka Vulkan descriptor `set`). +In this case, the Slang compiler has assigned `params` to have a space offset of 1 (`set=1` in GLSL terms). + +The offset information for the container part of `params` is the following: + +``` +container: +offset: + relative: + - value: 0 + unit: DescriptorTableSlot # bindings + space: 0 + - value: 0 + unit: SubElementRegisterSpace # register spaces / descriptor sets +``` + +We can see from this information that the `ParameterBlock<>` container had two things allocated to it: a descriptor set (`ParameterCategory::SubElementRegisterSpace`), and a binding within that descriptor set (`ParameterCategory::DescriptorTableSlot`) for the automatically-introduced constant buffer. +That automatically-introduced buffer has an offset of 0 bindings from the start of the descriptor set. + +The layout for the element part of the parameter block is as follows: + +``` +element: + offset: + relative: + - value: 1 + unit: DescriptorTableSlot # bindings + space: 0 + - value: 0 + unit: Uniform # bytes + type layout: + name: "FrameParams" + kind: Struct + size: + - value: 6 + unit: DescriptorTableSlot # bindings + - value: 64 + unit: Uniform # bytes + alignment in bytes: 16 + stride in bytes: 64 + fields: + - name: "material" + offset: + relative: + - value: 0 + unit: DescriptorTableSlot # bindings + space: 0 + ... +``` + +We see here that the type layout for the element is as expected of a layout for the `FrameParams` type. +In particular, note how the `material` field has a relative offset of zero bindings from the start of the `struct`, as is expected for the first field. +In order to account for the automatically-introduced constant buffer that is used by the container part of the layout, the element variable layout includes a relative offset of one binding (`ParameterCategory::DescriptorTableSlot`). + +In a later section we will discuss how to easily sum up the various relative offsets shown in an example like this, when an application wants to compute a *cumulative* offset for a field like `params.material.sampler`. + + +##### Pitfalls to Avoid + +It is a common mistake for users to apply `getElementTypeLayout()` on a single-element container, instead of using `getElementVarLayout()` as we advise here. +The implementation of the reflection API makes an effort to ensure that the type layout returned by `getElementTypeLayout()` automatically bakes in the additional offsets that are needed, but the results can still be unintuitive. + +Programs and Scopes +------------------- + +So far, our presentation has largely been bottom-up: we have shown how to recursively perform reflection on types, variables, and their layouts, but we have not yet shown how how to get this recursive traversal started. +We will now proceed top-down for a bit, and look at how to reflect the top-level parameters of a program. + +A `ProgramLayout` is typically obtained using `IComponentType::getLayout()` after compiling and linking a Slang program. +A program layout primarily comprises the global scope, and zero or more entry points: + +```c++ +void printProgramLayout( + slang::ProgramLayout* programLayout) +{ + print("global scope: "); + printScope(programLayout->getGlobalParamsVarLayout()); + + print("entry points: "); + int entryPointCount = programLayout->getEntryPointCount(); + for (int i = 0; i < entryPointCount; ++i) + { + print("- "); + printEntryPointLayout( + programLayout->getEntryPointByIndex(i)); + } +} +``` + +The global scope and entry points are each an example of a *scope* where top-level shader parameters can be declared. +Scopes are represented in the reflection API using `VariableLayoutReflection`s. +We will now discuss the details of reflection for scopes, starting with the global scope as an example. + +### Global Scope + +In order to understand how the Slang reflection API exposes the global scope, it is valuable to think of the steps (some of them optional) that the Slang compiler applies to global-scope shader parameter declarations as part of compilation. + +#### Parameters are Grouped Into a Structure + +If a shader program declares global-scope parameters like the following: + +```hlsl +Texture2D diffuseMap; +TextureCube envMap; +SamplerState sampler; +``` + +The Slang compiler will conceptually group all of those distinct global-scope parameter declarations into a `struct` type and then have only a single global-scope parameter of that type: + +```hlsl +struct Globals +{ + Texture2D diffuseMap; + TextureCube envMap; + SamplerState sampler; +} +uniform Globals globals; +``` + +In this simple kind of case, the scope will be reflected as a variable layout with a `struct` type layout, with one field for each parameter declared in that scope: + +```c++ +void printScope( + slang::VariableLayoutReflection* scopeVarLayout) +{ + auto scopeTypeLayout = scopeVarLayout->getTypeLayout(); + switch (scopeTypeLayout->getKind()) + { + case slang::TypeReflection::Kind::Struct: + { + print("parameters: "); + + int paramCount = scopeTypeLayout->getFieldCount(); + for (int i = 0; i < paramCount; i++) + { + print("- "); + + auto param = scopeTypeLayout->getFieldByIndex(i); + printVarLayout(param, &scopeOffsets); + } + } + break; + + // ... + } +} +``` + +#### Wrapped in a Constant Buffer If Needed + +In existing shader code that was originally authored for older APIs (such as D3D9) it is common to find a mixture of opaque and ordinary types appearing as global-scope shader parameters: + +```hlsl +Texture2D diffuseMap; +TextureCube envMap; +SamplerState sampler; + +uniform float3 cameraPos; +uniform float3 cameraDir; +``` + +In these cases, when the Slang compiler groups the parameters into a single `struct`: + +```hlsl +struct Globals +{ + Texture2D diffuseMap; + TextureCube envMap; + SamplerState sampler; + + float3 cameraPos; + float3 cameraDir; +} +``` + +it finds that the resulting `struct` consumes a non-zero number of bytes and, for most compilation targets, it will automatically wrap that structure in a `ConstantBuffer<>` before declaring the single shader parameter that represents the global scope: + +```hlsl +ConstantBuffer globals +``` + +This case shows up in the Slang reflection API as the scope having a type layout with the constant-buffer kind: + +```c++ +case slang::TypeReflection::Kind::ConstantBuffer: + print("automatically-introduced constant buffer: "); + + printOffsets(scopeTypeLayout->getContainerVarLayout()); + + printScope(scopeTypeLayout->getElementVarLayout()); + break; +``` + +In this case, the container variable layout reflects the relative offsets for where the automatically-introduced constant buffer is bound, and the element variable layout reflects the global scope parameters that were wrapped in this way. + +#### Wrapped in a Parameter Block If Needed + +For targets like D3D12/DXIL, Vulkan/SPIR-V, and WebGPU/WGSL, most shader parameters must be bound via the target-specific grouping mechanism (descriptor tables, descriptor sets, or binding groups, respectively). +If the Slang compiler is compiling for such a target and detects that there are global-scope parameters that do not specify an explicit space, then it will conceptually wrap the global-scope declarations in a `ParameterBlock<>` that provides a default space. + +For example, if compiling this code to Vulkan: + +```hlsl +Texture2D diffuseMap; +[[vk::binding(1,0)]] TextureCube envMap; +SamplerState sampler; +``` + +the Slang compiler will detect that `envMap` is explicitly bound to `binding` 1 in space (aka descriptor `set`) 0, and that neither `diffuseMap` nor `sampler` has been explicitly bound. +Both of the unbound parameters need to be passed inside of some space, so the compiler will allocate space 1 for that purpose (as space 0 was already claimed by explicit bindings). +In simplistic terms, the compiler will behave *as if* the global-scope parameters are wrapped up in a `struct` and then further wrapped up into a `ParameterBlock<>`. + +This case shows up in the Slang reflection API as the scope having a type layout with the parameter-block kind: + +```c++ +case slang::TypeReflection::Kind::ParameterBlock: + print("automatically-introduced parameter block: "); + + printOffsets(scopeTypeLayout->getContainerVarLayout()); + + printScope(scopeTypeLayout->getElementVarLayout()); + break; +``` + +In cases where the parameters in a scope require *both* a constant buffer and a parameter block to be automatically introduced, the scope is reflected as if things were wrapped with `ParameterBlock<...>` and not `ParameterBlock>`. +That is, the binding information for the implicit constant buffer will be found as part of the container variable layout for the parameter block. + +#### Pitfalls to Avoid + +The `ProgramLayout` type has the appealingly-named `getParameterCount` and `getParameterByIndex()` methods, which seem to be the obvious way to navigate the global-scope parameters of a shader. +However, we recommend *against* using these functions in applications that want to be able to systematically and robustly reflect any possible input shader code. + +While the reflection API implementation makes an effort to ensure that the information returned by `getParameterByIndex()` is not incorrect, it is very difficult when using those functions to account for how global-scope parameters might have been grouped into an automatically-introduced constant buffer or parameter block. +The `getGlobalConstantBufferBinding()` and `getGlobalConstantBufferSize()` methods can be used in some scenarios, but aren't the best way to get the relevant information. + +While it would only matter in corner cases, we still recommend that applications use `getGlobalParamsVarLayout()` instead of `getGlobalParamsTypeLayout()`, to account for cases where the global-scope might have offsets applied to it (and also to handle the global scope and entry-point scopes more uniformly). + +### Entry Points + +An `EntryPointReflection` provides information on an entry point. +This includes the stage that the entry point was compiled for: + +```c++ +void printEntryPointLayout(slang::EntryPointReflection* entryPointLayout) +{ + print("stage: "); printStage(entryPointLayout->getStage()); + + // ... +} +``` + +#### Entry Point Parameters + +An entry point acts as a scope for top-level shader parameters, much like the global scope. +Entry-point parameters are grouped into a `struct`, and then automatically wrapped in a constant buffer or parameter block if needed. +The main additional consideration, compared to the global scope, is that an entry-point function may also declare a result type. +When present, the function result acts more or less as an additional `out` parameter. + +The parameter scope and result of an entry point can be reflected with logic like: + +```c++ +void printEntryPointLayout(slang::EntryPointReflection* entryPointLayout) +{ + // ... + printScope(entryPointLayout->getVarLayout()); + + auto resultVarLayout = entryPointLayout->getResultVarLayout(); + if (resultVarLayout->getTypeLayout()->getKind() != slang::TypeReflection::Kind::None) + { + key("result"); printVarLayout(resultVarLayout); + } +} +``` + +##### Pitfalls to Avoid + +Similarly to the case for the global scope, we recommend against using the `getParameterCount()` and `getParameterByIndex()` methods on `EntryPointReflection`, since they make it harder to handle cases where the entry-point scope might have been allocated as a constant buffer (although the `hasDefaultConstantBuffer()` method is provided to try to support older applications that still use `getParameterByIndex()`). +Applications are also recommended to use `EntryPointReflection::getVarLayout()` instead of `::getTypeLayout()`, to more properly reflect the way that offsets are computed and applied to the parameters of an entry point. + +#### Stage-Specific Information + +Depending on the stage that an entry point was compiled for, it may provide additional information that an application can query: + +```c++ +void printEntryPointLayout(slang::EntryPointReflection* entryPointLayout) +{ + // ... + switch (entryPointLayout->getStage()) + { + default: + break; + + // ... + } + // ... +} +``` + +For example, compute entry points store the thread-group dimensions: + +```c++ +case SLANG_STAGE_COMPUTE: + { + SlangUInt sizes[3]; + entryPointLayout->getComputeThreadGroupSize(3, sizes); + + print("thread group size: "); + print("x: "); print(sizes[0]); + print("y: "); print(sizes[1]); + print("z: "); print(sizes[2]); + } + break; +``` + +#### Varying Parameters + +So far we have primarily been talking about the *uniform* shader parameters of a program: those that can be passed in from application code to shader code. +Slang's reflection API also reflects the *varying* shader parameters that appear are passed between stages of a pipeline. + +Variable and type layouts for varying shader parameters will typically show usage of: + +* Varying input slots (`slang::ParameterCategory::VaryingInput`) for stage inputs +* Varying output slots (`slang::ParameterCategory::VaryingOutput`) for `out` parameters and the entry-point result +* Both (`slang::ParameterCategory::VaryingInput` *and* `::VaryingOutput`) for `inout` parameters +* Nothing (no usage for any unit) for *system value* parameters (typically using an `SV_*` semantic) + +For user-defined varying parameters, some GPU APIs care about the *semantic* that has been applied to the parameter. +For example, given this shader code: + +```hlsl +[shader("vertex")] +float4 vertexMain( + float3 position : POSITION, + float3 normal : NORMAL, + float3 uv : TEXCOORD, + // ... + ) + : SV_Position +{ + // ... +} +``` + +the shader parameter `normal` of `vertexMain` has a semantic of `NORMAL`. + +Semantics are only relevant for shader parameters that became part of the varying input/output interface of an entry point for some stage, in which case the `VariableLayoutReflection::getStage()` method will return that stage. +A semantic is decomposed into both a name and an index (e.g., `TEXCOORD5` has a name of `"TEXCOORD"` and an index of `5`). +This information can be reflected with `getSemanticName()` and `getSemanticIndex()`: + + +```c++ +void printVarLayout(slang::VariableLayoutReflection* varLayout) +{ + // ... + if (varLayout->getStage() != SLANG_STAGE_NONE) + { + print("semantic: "); + print("name: "); printQuotedString(varLayout->getSemanticName()); + print("index: "); print(varLayout->getSemanticIndex()); + } + // ... +} +``` + +Calculating Cumulative Offsets +------------------------------ + +All of the code so far has only extracted the *relative* offsets of variable layouts. +Offsets for fields have been relative to the `struct` that contains them. +Offsets for top-level parameters have been relative to the scope that contains them, or even to a constant buffer or parameter block that was introduced for that scope. + +There are many cases where an application needs to calculate a *cumulative* offset (or even an absolute offset) for some parameter, even down to the granularity of individual `struct` fields. +As a notable example, allocation of D3D root signatures and Vulkan pipeline layouts for a program requires being able to enumerate the absolute offsets of all bindings in all descriptor tables/sets. + +Because offsets for certain layout units include an additional dimension for a space, our example application will define a simple `struct` to represent a cumulative offset: + +```c++ +struct CumulativeOffset +{ + int value; // the actual offset + int space; // the associated space +}; +``` + +### Access Paths + +There are multiple ways to track and calculate cumulative offsets. +Here we will present a solution that is both simple and reasonably efficient, while still yielding correct results even in complicated scenarios. + +If all we had to do was calculate the byte offsets of things, a single `size_t` would be enough to represent a cumulative offset. +However, we have already seen that in the context of a GPU language like Slang, we can have offsets measured in multiple different layout units. +A naive implementation might try to represent a cumulative offset as a vector or dictionary of scalar offsets, with (up to) one for each layout unit. +The sheer number of layout units (the cases of the `slang::ParameterCategory` enumeration) makes such an approach unwieldy. + +Instead we focus on the intuition that the cumulative offset of a variable layout, for any given layout unit, can be computed by summing up all the relative offsets along the *access path* to that variable. +For example, given code like: + +```hlsl +struct Material +{ + Texture2D albedoMap; + Texture2D glossMap; + SamplerState sampler; +} +struct LightingEnvironment +{ + TextureCube environmentMap; + float3 sunLightDir; + float3 sunLightIntensity; +} +struct Params +{ + LightingEnvironment lights; + Material material; +} +uniform Params params; +``` + +we expect that the cumulative offset of `params.material.glossMap` in units of Vulkan `binding`s can be computed by summing up the offsets in that unit of `params` (0), `material` (1), and `glossMap` (1). + +When recursively traversing the parameters of a shader, out example application will track an access path as a singly-linked list of variable layouts that points up the stack, from the deepest variable to the shallowest: + +```c++ +struct AccessPathNode +{ + slang::VariableLayoutReflection* varLayout; + AccessPathNode* outer; +}; + +struct AccessPath +{ + AccessPathNode* leafNode = nullptr; +}; +``` + +For the example code above, if our recursive traversal is at `params.material.glossMap`, then the access path will start with a node for `glossMap` which points to a node for `material`, which points to a node for `glossMap`. + +For many layout units, we can calculate a cumulative offset simply by summing up contributions along the entire access path, with logic like the following: + +```c++ +CumulativeOffset calculateCumulativeOffset(slang::ParameterCategory layoutUnit, AccessPath accessPath) +{ + // ... + for(auto node = accessPath.leafNode; node != nullptr; node = node->outer) + { + result.value += node->varLayout->getOffset(layoutUnit); + result.space += node->varLayout->getBindingSpace(layoutUnit); + } + // ... +} +``` + +Once our example application is properly tracking access paths, we will be able to use them to calculate and print the cumulative offsets of variable layouts: + +```c++ +void printOffsets( + slang::VariableLayoutReflection* varLayout, + AccessPath accessPath) +{ + // ... + + print("cumulative:"); + for (int i = 0; i < usedLayoutUnitCount; ++i) + { + print("- "); + auto layoutUnit = varLayout->getCategoryByIndex(i); + printCumulativeOffset(varLayout, layoutUnit, accessPath); + } +} +``` + +Printing the cumulative offset of a variable layout requires adding the offset information for the variable itself to the offset calculated from its access path: + +```c++ +void printCumulativeOffset( + slang::VariableLayoutReflection* varLayout, + slang::ParameterCategory layoutUnit, + AccessPath accessPath) +{ + CumulativeOffset cumulativeOffset = calculateCumulativeOffset(layoutUnit, accessPath); + + cumulativeOffset.offset += varLayout->getOffset(layoutUnit); + cumulativeOffset.space += varLayout->getBindingSpace(layoutUnit); + + printOffset(layoutUnit, cumulativeOffset.offset, cumulativeOffset.space); +} +``` + +### Tracking Access Paths + +In order to support calculation of cumulative offsets, the various functions we've presented so far like `printVarLayout()` and `printTypeLayout()` need to be extended with an additional parameter for an `AccessPath`. +For example, the signature of `printTypeLayout()` becomes: + +```c++ +void printTypeLayout(slang::TypeLayoutReflection* typeLayout, AccessPath accessPath) +{ + // ... +} +``` + +#### Variable Layouts + +When traversing a variable layout, we then need to extend the access path to include the additional variable layout, before traversing down into its type layout: + +```c++ +void printVarLayout(slang::VariableLayoutReflection* typeLayout, AccessPath accessPath) +{ + // ... + + ExtendedAccessPath varAccessPath(accessPath, varLayout); + + print("type layout: "); + printTypeLayout(varLayout->getTypeLayout(), varAccessPath); +} +``` + +#### Scopes + +Similar logic is needed within `printScope()` in our example program: + +```c++ +void printScope( + slang::VariableLayoutReflection* scopeVarLayout, + AccessPath accessPath) +{ + ExtendedAccessPath scopeAccessPath(accessPath, scopeVarLayout); + + // ... +} +``` + +The calls to `printOffsets()`, `printTypeLayout()`, etc. inside of `printScope()` will then pass along the extended access path. + +#### Array-Like Types + +When the traversing an array, matrix, or vector type, it is impossible to compute a single cumulative offset that is applicable to all elements of the type. +The recursive calls to `printTypeLayout()` in these cases will simply pass in an empty `AccessPath`. +For example: + +```c++ +case slang::TypeReflection::Kind::Array: + { + // ... + + print("element type layout: "); + printTypeLayout( + typeLayout->getElementTypeLayout(), + AccessPath()); + } + break; +``` + +### Handling Single-Element Containers + +Types like constant buffers and parameter blocks add complexity that requires additions to our representation and handling of access paths. + +First, when calculating the cumulative byte offset of variables inside a constant buffer (or any of these single-element container types), it is important not to sum contributions too far up the access path. +Consider this example: + +```c++ +struct A +{ + float4 x; + Texture2D t; +} +struct B +{ + float4 y; + ConstantBuffer a; +} +struct C +{ + float4 z; + Texture2D t; + B b; +} +uniform C c; +``` + +When compiling for D3D12, the cumulative byte offset of `c.b` is 16, but the cumulative byte offset of `c.b.a.x` needs to be zero, because its byte offset should be measured relative to the enclosing constant buffer `c.b.a`. +In contrast, the cumulative of offset of `c.b` in `t` registers is one, and the cumulative offset of `c.b.a.t` needs to be two. + +Similarly, when calculating the cumulative offsets of variables inside a parameter block (for targets that can allocate each parameter block its own space), it is important not to sum contributions past an enclosing parameter block. + +We can account for these subtleties by extending the representation of access paths in our example application to record the node corresponding to the deepest constant buffer or parameter block along the path: + +```c++ +struct AccessPath +{ + AccessPathNode* leaf = nullptr; + AccessPathNode* deepestConstantBuffer = nullptr; + AccessPathNode* deepestParameterBlock = nullptr; +}; +``` + +Now when traversing a single-element container type in `printTypeLayout`, we can make a copy of the current access path and modify its `deepestConstantBuffer` to account for the container: + +```c++ +case slang::TypeReflection::Kind::ConstantBuffer: +case slang::TypeReflection::Kind::ParameterBlock: +case slang::TypeReflection::Kind::TextureBuffer: +case slang::TypeReflection::Kind::ShaderStorageBuffer: + { + // ... + + AccumulatedOffsets innerAccessPath = accessPath; + innerAccessPath.deepestConstantBuffer = innerAccessPath.leaf; + + // ... + } + break; +``` + +Further, if the container had a full space allocated to it, then we also update the `deepestParameterBlock`: + +```c++ +// ... +if (containerVarLayout->getTypeLayout()->getSize( + slang::ParameterCategory::SubElementRegisterSpace) != 0) +{ + innerAccessPath.deepestParameterBlock = innerAccessPath.leaf; +} +// ... +``` + +Finally, when traversing the element of the container, we need to use this new `innerAccessPath`, and also extend the access path when traversing into the type layout of the element: + +```c++ +print("element: "); +printOffsets(elementVarLayout, innerAccessPath); + +ExtendedAccessPath elementAccessPath(innerAccessPath, elementVarLayout); + +print("type layout: "); +printTypeLayout( + elementVarLayout->getTypeLayout(), + elementAccessPath); +``` + +### Accumulating Offsets Along An Access Path + +We now understand that the proper way to calculate a cumulative offset depends on the layout unit: + +```c++ +CumulativeOffset calculateCumulativeOffset( + slang::ParameterCategory layoutUnit, + AccessPath accessPath) +{ + switch(layoutUnit) + { + // ... + } +} +``` + +#### Layout Units That Don't Require Special Handling + +By default, relative offsets will be summed for all nodes along the access path: + +```c++ +default: + for (auto node = accessPath.leaf; node != nullptr; node = node->outer) + { + result.offset += node->varLayout->getOffset(layoutUnit); + } + break; +``` + +#### Bytes + +When a byte offset is being computed, relative offsets will only be summed up to the deepest enclosing constant buffer, if any: + +```c++ +case slang::ParameterCategory::Uniform: + for (auto node = accessPath.leaf; node != accessPath.deepestConstantBuffer; node = node->outer) + { + result.offset += node->varLayout->getOffset(layoutUnit); + } + break; +``` + +#### Layout Units That Care About Spaces + +Finally, we need to handle the layout units that care about spaces: + +```c++ +case slang::ParameterCategory::ConstantBuffer: +case slang::ParameterCategory::ShaderResource: +case slang::ParameterCategory::UnorderedAccess: +case slang::ParameterCategory::SamplerState: +case slang::ParameterCategory::DescriptorTableSlot: + // ... + break; +``` + +Relative offsets, including space offsets, need to be summed along the access path up to the deepest enclosing parameter block, if any: + +```c++ +for (auto node = accessPath.leaf; node != accessPath.deepestParameterBlock; node = node->outer) +{ + result.offset += node->varLayout->getOffset(layoutUnit); + result.space += node->varLayout->getBindingSpace(layoutUnit); +} +``` + +Additionally, the offset of the enclosing parameter block in spaces needs to be added to the space of the cumulative offset: + +```c++ +for (auto node = accessPath.deepestParameterBlock; node != nullptr; node = node->outer) +{ + result.space += node->varLayout->getOffset(slang::ParameterCategory::SubElementRegisterSpace); +} +``` + +Determining Whether Parameters Are Used +--------------------------------------- + +Some application architectures make use of shader code that declares a large number of shader parameters at global scope, but only uses a small fraction of those parameters at runtime. +Similarly, shader parameters may be declared at global scope even if they are only used by a single entry point in a pipeline. +These kinds of architectures are not ideal, but they are pervasive. + +Slang's base reflection API *intentionally* does not provide information about which shader parameters are or are not used by a program, or specific entry points. +This choice ensures that applications using the reflection API can robustly re-use data structures built from reflection data across hot reloads of shaders, or switches between variants of a program. + +Applications that need to know which parameters are used (and by which entry points or stages) need to query for additional metadata connected to the entry points of their compiled program using `IComponentType::getEntryPointMetadata()`: + +```c++ +slang::IComponentType* program = ...; +slang::IMetadata* entryPointMetadata; +program->getEntryPointMetadata( + entryPointIndex, + 0, // target index + &entryPointMetadata); +``` + +When traversal of reflection data reaches a leaf parameter, the application can use `IMetadata::isParameterLocationUsed()` with the absolute location of that parameter for a given layout unit: + +```c++ +unsigned calculateParameterStageMask( + slang::ParameterCategory layoutUnit, + CumulativeOffset offset) +{ + unsigned mask = 0; + for(int i = 0; i < entryPointCount; ++i) + { + bool isUsed = false; + entryPoints[i].metadata->isParameterLocationUsed( + layoutUnit, offset.space, offset.value, isUsed); + if(isUsed) + { + mask |= 1 << unsigned(entryPoints[i].stage); + } + } + return mask; +} +``` + +The application can then incorporate this logic into a loop over the layout units consumed by a parameter: + +```c++ +unsigned calculateParameterStageMask( + slang::VariableLayoutReflection* varLayout, + AccessPath accessPath) +{ + unsigned mask = 0; + + int usedLayoutUnitCount = varLayout->getCategoryCount(); + for (int i = 0; i < usedLayoutUnitCount; ++i) + { + auto layoutUnit = varLayout->getCategoryByIndex(i); + auto offset = calculateCumulativeOffset( + varLayout, layoutUnit, accessPath); + + mask |= calculateStageMask( + layoutUnit, offset); + } + + return mask; +} +``` + +Finally, we can wrap all this up into logic to print which stage(s) use a given parameter, based on the information in the per-entry-point metadata: + +```c++ +void printVarLayout( + slang::VariableLayoutReflection* varLayout, + AccessPath accessPath) +{ + //... + unsigned stageMask = calculateStageMask( + varLayout, accessPath); + + print("used by stages: "); + for(int i = 0; i < SLANG_STAGE_COUNT; i++) + { + if(stageMask & (1 << i)) + { + print("- "); + printStage(SlangStage(i)); + } + } + // ... +} +``` + +Conclusion +---------- + +At this point we have provided a comprehensive example of how to robustly traverse the information provided by the Slang reflection API to get a complete picture of the shader parameters of a program, and what target-specific locations they were bound to. +We hope that along the way we have also imparted some key parts of the mental model that exists behind the reflection API and its representations. diff --git a/lib/All/slang/share/doc/slang/user-guide/09-targets.md b/lib/All/slang/share/doc/slang/user-guide/09-targets.md new file mode 100644 index 0000000..1e2fe7c --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/09-targets.md @@ -0,0 +1,460 @@ +--- +layout: user-guide +permalink: /user-guide/targets +--- + +# Supported Compilation Targets + +This chapter provides a brief overview of the compilation targets supported by Slang, and their different capabilities. + +## Background and Terminology + +### Code Formats + +When Slang compiles for a target platform one of the most important distinctions is the _format_ of code for that platform. +For a native CPU target, the format is typically the executable machine-code format for the processor family (for example, x86-64). +In contrast, GPUs are typically programmed through APIs that abstract over multiple GPU processor families and versions. +GPU APIs usually define an _intermediate language_ that sits between a high-level-language compiler like Slang and GPU-specific compilers that live in drivers for the API. + +### Pipelines and Stages + +GPU code execution occurs in the context of a _pipeline_. +A pipeline comprises one or more _stages_ and dataflow connections between them. +Some stages are _programmable_ and run a user-defined _kernel_ that has been compiled from a language like Slang, while others are _fixed-function_ and can only be configured, rather than programmed, by the user. +Slang supports three different pipelines. + +#### Rasterization + +The _rasterization_ pipeline is the original GPU rendering pipeline. +On current GPUs, the simplest rasterization pipelines have two programmable stages: a `vertex` stage and a `fragment` stage. +The rasterization pipeline is named after its most important fixed-function stage: the rasterizer, which determines the pixels covered by a geometric primitive, and emits _fragments_ covering those pixels, to be shaded. + +#### Compute + +The _compute_ pipeline is a simple pipeline with only one stage: a programmable `compute` stage. +As a result of being a single-stage pipeline the compute pipeline doesn't need to deal with many issues around inter-stage dataflow that other pipelines do. + +#### Ray Tracing + +A _ray tracing_ pipeline has multiple stages pertaining to the life cycle of a ray being traced through a scene of geometric primitives. +These can include an `intersection` stage to compute whether a ray intersects a geometry primitive, a `miss` stage that runs when a ray does not intersect any geometric object in a scene, etc. + +Note that some platforms support types and operations related to ray tracing that can run outside of the context of a dedicated ray tracing pipeline. +Just as applications can do computation outside of the dedicated compute pipeline, the use of ray tracing does not necessarily mean that a ray tracing pipeline is being used. + +### Shader Parameter Bindings + +The kernels that execute within a pipeline typically has access to four different kinds of data: + +- _Varying inputs_ coming from the system or from a preceding pipeline stage + +- _Varying outputs_ which will be passed along to the system or to a following pipeline stage + +- _Temporaries_ which are scratch memory or registers used by each invocation of the kernel and then dismissed on exit. + +- _Shader parameters_ (sometimes also called _uniform parameters_), which provide access to data from outside the pipeline dataflow + +The first three of these kinds of data are largely handled by the implementation of a pipeline. +In contrast, an application programmer typically needs to manually prepare shader parameters, using the appropriate mechanisms and rules for each target platform. + +On platforms that provide a CPU-like "flat" memory model with a single virtual address space, and where any kind of data can be stored at any address, passing shader parameters can be almost trivial. +Current graphics APIs provide far more complicated and less uniform mechanisms for passing shader parameters. + +A high-level language compiler like Slang handles the task of _binding_ each user-defined shader parameter to one or more of the parameter-passing resources defined by a target platform. +For example, the Slang compiler might bind a global `Texture2D` parameter called `gDiffuse` to the `t1` register defined by the Direct3D 11 API. + +An application is responsible for passing the argument data for a parameter using the using the corresponding platform-specific resource it was bound to. +For example, an application should set the texture they want to use for `gDiffuse` to the `t1` register using Direct3D 11 API calls. + +#### Slots + +Historically, most graphics APIs have used a model where shader parameters are passed using a number of API-defined _slots_. +Each slot can store a single argument value of an allowed type. +Depending on the platform slots might be called "registers," "locations," "bindings," "texture units," or other similar names. + +Slots almost exclusively use opaque types: textures, buffers, etc. +On platforms that use slots for passing shader parameters, value of ordinary types like `float` or `int` need to be stored into a buffer, and then that buffer is passed via an appropriate slot. + +Although many graphics APIs use slots as an abstraction, the details vary greatly across APIs. +Different APIs define different kinds of slots, and the types of arguments that may be stored in those slots vary. +For example, one API might use two different kinds of slots for textures and buffers, while another uses a single kind of slot for both. +On some APIs each pipeline stage gets is own dedicated slots, while on others slots are shared across all stages in a pipeline. + +#### Blocks + +Newer graphics APIs typically provide a system for grouping related shader parameters into re-usable _blocks_. +Blocks might be referred to as "descriptor tables," "descriptor sets," or "argument buffers." +Each block comprises one or more slots (often called "descriptors") that can be used to bind textures, buffers, etc. + +Blocks are in turn set into appropriate slots provided by a pipeline. +Because a block can contain many different slots for textures or buffers, switching a pipeline argument from one block to another can effectively swap out a large number of shader parameters in one operation. +Thus, while blocks introduce a level of indirection to parameter setting, then can also enable greater efficiency when parameters are grouped into blocks according to frequency of change. + +#### Root Constants + +Most recent graphics APIs also allow for a small amount of ordinary data (meaning types like `float` and `int` but not opaque types like buffers or textures) to be passed to the pipeline as _root constants_ (also called "push constants"). + +Using root constants can eliminate some overheads from passing parameters of ordinary types via buffers. +Passing a single `float` using a root constant rather than a buffer obviously eliminates a level of indirection. +More importantly, though, using a root constant can avoid application code having to allocate and manage the lifetime of a buffer in a concurrent CPU/GPU program. + +## Direct3D 11 + +Direct3D 11 (D3D11) is an older graphics API, but remains popular because it is much simpler to learn and use than some more recent APIs. +In this section we will give an overview of the relevant features of D3D11 when used as a target platform for Slang. +Subsequent sections about other APIs may describe them by comparison to D3D11. + +D3D11 kernels must be compiled to the DirectX Bytecode (DXBC) intermediate language. +A DXBC binary includes a hash/checksum computed using an undocumented algorithm, and the runtime API rejects kernels without a valid checksum. +The only supported way to generate DXBC is by compiling HLSL using the fxc compiler. + +### Pipelines + +D3D11 exposes two pipelines: rasterization and compute. + +The D3D11 rasterization pipeline can include up to five programmable stages, although most of them are optional: + +- The `vertex` stage (VS) transforms vertex data loaded from memory + +- The optional `hull` stage (HS) typically sets up and computes desired tessellation levels for a higher-order primitive + +- The optional `domain` stage (DS) evaluates a higher-order surface at domain locations chosen by a fixed-function tessellator + +- The optional `geometry` stage (GS) receives as input a primitive and can produce zero or more new primitives as output + +- The optional `fragment` stage transforms fragments produced by the fixed-function rasterizer, determining the values for those fragments that will be merged with values in zero or more render targets. The fragment stage is sometimes called a "pixel" stage (PS), even when it does not process pixels. + +### Parameter Passing + +Shader parameters are passed to each D3D11 stage via slots. +Each stage has its own slots of the following types: + +- **Constant buffers** are used for passing relatively small (4KB or less) amounts of data that will be read by GPU code. Constant buffers are passed via `b` registers. + +- **Shader resource views** (SRVs) include most textures, buffers, and other opaque resource types there are read or sampled by GPU code. SRVs use `t` registers. + +- **Unordered access views** (UAVs) include textures, buffers, and other opaque resource types used for write or read-write operations in GPU code. UAVs use `u` registers. + +- **Samplers** are used to pass opaque texture-sampling state, and use `s` registers. + +In addition, the D3D11 pipeline provides _vertex buffer_ slots and a single _index buffer_ slot to be used as the source vertex and index data that defines primitives. +User-defined varying vertex shader inputs are bound to _vertex attribute_ slots (referred to as "input elements" in D3D11) which define how data from vertex buffers should be fetched to provide values for vertex attributes. + +The D3D11 rasterization pipeline also provides a mechanism for specifying _render target views_ (RTVs) and _depth-stencil views_ (DSVs) that provide the backing storage for the pixels in a framebuffer. +User-defined fragment shader varying outputs (with `SV_Target` binding semantics) are bound to RTV slots. + +One notable detail of the D3D11 API is that the slots for fragment-stage UAVs and RTVs overlap. +For example, a fragment kernel cannot use both `u0` and `SV_Target0` at once. + +## Direct3D 12 + +Direct3D 12 (D3D12) is the current major version of the Direct3D API. + +D3D12 kernels must be compiled to the DirectX Intermediate Language (DXIL). +DXIL is a layered encoding based off of LLVM bitcode; it introduces additional formatting rules and constraints which are loosely documented. +A DXIL binary may be signed, and the runtime API only accepts appropriately signed binaries (unless a developer mode is enabled on the host machine). +A DXIL validator `dxil.dll` is included in SDK releases, and this validator can sign binaries that pass validation. +While DXIL can in principle be generated from multiple compiler front-ends, support for other compilers is not prioritized. + +### Pipelines + +D3D12 includes rasterization and compute pipelines similar to those in D3D11. +Revisions to D3D12 have added additional stages to the rasterization pipeline, as well as a ray-tracing pipeline. + +#### Mesh Shaders + +> #### Note +> +> The Slang system does not currently support mesh shaders. + +The D3D12 rasterization pipeline provides alternative geometry processing stages that may be used as an alternative to the `vertex`, `hull`, `domain`, and `geometry` stages: + +- The `mesh` stage runs groups of threads which are responsible cooperating to produce both the vertex and index data for a _meshlet_ a bounded-size chunk of geometry. + +- The optional `amplification` stage precedes the mesh stage and is responsible for determining how many mesh shader invocations should be run. + +Compared to the D3D11 pipeline without tessellation (hull and domain shaders), a mesh shader is kind of like a combined/generalized vertex and geometry shader. + +Compared to the D3D11 pipeline with tessellation, an amplification shader is kind of like a combined/generalized vertex and hull shader, while a mesh shader is kind of like a combined/generalized domain and geometry shader. + +#### Ray Tracing + +The DirectX Ray Tracing (DXR) feature added a ray tracing pipeline to D3D12. +The D3D12 ray tracing pipeline exposes the following programmable stages: + +- The ray generation (`raygeneration`) stage is similar to a compute stage, but can trace zero or more rays and make use of the results of those traces. + +- The `intersection` stage runs kernels to compute whether a ray intersects a user-defined primitive type. The system also includes a default intersector that handles triangle meshes. + +- The so-called any-hit (`anyhit`) stage runs on _candidate_ hits where a ray has intersected some geometry, but the hit must be either accepted or rejected by application logic. Note that the any-hit stage does not necessarily run on _all_ hits, because configuration options on both scene geometry and rays can lead to these checks being bypassed. + +- The closest-hit (`closesthit`) stage runs a single _accepted_ hit for a ray; under typical circumstances this will be the closest hit to the origin of the ray. A typical closest-hit shader might compute the apparent color of a surface, similar to a typical fragment shader. + +- The `miss` stage runs for rays that do not find or accept any hits in a scene. A typical miss shader might return a background color or sample an environment map. + +- The `callable` stage allows user-defined kernels to be invoked like subroutines in the context of the ray tracing pipeline. + +Compared to existing rasterization and compute pipelines, an important difference in the design of the D3D12 ray tracing pipeline is that multiple kernels can be loaded into the pipeline for each of the programming stages. +The specific closest-hit, miss, or other kernel that runs for a given hit or ray is determined by indexing into an appropriate _shader table_, which is effectively an array of kernels. +The indexing into a shader table can depend on many factors including the type of ray, the type of geometry hit, etc. + +Note that DXR version 1.1 adds ray tracing types and operations that can be used outside of the dedicated ray tracing pipeline. +These new mechanisms have less visible impact for a programmer using or integrating Slang. + +### Parameter Passing + +The mechanisms for parameter passing in D3D12 differ greatly from D3D11. +Most opaque types (texture, resources, samplers) must be set into blocks (D3D12 calls blocks "descriptor tables"). +Each pipeline supports a fixed amount of storage for "root parameters," and allows those root parameters to be configured as root constants, slots for blocks, or slots for a limited number of opaque types (primarily just flat buffers). + +Shader parameters are still grouped and bound to registers as in D3D11; for example, a `Texture2D` parameter is considered as an SRV and uses a `t` register. +D3D12 additionally associates binds shader parameters to "spaces" which are expressed similarly to registers (e.g., `space2`), but represent an orthogonal "axis" of binding. + +While shader parameters are bound registers and spaces, those registers and spaces do not directly correspond to slots provided by the D3D12 API the way registers do in D3D11. +Instead, the configuration of the root parameters and the correspondence of registers/spaces to root parameters, blocks, and/or slots are defined by a _pipeline layout_ that D3D12 calls a "root signature." + +Unlike D3D11, all of the stages in a D3D12 pipeline share the same root parameters. +A D3D12 pipeline layout can specify that certain root parameters or certain slots within blocks will only be accessed by a subset of stages, and can map the _same_ register/space pair to different parameters/blocks/slots as long as this is done for disjoint subset of stages. + +#### Ray Tracing Specifics + +The D3D12 ray tracing pipeline adds a new mechanism for passing shader parameters. +In addition to allowing shader parameters to be passed to the entire pipeline via root parameters, each shader table entry provides storage space for passing argument data specific to that entry. + +Similar to the use of a pipeline layout (root signature) to configure the use of root parameters, each kernel used within shader entries must be configured with a "local root signature" that defines how the storage space in the shader table entry is to be used. +Shader parameters are still bound to registers and spaces as for non-ray-tracing code, and the local root signature simply allows those same registers/spaces to be associated with locations in a shader table entry. + +One important detail is that some shader table entries are associated with a kernel for a single stage (e.g., a single miss shader), while other shader table entries are associated with a "hit group" consisting of up to one each of an intersection, any-hit, and closest-hit kernel. +Because multiple kernels in a hit group share the same shader table entry, they also share the configured slots in that entry for binding root constants, blocks, etc. + +## Vulkan + +Vulkan is a cross-platform GPU API for graphics and compute with a detailed specification produced by a multi-vendor standards body. +In contrast with OpenGL, Vulkan focuses on providing explicit control over as many aspects of GPU work as possible. +In contrast with OpenCL, Vulkan focuses first and foremost on the needs of real-time graphics developers. + +Vulkan requires kernels to be compiled to the SPIR-V intermediate language. +SPIR-V is a simple and extensible binary program format with a detailed specification; it is largely unrelated to earlier "SPIR" formats that were LLVM-based and loosely specified. +The SPIR-V format does not require signing or hashing, and is explicitly designed to allow many different tools to produce and manipulate the format. +Drivers that consume SPIR-V are expected to perform validation at load time. +Some choices in the SPIR-V encoding are heavily influenced by specific design choices in the GLSL language, and may require non-GLSL compilers to transform code to match GLSL idioms. + +### Pipelines + +Vulkan includes rasterization, compute, and ray tracing pipelines with the same set of stages as described for D3D12 above. + +### Parameter Passing + +Like D3D12, Vulkan uses blocks (called "descriptor sets") to organize groups of bindings for opaque types (textures, buffers, samplers). +Similar to D3D12, a Vulkan pipeline supports a limited number of slots for passing blocks to the pipeline, and these slots are shared across all stages. +Vulkan also supports a limited number of bytes reserved for passing root constants (called "push constants"). +Vulkan uses pipeline layouts to describe configurations of usage for blocks and root constants. + +High-level-language shader parameters are bound to a combination of a "binding" and a "set" for Vulkan, which are superficially similar to the registers and spaces of D3D12. +Unlike D3D12, however, bindings and sets in Vulkan directly correspond to the API-provided parameter-passing mechanism. +The set index of a parameter indicates the zero-based index of a slot where a block must be passed, and the binding index is the zero-based index of a particular opaque value set into the block. +A shader parameter that will be passed using root constants (rather than via blocks) must be bound to a root-constant offset as part of compilation. + +Unlike D3D12, where SRVs, UAVs, etc. use distinct classes of registers, all opaque-type shader parameters use the same index space of bindings. +That is, a buffer and a texture both using `binding=2` in `set=3` for Vulkan will alias the same slot in the same block. + +The Vulkan ray tracing pipeline also uses a shader table, and also forms hit groups similar to D3D12. +Unlike D3D12, each shader table entry in Vulkan can only be used to pass ordinary values (akin to root constants), and cannot be configured for binding of opaque types or blocks. + +## OpenGL + +> #### Note +> +> Slang has only limited support for compiling code for OpenGL. + +OpenGL has existed for many years, and predates programmable GPU pipelines of the kind this chapter discusses; we will focus solely on use of OpenGL as an API for programmable GPU pipelines. + +OpenGL is a cross-platform GPU API for graphics and compute with a detailed specification produced by a multi-vendor standard body. +In contrast with Vulkan, OpenGL provides many convenience and safety features that can simplify GPU programming. + +OpenGL allows kernels to be loaded as SPIR-V binaries, vendor-specific binaries, or using GLSL source code. +Loading shaders as GLSL source code is the most widely supported of these options, such that GLSL is the _de facto_ intermediate language of OpenGL. + +### Pipelines + +OpenGL supports rasterization and compute pipelines with the same stages as described for D3D11. +The OpenGL rasterization pipeline also supports the same mesh shader stages that are supported by D3D12. + +### Parameter Passing + +OpenGL uses slots for binding. +There are distinct kinds of slots for buffers and textures/images, and each set of slots is shared by all pipeline stages. + +High-level-language shader parameters are bounding to a "binding" index for OpenGL. +The binding index of a parameter is the zero-based index of the slot (of the appropriate kind) that must be used to pass an argument value. + +Note that while OpenGL and Vulkan both use binding indices for shader parameters like textures, the semantics of those are different because OpenGL uses distinct slots for passing buffers and textures. +For OpenGL it is legal to have a texture that uses `binding=2` and a buffer that uses `binding=2` in the same kernel, because those are indices of distinct kinds of slots, while this scenario would typically be invalid for Vulkan. + +## Metal + +> #### Note +> +> Slang support for Metal is a work in progress. + +Metal is Apple's proprietary graphics and compute API for iOS and macOS +platforms. It provides a modern, low-overhead architecture similar to Direct3D +12 and Vulkan. + +Metal kernels must be compiled to the Metal Shading Language (MSL), which is +based on C++14 with additional GPU-specific features and constraints. Unlike +some other APIs, Metal does not use an intermediate representation - MSL source +code is compiled directly to platform-specific binaries by Apple's compiler. + +### Pipelines + +Metal supports rasterization, compute, and ray tracing pipelines. + +> #### Note +> +> Ray-tracing support for Metal is a work in progress. + +The Metal rasterization pipeline includes the following programmable stages: + +- The vertex stage outputs vertex data + +- The optional mesh stage allows groups of threads to cooperatively generate geometry + +- The optional task stage can be used to control mesh shader invocations + +- The optional tessellation stages (kernel, post-tessellation vertex) enable hardware tessellation + +- The fragment stage processes fragments produced by the rasterizer + +### Parameter Passing + +Metal uses a combination of slots and blocks for parameter passing: + +- Resources (buffers, textures, samplers) are bound to slots using explicit + binding indices + +- Argument buffers (similar to descriptor tables/sets in other APIs) can group + multiple resources together + +- Each resource type (buffer, texture, sampler) has its own independent binding + space + +- Arguments within argument buffers are referenced by offset rather than + explicit bindings + +Unlike some other APIs, Metal: + +- Does not support arrays of buffers as of version 3.1 +- Shares binding slots across all pipeline stages +- Uses argument buffers that can contain nested resources without consuming additional binding slots + +The Metal ray tracing pipeline follows similar parameter passing conventions to +the rasterization and compute pipelines, while adding intersection, +closest-hit, and miss stages comparable to those in Direct3D 12 and Vulkan. + +## CUDA and OptiX + +> #### Note +> +> Slang support for OptiX is a work in progress. + +CUDA C/C++ is a language for expressing heterogeneous CPU and GPU code with a simple interface to invoking GPU compute work. +OptiX is a ray tracing API that uses CUDA C++ as the language for expressing shader code. +We focus here on OptiX version 7 and up. + +CUDA and OptiX allow kernels to be loaded as GPU-specific binaries, or using the PTX intermediate language. + +### Pipelines + +CUDA supports a compute pipeline that is similar to D3D12 or Vulkan, with additional features. + +OptiX introduced the style of ray tracing pipeline adopted by D3D12 and Vulkan, and thus uses the same basic stages. + +The CUDA system does not currently expose a rasterization pipeline. + +### Parameter Passing + +Unlike most of the GPU APIs discussed so far, CUDA supports a "flat" memory model with a single virtual address space for all GPU data. +Textures, buffers, etc. are not opaque types, but can instead sit in the same memory as ordinary data like `float`s or `int`s. + +With a flat memory model, a distinct notion of a slot or block is not needed. +A slot is just an ordinary memory location that happens to be used to store a value of texture, buffer, or other resource type. +A block is just an ordinary memory buffer that happens to be filled with values of texture/buffer/etc. type. + +CUDA provides two parameter-passing mechanisms for the compute pipeline. +First, when invoking a compute kernel, the application passes a limited number of bytes of parameter data that act as root constants. +Second, each loaded module of GPU code may contain pre-allocated "constant memory" storage which can be initialized from the host and then read by GPU code. +Because types like blocks or textures are not special in CUDA, either of these mechanisms can be utilized to pass any kind of data including references to pointer-based data structures stored in the GPU virtual address space. +The use of "slots" or "blocks" or "root constants" is a matter of application policy instead of API mechanism. + +OptiX supports use of constant memory storage for ray tracing pipelines, where all the stages in a ray tracing pipeline share that storage. +OptiX uses a shader table for managing kernels and hit groups, and allows kernels to access the bytes of their shader table entry via a pointer. +Similar to the compute pipeline, application code can layer many different policies on top of these mechanisms. + +## CPU Compute + +> #### Note +> +> Slang's support for CPU compute is functional, but not feature- or performance-complete. +> Backwards-incompatible changes to this target may come in future versions of Slang. + +For the purposes of Slang, different CPU-based host platforms are largely the same. +All support binary code in a native machine-code format. +All CPU platforms Slang supports use a flat memory model with a single virtual address space, where any data type can be stored at any virtual address. + +Note that this section considers CPU-based platforms only as targets for kernel compilation; using a CPU as a target for scalar "host" code is an advanced target beyond the scope of this document. + +### Pipelines + +Slang's CPU compute target supports only a compute pipeline. + +### Parameter Passing + +Because CPU target support flexible pointer-based addressing and large low-latency caches, a compute kernel can simply be passed a small fixed number of pointers and be relied upon to load parameter values of any types via indirection through those pointers. + +## WebGPU + +> #### Note +> +> Slang support for WebGPU is work in progress. + +WebGPU is a graphics and compute API. +It is similar in spirit to modern APIs, like Metal, Direct3D 12 and Vulkan, but with concessions to portability and privacy. + +WebGPU is available both in browsers as a JavaScript API, and natively as a C/C++ API. +[Dawn](https://github.com/google/dawn), is a native WebGPU implementation used by the Chrome browser. + +By combining Slang, [Dawn](https://github.com/google/dawn) and [Emscripten](https://emscripten.org/), +an application can easily target any native API, and the web, with a single codebase consisting of C++ and Slang code. + +WebGPU shader modules are created from WGSL (WebGPU Shading Language) source files. +WebGPU does not use an intermediate representation - WGSL code is compiled to backend-specific code by +compilers provided by the WebGPU implementation. + +### Pipelines + +WebGPU supports render and compute pipelines. + +The WebGPU render pipeline includes the following programmable stages: + +- The vertex stage outputs vertex data + +- The fragment stage outputs fragments + +### Parameter Passing + +WebGPU uses groups of bindings called bind groups to bind things like textures, buffers and samplers. +Bind group objects are passed as arguments when encoding bind group setting commands. + +There is a notion of equivalence for bind groups, and a notion of equivalence for pipelines defined in +terms of bind group equivalence. +This equivalence allows an application to save some bind group setting commands, when switching between +pipelines, if bindings are grouped together appropriately. + +Which bindings are grouped together can be controlled using Slang's `ParameterBlock` generic type. + +## Summary + +This chapter has reviewed the main target platforms supported by the Slang compiler and runtime system. +A key point to take away is that there is great variation in the capabilities of these systems. +Even superficially similar graphics APIs have complicated differences in their parameter-passing mechanisms that must be accounted for by application programmers and GPU compilers. diff --git a/lib/All/slang/share/doc/slang/user-guide/10-link-time-specialization.md b/lib/All/slang/share/doc/slang/user-guide/10-link-time-specialization.md new file mode 100644 index 0000000..bda8692 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/10-link-time-specialization.md @@ -0,0 +1,239 @@ +--- +layout: user-guide +permalink: /user-guide/link-time-specialization +--- + +# Link-time Specialization and Module Precompilation + +Traditionally, graphics developers have been relying on preprocessor defines to specialize their shader code for high-performance GPU execution. +While functioning systems can be built around preprocessor macros, overusing them leads to many problems: +- Long compilation time. With preprocessor defines, specialization happens before parsing, which is a very early stage in the compilation flow. + This means that the compiler must redo almost all work from scratch with every specialized variant, including parsing, type checking, IR generation + and optimization, even when two specialized variants only differ in one constant value. The lack of reuse of compiler front-end work between + different shader specializations contributes a significant portion to long shader compile times. +- Reduced code readability and maintainability. The compiler cannot enforce any structures on preprocessor macros and cannot offer static checks to + guarantee that the preprocessor macros are used in an intended way. Macros don't blend well with the native language syntax, which leads to less + readable code, mystic diagnostic messages when things go wrong, and suboptimal intellisense experience. +- Locked in with early specialization. Once the code is written using preprocessor macros for specialization, the application that uses the shader + code has no choice but to provide the macro values during shader compilation and always opt-in to static specialization. If the developer changes + their mind to move away from specialization, a lot of code needs to be rewritten. As a result, the application is locked out of opportunities to + take advantage of different design decisions or future hardware features that allow more efficient execution of non-specialized code. + +Slang approaches the problem of shader specialization by supporting generics as a first class feature that allow most specializable code to be +written in strongly typed code, and by allowing specialization to be triggered through link-time constants or types. + +As discussed in the [Compiling code with Slang](08-compiling.md) chapter, Slang provides a three-step compilation model: precompiling, linking and target code generation. +Assuming the user shader is implemented as three Slang modules: `a.slang`, `b.slang`, and `c.slang`, the user can precompile all three modules to binary IR and store +them as `a.slang-module`, `b.slang-module`, and `c.slang-module` in a complete offline process that is independent to any specialization arguments. +Next, these three IR modules are linked together to form a self-contained program that will then go through a set of compiler optimizations for target code generation. +Slang's compilation model allows specialization arguments, in the form of constants or types to be provided during linking. This means that specialization happens at +a much later stage of compilation, reusing all the work done during module precompilation. + +## Link-time Constants + +The simplest form of link time specialization is done through link-time constants. See the following code for an example. +```c++ +// main.slang + +// Define a constant whose value will be provided in another module at link time. +extern static const int kSampleCount; + +float sample(int index) {...} + +RWStructuredBuffer output; +void main(uint tid : SV_DispatchThreadID) +{ + [ForceUnroll] + for (int i = 0; i < kSampleCount; i++) + output[tid] += sample(i); +} +``` +This code defines a compute shader that can be specialized with different constant values of `kSampleCount`. The `extern` modifier means that +`kSampleCount` is a constant whose value is not provided within the current module, but will be resolved during the linking step. +The `main.slang` file can be compiled offline into a binary IR module with the `slangc` tool: +``` +slangc main.slang -o main.slang-module +``` + +To specialize the code with a value of `kSampleCount`, the user can create another module that defines it: + +```c++ +// sample-count.slang +export static const int kSampleCount = 2; +``` + +This file can also be compiled separately: +``` +slangc sample-count.slang -o sample-count.slang-module +``` + +With these two modules precompiled, we can link them together to get our specialized code: +``` +slangc sample-count.slang-module main.slang-module -target hlsl -entry main -profile cs_6_0 -o main.hlsl +``` + +This process can also be done with Slang's compilation API as in the following code snippet: + +```c++ + +ComPtr slangSession = ...; +ComPtr diagnosticsBlob; + +// Load the main module from file. +slang::IModule* mainModule = slangSession->loadModule("main.slang", diagnosticsBlob.writeRef()); + +// Load the specialization constant module from string. +const char* sampleCountSrc = R"(export static const int kSampleCount = 2;)"; +slang::IModule* sampleCountModule = slangSession->loadModuleFromSourceString( + "sample-count", // module name + "sample-count.slang", // synthetic module path + sampleCountSrc, // module source content + diagnosticsBlob.writeRef()); + +// Compose the modules and entry points. +ComPtr computeEntryPoint; +SLANG_RETURN_ON_FAIL( + mainModule->findEntryPointByName(entryPointName, computeEntryPoint.writeRef())); + +std::vector componentTypes; +componentTypes.push_back(mainModule); +componentTypes.push_back(computeEntryPoint); +componentTypes.push_back(sampleCountModule); + +ComPtr composedProgram; +SlangResult result = slangSession->createCompositeComponentType( + componentTypes.data(), + componentTypes.size(), + composedProgram.writeRef(), + diagnosticsBlob.writeRef()); + +// Link. +ComPtr linkedProgram; +composedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef()); + +// Get compiled code. +ComPtr compiledCode; +linkedProgram->getEntryPointCode(0, 0, compiledCode.writeRef(), diagnosticsBlob.writeRef()); + +``` + +## Link-time Types + +In addition to constants, you can also define types that are specified at link-time. For example, given the following modules: + +```csharp +// common.slang +interface ISampler +{ + int getSampleCount(); + float sample(int index); +} +struct FooSampler : ISampler +{ + int getSampleCount() { return 1; } + float sample(int index) { return 0.0; } +} +struct BarSampler : ISampler +{ + int getSampleCount() { return 2; } + float sample(int index) { return index * 0.5; } +} +``` + +```csharp +// main.slang +import common; +extern struct Sampler : ISampler; + +RWStructuredBuffer output; +void main(uint tid : SV_DispatchThreadID) +{ + Sampler sampler; + for (int i = 0; i < sampler.getSampleCount(); i++) + output[tid] += sampler.sample(i); +} +``` + +Again, we can separately compile these modules into binary forms independently from how they will be specialized. +To specialize the shader, we can author a third module that provides a definition for the `extern Sampler` type: + +```csharp +// sampler.slang +import common; +export struct Sampler : ISampler = FooSampler; +``` + +The `=` syntax defines a typealias that allows `Sampler` to resolve to `FooSampler` at link-time. +Note that both the name and type conformance clauses must match exactly between an `export` and an `extern` declaration +for link-time types to resolve correctly. Link-time types can also be generic, and may conform to generic interfaces. + +When all these three modules are linked, we will produce a specialized shader that uses the `FooSampler`. + +## Providing Default Settings + +When defining an `extern` symbol as a link-time constant or type, it is allowed to provide a default value for that constant or type. +When no other modules exists to `export` the same-named symbol, the default value will be used in the linked program. + +For example, the following code is considered complete at linking and can proceed to code generation without any issues: +```c++ +// main.slang + +// Provide a default value when no other modules are exporting the symbol. +extern static const int kSampleCount = 2; +// ... +void main(uint tid : SV_DispatchThreadID) +{ + [ForceUnroll] + for (int i = 0; i < kSampleCount; i++) + output[tid] += sample(i); +} +``` + +## Using Precompiling Modules with the API + +In addition to using `slangc` for precompiling Slang modules, the `IModule` class provides a method to serialize itself to disk: + +```C++ +/// Get a serialized representation of the checked module. +SlangResult IModule::serialize(ISlangBlob** outSerializedBlob); + +/// Write the serialized representation of this module to a file. +SlangResult IModule::writeToFile(char const* fileName); +``` + +These functions will write only the module itself to a file, which excludes the modules that it includes. To write all imported +modules, you can use methods from the `ISession` class to enumerate all currently loaded modules (including transitively imported modules) +in the session: + +```c++ +SlangInt ISession::getLoadedModuleCount(); +IModule* ISession::getLoadedModule(SlangInt index); +``` + +Additionally, the `ISession` class also provides a function to query if a previously compiled module is still up-to-date with the current +Slang version, the compiler options in the session and the current content of the source files used to compile the module: + +```c++ +bool ISession::isBinaryModuleUpToDate( + const char* modulePath, + slang::IBlob* binaryModuleBlob); +``` + +If the compiler options or source files have been changed since the module was last compiled, the `isBinaryModuleUpToDate` will return false. + +The compiler can be setup to automatically use the precompiled modules when they exist and up-to-date. When loading a module, +either triggered via the `ISession::loadModule` call or via transitive `import`s in the modules being loaded, the compiler will look in the +search paths for a `.slang-module` file first. If it exists, it will load the precompiled module instead of compiling from the source. +If you wish the compiler to verify whether the `.slang-module` file is up-to-date before loading it, you can specify the `CompilerOptionName::UseUpToDateBinaryModule` to `1` +when creating the session. When this option is set, the compiler will verify the precompiled module is still update, and will recompile the module +from source if it is not up-to-date. + + +## Additional Remarks + +Link-time specialization is Slang's answer to compile-time performance and modularity issues associated with preprocessor +based shader specialization. By representing specializable settings as link-time constants or link-time types, we are able +to defer shader specialization to link time, allowing reuse of all the front-end compilation work that includes tokenization, +parsing, type checking, IR generation and validation. As Slang evolves to support more language features and as the user code +is growing to be more complex, the cost of front-end compilation will only increase over time. By using link-time specialization +on precompiled modules, an application can be completely isolated from any front-end compilation cost. \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/11-language-version.md b/lib/All/slang/share/doc/slang/user-guide/11-language-version.md new file mode 100644 index 0000000..74b4c33 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/11-language-version.md @@ -0,0 +1,41 @@ +# Language Version + +Like many programming languages, Slang experiences a tension between the desire for rapid innovation/evolution and stability. One of the benefits that users of Slang have so far enjoyed has been the rapid pace of innovation in the language and its standard library. However, as developers start to have larger bodies of Slang code, they may become concerned that changes to the language could break existing code. There is no magical way to keep innovating while also keeping the language static. + +Slang supports using `#language` preprocessor directive, as well as the `-std` compiler option (`CompilerOptionName::LanguageVersion`) to specify the language version that a source file is written against. The source file will then be parsed and checked by the compiler using the rules from the specified language version. + +Users are advised to provide a `#language` directive as the first non-white-space line in their source file, such as: + +``` +#language slang 2026 +``` + +The following version strings are allowed: +- `latest`: use the latest language version supported by the current compiler. +- `legacy`: use the legacy Slang language. +- `2018`: equivalent to `legacy`. +- `2025`: Slang language version 2025. +- `2026`: Slang language version 2026. + +If no `#language` line exists and no version is specified via compiler options, the default setting is `legacy`. + +## The Legacy Slang Language + +When language version is set to `legacy`, the compiler behavior will be consistent with the Slang language as in 2018-2023. Specifically: + +- All declarations have `public` visibility. +- `module` declaration is not required at the start of each module. + +## Slang 2025 + +Slang language version 2025 brings these changes on top of the legacy language: + +- All declarations have `internal` visibility. +- `module` declaration is required at the start of each module. + +## Slang 2026 + +Slang language 2026 brings these changes on top of Slang 2025: + +- Comma expression is removed when it is used inside a parenthesis. The expression `(a, b)` no longer evaluates to have `b`'s type as in C/C++. Instead, `(a,b)` means `makeTuple(a,b)` and returns a tuple consists of `a` and `b`. See [SP#027](https://github.com/shader-slang/spec/blob/main/proposals/027-tuple-syntax.md) for details. +- User must explicitly opt-in to enable dynamic dispatch with `dyn` keyword. More rigorous validation are enabled to make sure dynamic dispatch is not triggerred accidentally. See [SP#024](https://github.com/shader-slang/spec/blob/main/proposals/024-any-dyn-types.md) for details. diff --git a/lib/All/slang/share/doc/slang/user-guide/a1-01-matrix-layout.md b/lib/All/slang/share/doc/slang/user-guide/a1-01-matrix-layout.md new file mode 100644 index 0000000..b3d98c5 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a1-01-matrix-layout.md @@ -0,0 +1,158 @@ +--- +layout: user-guide +--- + +Handling Matrix Layout Differences on Different Platforms +========================================================= + +The differences between default matrix layout or storage conventions between GLSL (OpenGL/Vulkan) and HLSL has been an issue that frequently causes confusion among developers. When writing applications that work on different targets, one important goal that developers frequently seek is to make it possible to pass the same matrix generated by host code to the same shader code, regardless of what graphics API is being used (e.g. Vulkan, OpenGL or Direct3D). As a solution to shader cross-compilation, Slang provides necessary tools for developers to navigate around the differences between GLSL and HLSL targets. + +A high level summary: + +* Default matrix **layout** in memory for Slang is `row-major`. + * Except when running the compiler through the `slangc` tool, in which case the default is `col-major`. This default is for *legacy* reasons and may change in the future. +* Row-major layout is the only *portable* layout to use across targets (with significant caveats for non 4x4 matrices) +* Use `setMatrixLayoutMode`/`spSetMatrixLayoutMode`/`createSession` to set the default +* Use `-matrix-layout-row-major` or `-matrix-layout-column-major` for the command line + * or via `spProcessCommandLineArguments`/`processCommandLineArguments` +* Depending on your host maths library, matrix sizes and targets, it may be necessary to convert matrices at host/kernel boundary + +On the portability issue, some targets *ignore* the matrix layout mode, notably CUDA and CPU/C++. For this reason for the widest breadth of targets it is recommended to use *row-major* matrix layout. + +Two conventions of matrix transform math +---------------------------------------- + +Depending on the platform a developer is used to, a matrix-vector transform can be expressed as either `v*m` (`mul(v, m)` in HLSL), or `m*v` (`mul(m,v)` in HLSL). This convention, together with the matrix layout (column-major or row-major), determines how a matrix should be filled out in host code. + +In HLSL/Slang the order of vector and matrix parameters to `mul` determine how the *vector* is interpreted. This interpretation is required because a vector does not in and of itself differentiate between being a row or a column. + +* `mul(v, m)` - v is interpreted as a row vector. +* `mul(m, v)` - v is interpreted as a column vector. + +Through this mechanism a developer is able to write transforms in their preferred style. + +These two styles are not directly interchangeable - for a given `v` and `m` then generally `mul(v, m) != mul(m, v)`. For that the matrix needs to be transposed so + +* `mul(v, m) == mul(transpose(m), v)` +* `mul(m, v) == mul(v, transpose(m))` + +This behavior is *independent* of how a matrix layout in memory. Host code needs to be aware of how a shader code will interpret a matrix stored in memory, it's layout, as well as the vector interpretation convention used in shader code (ie `mul(v,m)` or `mul(m, v)`). + +[Matrix layout](https://en.wikipedia.org/wiki/Row-_and_column-major_order) can be either `row-major` or `column-major`. The difference just determines which elements are contiguous in memory. `Row-major` means the rows elements are contiguous. `Column-major` means the column elements are contiguous. + +Another way to think about this difference is in terms of where translation terms should be placed in memory when filling a typical 4x4 transform matrix. When transforming a row vector (ie `mul(v, m)`) with a `row-major` matrix layout, translation will be at `m + 12, 13, 14`. For a `column-major` matrix layout, translation will be at `m + 3, 7, 11`. + +For simplicity's sake the remainder of this discussion assumes that the `mul(v, m)` equivalent in host code follows the interpretation that `v` is a *row* vector. + +Discussion +---------- + +There are four variables in play here: + +* Host vector interpretation (row or column) - and therefore effective transform order (column) `m * v` or (row) `v * m` +* Host matrix memory layout +* Shader vector interpretation (as determined via `mul(v, m)` or `mul(m, v)` ) +* Shader matrix memory layout + +Since each item can be either `row` or `column` there are 16 possible combinations. For simplicity let's reduce the variable space by making some assumptions. + +1) The same vector convention will be used in host code as in shader code. +2) The host maths matrix layout is the same as the kernel. + +If we accept 1, then we can ignore the vector interpretation because as long as they are consistent then only matrix layout is significant. +If we accept 2, then there are only two possible combinations - either both host and shader are using `row-major` matrix layout or `column-major` layout. + +This is simple, but is perhaps not the end of the story. First lets assume that we want our Slang code to be as portable as possible. As previously discussed for CUDA and C++/CPU targets Slang ignores the matrix layout settings - the matrix layout is *always* `row-major`. + +Second lets consider performance. The matrix layout in a host maths library is not arbitrary from a performance point of view. A performant host maths library will want to use SIMD instructions. With both x86/x64 SSE and ARM NEON SIMD it makes a performance difference which layout is used, depending on if `column` or `row` is the *preferred* vector interpretation. If the `row` vector interpretation is preferred, it is most performant to have `row-major` matrix layout. Conversely if `column` vector interpretation is preferred `column-major` matrix will be the most performant. + +The performance difference comes down to a SIMD implementation having to do a transpose if the layout doesn't match the preferred vector interpretation. + +If we put this all together - best performance, consistency between vector interpretation, and platform independence we get: + +1) Consistency : Same vector interpretation in shader and host code +2) Platform independence: Kernel uses `row-major` matrix layout +3) Performance: Host vector interpretation should match host matrix layout + +The only combination that fulfills all aspects is `row-major` matrix layout and `row` vector interpretation for both host and kernel. + +It's worth noting that for targets that honor the default matrix layout - that setting can act like a toggle transposing a matrix layout. If for some reason the combination of choices leads to inconsistent vector transforms, an implementation can perform this transform in *host* code at the boundary between host and the kernel. This is not the most performant or convenient scenario, but if supported in an implementation it could be used for targets that do not support kernel matrix layout settings. + +If only targeting platforms that honor matrix layout, there is more flexibility, our constraints are + +1) Consistency : Same vector interpretation in shader and host code +2) Performance: Host vector interpretation should match host matrix layout + +Then there are two combinations that work + +1) `row-major` matrix layout for host and kernel, and `row` vector interpretation. +2) `column-major` matrix layout for host and kernel, and `column` vector interpretation. + +If the host maths library is not performance orientated, it may be arbitrary from a performance point of view if a `row` or `column` vector interpretation is used. In that case assuming shader and host vector interpretation is the same it is only important that the kernel and maths library matrix layout match. + +Another way of thinking about these combinations is to think of each change in `row-major`/`column-major` matrix layout and `row`/`column` vector interpretation is a transpose. If there are an *even* number of flips then all the transposes cancel out. Therefore the following combinations work + +| Host Vector | Kernel Vector | Host Mat Layout | Kernel Mat Layout +|-------------|---------------|-----------------|------------------ +| Row | Row | Row | Row +| Row | Row | Column | Column +| Column | Column | Row | Row +| Column | Column | Column | Column +| Row | Column | Row | Column +| Row | Column | Column | Row +| Column | Row | Row | Column +| Column | Row | Column | Row + +To be clear 'Kernel Mat Layout' is the shader matrix layout setting. As previously touched upon, if it is not possible to use the setting (say because it is not supported on a target), then doing a transpose at the host/kernel boundary can fix the issue. + +Matrix Layout +------------- + +The above discussion is largely around 4x4 32-bit element matrices. For graphics APIs such as Vulkan, GL, and D3D there are typically additional restrictions for matrix layout. One restriction is for 16 byte alignment between rows (for `row-major` layout) and columns (for `column-major` layout). + +More CPU-like targets such as CUDA and C++/CPU do not have this restriction, and all elements are consecutive. + +This being the case only the following matrix types/matrix layouts will work across all targets. (Listed in the HLSL convention of RxC). + +* 1x4 `row-major` matrix layout +* 2x4 `row-major` matrix layout +* 3x4 `row-major` matrix layout +* 4x4 `row-major` matrix layout + +These are all 'row-major' because as previously discussed currently only `row-major` matrix layout works across all targets currently. + +NOTE! This only applies to matrices that are transferred between host and kernel - any matrix size will work appropriately for variables in shader/kernel code for example. + +The hosts maths library also plays a part here. The library may hold all elements consecutively in memory. If that's the case it will match the CPU/CUDA kernels, but will only work on 'graphics'-like targets that match that layout for the size. + +For SIMD based host maths libraries it can be even more convoluted. If a SIMD library is being used that prefers `row` vector interpretation and therefore will have `row-major` layout it may for many sizes *not* match the CPU-like consecutive layout. For example a 4x3 - it will likely be packed with 16 byte row alignment. Additionally even if a matrix is packed in the same way it may not be the same size. For example a 3x2 matrix *may* hold the rows consecutively *but* be 16 bytes in size, as opposed to the 12 bytes that a CPU-like kernel will expect. + +If a SIMD based host maths library with graphics-like APIs are being used, there is a good chance (but certainly *not* guaranteed) that layout across non 4x4 sizes will match because SIMD typically implies 16 byte alignment. + +If your application uses matrix sizes that are not 4x4 across the host/kernel boundary and it wants to work across all targets, it is *likely* that *some* matrices will have to be converted at the boundary. This being the case, having to handle transposing matrices at the boundary is a less significant issue. + +In conclusion, if your application has to perform matrix conversion work at the host/kernel boundary, the previous observation about "best performance" implying `row-major` layout and `row` vector interpretation becomes somewhat moot. + +Overriding default matrix layout +-------------------------------- + +Slang allows users to override default matrix layout with a compiler flag. This compiler flag can be specified during the creation of a `Session`: + +``` +slang::IGlobalSession* globalSession; +... +slang::SessionDesc slangSessionDesc = {}; +slangSessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; +... +slang::ISession* session; +globalSession->createSession(slangSessionDesc, &session); +``` + +This makes Slang treat all matrices as in `column-major` layout, and for example emitting `column_major` qualifier in resulting HLSL code. + +Alternatively the default layout can be set by + +* Including a `CompilerOptionName::MatrixLayoutColumn` or `CompilerOptionName::MatrixLayoutRow` entry in `SessionDesc::compilerOptionEntries`. +* Setting `-matrix-layout-row-major` or `-matrix-layout-column-major` command line options to `slangc`. + + diff --git a/lib/All/slang/share/doc/slang/user-guide/a1-03-obfuscation.md b/lib/All/slang/share/doc/slang/user-guide/a1-03-obfuscation.md new file mode 100644 index 0000000..bafafee --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a1-03-obfuscation.md @@ -0,0 +1,278 @@ +--- +layout: user-guide +--- + +Obfuscation +=========== + +The Slang obfuscation feature allows developers to distribute shader code in a way where the implementation details are kept secret. For example, let's say a developer has produced a novel way to render and wants to protect that intellectual property. If it is possible to compile all possible uses of the shader code into SPIR-V/DXIL, the developer can ship their product with those binaries without debug information. This is similar to the protection achieved by shipping an executable - a determined person may with a good deal of effort work out how some algorithm in the executable works, but doing so requires a considerable amount of work, and certainly more work than reading the original source code. + +If a developer is not able to ship all shader binaries then there is a problem. The developer doesn't want to ship the source code as in doing so it is relatively straightforward to see how it works or even copy the implementation. A developer could provide some level of protection by encrypting the source, but when compilation occurs it will still be necessary to decrypt and so make it available to read. A developer could obfuscate their source before shipping it. In this scenario: + +* Requires tooling to do the obfuscation of the source +* Any source on the client that isn't obfuscated needs to be able to call to the obfuscated code + * Depending on how the obfuscation takes place this could be hard - remapping symbols or obfuscating on the fly on the client + * If "public" symbols keep their original names they leak information about the implementation +* Obfuscated source provides some protection but not typically as much as a binary format (like an object file without debug information) +* How can you debug, or determine where a crash occurred without the original source? +* If a failure occurs - how is it possible to report meaningful errors? + +Some of these issues are similar to the problems of distributing JavaScript libraries that run on client machines, but which the original authors do not want to directly make available the implementation. Some of the obfuscation solutions used in the JavaScript world are partially applicable to Slang's obfuscation solution, including [source maps](https://github.com/source-map/source-map-spec). + +## Obfuscation in Slang + +Slang provides an obfuscation feature that addresses these issues. The major parts being + +* The ability to compile a module with obfuscation enabled + * The module is a binary format, that doesn't contain the original names or locations +* The ability to compile regular slang code that can *link* against an obfuscated module +* Code emitted to downstream compilers contain none of the symbols or locations from the original source +* Source map(s) to provide mappings between originating source and obfuscated source produced on the client + +Enabling obfuscation can be achieved via the `-obfuscate` option. When using the Slang API the `-obfuscate` option can be passed via `spProcessCommandLineArguments` function or `processCommandLineArguments` method. + +When enabled a few things will happen + +* Source locations are scrambled to (blank) lines in an "empty" obfuscation source file. +* A source map is produced mapping from the (blank) lines, to the originating source locations +* Name hints are stripped. +* If a `slang-module` is being produced, AST information will be stripped. +* The names of symbols are scrambled into hashes + +The source Slang emits which is passed down to downstream compilers is obfuscated, and only contains the sections of code necessary for the kernel to compile and function. + +Currently all source that is going to be compiled and linked must all have the `-obfuscate` option enabled to be able to link correctly. + +When obfuscation is enabled source locations are scrambled, but Slang will also create a [source map](https://github.com/source-map/source-map-spec), which provides the mapping from the obfuscated locations to the original source. This so called "obfuscated source map" is stored with the module. If compilation produces an error, Slang will automatically use the obfuscated source map to display the error location in the originating source. + +If the obfuscated source map isn't available, it will still display a source location if available, but the location will be to the "empty" obfuscated source file. This will appear in diagnostics as "(hex-digits)-obfuscated(line)". With this information and the source map it is possible to output the original source location. Importantly without the obfuscated source map information leakage about the original source is very limited. + +It should be noted that the obfuscated source map is of key importance in hiding the information. In the example scenario of protecting intellectual property, a developer should compile the code they wish to protect with `-obfuscate` and distribute *just* the `.slang-module` file to link on the client machine. The source map file should not be distributed onto client machines. + +A developer could use the source map + +* To determine where a problem is occurring by getting the obfuscated error, or crash information. +* Provide a web service that could provide more meaningful information keyed on the obfuscated location. + * Such a service could limit what information is returned, but still be meaningful +* A web service could additionally log errors for later analysis with the source map to determine the actual origin. + +## Using An Obfuscated Module + +To use a `slang-module` with obfuscation requires + +* Specifying one or more obfuscated modules via `-r` option + * Currently there is only support for referencing modules stored in files +* Specifying the `-obfuscate` option + +In a non obfuscated module, parts of the AST are serialized. This AST information could be through as broadly analogous to a header in C++. It is enough such that functionality in the module can be semantically checked, and linked with, however it does not, for example, contain the implementations of functions. This means doing a `-r` is roughly equivalent to doing an `import` of the source, without having the source. Any of the types, functions and so forth are available. + +With the `-obfuscate` option we strip the AST, in an abundance of caution to try and limit leaking information about the module. + +This means that `-r` is *NOT* enough to be able access the functionality of the module. It is necessary to declare the functions and types you wish to use. If a type is used only opaquely - i.e. not accessing its members directly, it is only necessary to declare that the type exists. If fields are accessed directly it is undefined behavior for a definition in one module to be incompatible with the definition in the obfuscated module. + +For example, in "module.slang" + +```slang +struct Thing +{ + int a; + int b; +}; + +int foo(Thing thing) +{ + return (thing.a + thing.b) - thing.b; +} +``` + +In the source that uses this module + +```slang +// This is fragile - needs match the definition in "module.slang" +struct Thing +{ + int a; + int b; +}; + +int foo(Thing thing); + +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + Thing thing; + + int index = (int)dispatchThreadID.x; + + thing.a = index; + thing.b = -index; + + outputBuffer[index] = foo(thing); +} +``` + +If the type `Thing` is only used opaquely then it would only be necessary to declare that it exists. For example in "module-opaque.slang" + +```slang +struct Thing +{ + int a; + int b; +}; + +Thing makeThing(int a, int b) +{ + return {a, b}; +} + +int foo(Thing thing) +{ + return (thing.a + thing.b) - thing.b; +} +``` + +In the source that uses this module + +```slang +// We can just declare Thing exists, as its usage is opaque. +struct Thing; +int foo(Thing thing); +Thing makeThing(int a, int b); + +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int index = (int)dispatchThreadID.x; + Thing thing = makeThing(index, -index); + outputBuffer[index] = foo(thing); +} +``` + +That this works might seem surprising to users of languages such as C/C++, because in these languages it is necessary to know the layout of `Thing` to be able to create the `thing` variable. This isn't necessary here though, and this can be very useful for some scenarios. + +A future iteration of the feature may include parts of the AST such that an obfuscated slang-module can be used like a regular module. It would be important that what is exposed is clear and under programmer control. By default most of the definitions within a module would typically not be exposed. +## Accessing Source Maps + +During a compilation Slang can produce many different "artifacts". When using the obfuscated source map option to produce a `slang-module` Slang will associate an obfuscated source map providing the mapping to the original source. + +With typical Slang API usage, a compilation takes place and the output is a "blob" that is the output kernel. It is also possible to compile to a container, such as a zip file or a directory. The zip file can contain the kernel as well as source map(s). + +For example + +``` +slangc module-source.slang -o module.zip -g -obfuscate +``` + +This will compile "module-source.slang" into SlangIR module (aka `slang-module`) and places the `.slang-module` inside of the zip. As obfuscation is enabled the .zip will also contain the obfuscated source map for the module. + +The `.zip` file can now be used and referenced as a module + +``` +slangc source.slang -target dxil -stage compute -entry computeMain -obfuscate -r module.zip +``` + +Notice here that the `-r` module reference is to the `.zip` file rather than the more usual `.slang-module` that is contained in the zip file. By referencing the module in this way Slang will automatically associate the contained obfuscated source map with the module. It will use that mapping for outputting diagnostics. + +It is also worth noticing that in this second compilation, using `module.zip`, we need the `-obfuscate` flag set. If this isn't set linking will not work correctly. + +NOTE! As previously discussed, though you should *not* ship the .zip file with the obfuscated source map such that it's available on client machines, as doing so does leak some information about the original source. Not the original source itself, but the names of files and the locations in files. You could ship a .zip to client machines, but make sure the `.map` obfuscated source maps are stripped. Alternatively, and perhaps less riskily, you could ship `.slang-module` files taken from the `.zip` file and then it is clear there is no source map information available. + +## Accessing Source Maps without Files + +When using the Slang API typically things work through memory, such as accessing a compilation result via a blob. It is possible to access source maps via memory also, but doing so currently requires accessing the result of a compilation as if its a file system. The current API to do this is + +``` +ISlangMutableFileSystem* getCompileRequestResultAsFileSystem(); +``` + +This method is currently only available on the `ICompileRequest` and not on the component (aka `IComponentType`) API. + +The file system returned is held in memory, and the blob data held in the file system typically shared, so accessing items this way is typically very low overhead. + +The conventions used for the file system representation could best be described as a work in progress, and may change in the future. Internally Slang stores compilation results as a hierarchy of "artifacts". An artifact consists of the main result, plus associated artifacts. An artifact can also be a container which can additionally hold children artifacts. In the current directory structure each artifact is a directory, with the root directory of the `ISlangMutableFileSystem` being the root artifact. + +Given a directory representing an artifact it can contain 2 special directories `children` and `associated`. The `children` directory contains the artifacts that are children of the current directories artifact. Similarly `associated` contains directories for artifacts that are associated with the current artifact. + +To give an example, if we compiled a module with obfuscation we might end up with a directory structure like.... + +``` +obfuscated-loc-module.slang-module +associated/ +associated/bc65f637-obfuscated/ +associated/bc65f637-obfuscated/bc65f637-obfuscated.map +``` + +The root contains the root artifact `obfuscated-loc-module.slang-module` and the associated directory holds anything associated with that module, in this case there is just one thing associated which is the obfuscated source map. Note all obfuscated source maps have a name ending in `-obfuscated`. + +The directory `associated/bc65f637-obfuscated/` is the directory that represents the `bc65f637-obfuscated` artifact, and that just consists of the contained map file. + +At the moment the types of files need to be determined by their extensions. A future version will hold a manifest that describes in more detail the content. + +## Emit Source Maps + +So far we have been mainly discussing "obfuscation" source maps. These maps provide a mapping from output locations to hidden original locations. + +It is also possible to generate a source map as part of emitting source to be passed to downstream compilers such as DXC, FXC, GLSLANG, NVRTCC or C++ compilers. This can be achieved via `-line-directive-mode source-map` option. The line directive mode controls how information about the original source is handled when emitting the source. The default mechanism, will add `#line` declarations into the original source. + +Via the API there are a few options to enable emit source maps + +``` +const char* args[2] = {"-line-directive-mode", "source-map" }; +request->processCommandLineArguments(args, 2); + +// Or +spProcessCommandLineArguments(request, args, 2); + +// Or just setting directly +request->setLineDirectiveMode(SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP); + +// Or +spSetLineDirectiveMode(request, SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP); +``` + +The `#line` mechanism is fairly straight forward in that all of the information is including the mapping information is in a single file. A downstream compiler will then embed that information into its debug information. If obfuscation is being used, this will work and the `#line` will actually reference the "made up" "xxx-obfuscated" files. + +With the `-line-directive-mode source-map` option no line directives are emitted, but a source map is produced that can map from a location in the emitted source back to its origin. If one of the origins is an obfuscated module this will reference "xxx-obfuscated" files. So in this scenario if you want to do a lookup to a location in the original source you *potentially* have to do two source map lookups. + +The first lookup will take you from the emitted source location, as will likely be specified by a debugger, to their origin. Some of the origins might be source that was compiled directly (i.e. not part of an obfuscated module); these files will be named directly. If this leads to a location inside an obfuscated source map, another lookup is needed to get back to the original source location. + +Why might you want to use an emit source map rather than use the `#line` mechanism? + +* Less source will need to be consumed by the downstream compiler - it can just be emitted as is +* The debugging source locations will be directly the locations within the emitted source +* Source map mapping is accurate from any point in the generated source to any point in the original source + * The `#line` mechanism is only accurate to a line +* It allows a separation of this information, such that it can be consumed and disposed of as the application requires +* Source maps are a standard, and so can be used in tooling +* Source maps allow for name mapping, mapping a symbol name to the symbol name in the original source + * This is currently not enabled in Slang, but may be a future addition + +Why you might not want to use an emit source map + +* The `#line` mechanism doesn't require any special handling, and the mapping back is embedded directly into the emitted source/output binary +* There is more housekeeping in getting keeping and using source maps +* Currently Slang doesn't directly expose a source map processing API directly + * We do support source maps in module files, or produced as part of a compilation + * A developer could use the slang `compiler-core` implementation + * In the future the project could provide some API support + +## Issues/Future Work + +* Support AST emitting in obfuscated modules +* Potentially add API support for source maps +* Add manifest support for artifacts +* Potentially provide a way to interact with artifacts more directly +* Potentially support for name mapping +* May want to improve the file hierarchy representation +* Provide other ways to ingest modules, such as through memory (currently -r just supports files) +* Provide more support for other kinds of artifacts + * Diagnostics + * Meta data (such as bindings used) + * Reflection +* We use -g to indicate debug information + * On DXC the debug information is embedded in the DXIL, we allow for pdb to separate, but we currently *don't* strip the PDB from the DXIL + * If we do strip the PDB, we may need to resign the DXIL diff --git a/lib/All/slang/share/doc/slang/user-guide/a1-04-interop.md b/lib/All/slang/share/doc/slang/user-guide/a1-04-interop.md new file mode 100644 index 0000000..5561d58 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a1-04-interop.md @@ -0,0 +1,242 @@ +--- +layout: user-guide +--- + +Interoperation with Target-Specific Code +=========== + +Slang provides low-level interoperation mechanisms to allow developers to use target-specific features or invoke code written in the target language from Slang code. These mechanisms are: +- `__intrinsic_asm` construct to map a function invocation to specific textual target code. +- `__require_prelude` construct to inject arbitrary text to the generated textual target code. +- `__target_switch` construct to use different implementations for different targets. +- `spirv_asm` construct to define inline SPIRV assembly blocks. + +> #### Note +> The language mechanisms described in this chapter are considered internal compiler features. +> The compiler does not provide comprehensive checks around their uses. These mechanisms are also subject +> to breaking changes in future releases. + +## Defining Intrinsic Functions for Textual Targets + +When using Slang to generate code for a textual target, e.g. HLSL, GLSL, CUDA or C++, you can use `__intrinsic_asm` to define what code to generate for an invocation to an intrinsic function. For example, the following Slang code defines an intrinsic function `myPrint`, that when called, will produce a call to `printf` in the target code: +```cpp +void myPrint(float v) +{ + __intrinsic_asm R"(printf("v is %f", $0))"; +} + +void test() +{ + myPrint(1.0f); +} +``` +Compiling the above code to CUDA or C++ will yield the following output: + +```cpp +// ... +void test_0() +{ + printf("v is %f", 1.0f); +} +``` + +The `__intrinsic_asm` statement in `myPrint` serves as the definition for the function. When a function body contains `__intrinsic_asm`, the function is treated by the compiler as an intrinsic and it must not contain other ordinary statements. Calls to an intrinsic function will be translated using the definition string of the intrinsic. In this example, the intrinsic is defined by the string literal `R"(printf("v is %f", $0))"`, which is used to translate the call from `test()`. The `"$0"` in the literal is replaced with the first argument. Besides `"$"`, you may also use the following macros in an intrinsic definition: + +| Macro | Expands to | +|-----------|-------------| +| `$` | Argument ``, starting from 0 | +| `$T` | Type of argument `` | +| `$TR` | The return type. | +| `$N` | The element count of argument ``, if the argument is a vector. | +| `$S` | The scalar type of argument ``, if the argument is a matrix or vector. | +| `$*` | Emit all arguments starting from `` as comma separated list | + +## Defining Intrinsic Types + +You can use `__target_intrinsic` modifier on a `struct` type to cause the type being emitted as a specific string for a given target. For example: +``` +__target_intrinsic(cpp, "std::string") +struct CppString +{ + uint size() + { + __intrinsic_asm "static_cast(($0).size())"; + } +} +``` +When compiling the above code to C++, the `CppString` struct will not be emitted as a C++ struct. Instead, all uses of `CppString` will be emitted as `std::string`. + +## Injecting Preludes + +If you have code written in the target language that you want to include in the generated code, you can use `__requirePrelude`. +For example: +```cpp +int getMyEnvVariable() +{ + __requirePrelude(R"(#include )"); + __requirePrelude(R"(#include )"); + __requirePrelude(R"( + int getEnvVarImpl() + { + char* var = getenv("MY_ENVIRONMENT_VAR"); + return std::stoi(var); + } + )"); + __intrinsic_asm "getEnvVarImpl()"; +} +void test() +{ + if (getMyEnvVariable() == 0) + return; +} +``` +In this code, `getMyEnvVariable()` is defined as an intrinsic Slang function that will translate to a call to `getEnvVarImpl()` in the target code. The first two `__requirePrelude` calls causes include directives being emitted in the resulting code, and the third `__requirePrelude` call causes a definition of `getEnvVarImpl()`, written in C++, being emitted before other Slang functions are emitted. The above code will translate to the following output: +```cpp +// ... +#include +#include +int getEnvVarImpl() +{ + char* var = getenv("MY_ENVIRONMENT_VAR"); + return std::stoi(var); +} +void test_0() +{ + if (getEnvVarImpl() == 0) + return; +} +``` + +The strings in `__requirePrelude` are deduplicated: the same prelude string will only be emitted once no matter how many times an intrinsic function is invoked. Therefore, it is good practice to put `#include` lines as separate `__requirePrelude` statements to prevent duplicate `#include`s being generated in the output code. + +## Managing Cross-Platform Code +If you are defining an intrinsic function that maps to multiple targets in different ways, you can use `__target_switch` construct to manage the target-specific definitions. For example, here is a snippet from the Slang core module that defines `getRealtimeClock`: +```hlsl +[__requiresNVAPI] +__glsl_extension(GL_EXT_shader_realtime_clock) +uint2 getRealtimeClock() +{ + __target_switch + { + case hlsl: + __intrinsic_asm "uint2(NvGetSpecial(NV_SPECIALOP_GLOBAL_TIMER_LO), NvGetSpecial( NV_SPECIALOP_GLOBAL_TIMER_HI))"; + case glsl: + __intrinsic_asm "clockRealtime2x32EXT()"; + case spirv: + return spirv_asm + { + OpCapability ShaderClockKHR; + OpExtension "SPV_KHR_shader_clock"; + result : $$uint2 = OpReadClockKHR Device + }; + default: + return uint2(0, 0); + } +} +``` +This definition causes `getRealtimeClock()` to translate to a call to NVAPI when targeting HLSL, to `clockRealtime2x32EXT()` when targeting +GLSL, and to the `OpReadClockKHR` instruction when compiling directly to SPIRV through the inline SPIRV assembly block. + +A `case` label may be a target base capability atom or a capability atom inheriting the target base. The latter allows targeting for a specific target capability or capability level. Note that aliases or compound capabilities are not allowed as `case` labels. + +The `default` case is used for targets not specified in the `__target_switch` statement. However, when any target-specific `case` label is specified, the target is no longer included in the `default` case. For example: + +```hlsl +[ForceInline] +bool __targetHasImplicitDerivativesInComputeStage() +{ + __target_switch + { + case _GL_NV_compute_shader_derivatives: + case SPV_KHR_compute_shader_derivatives: + case _sm_6_6: + return true; + + case hlsl: + case glsl: + case spirv: + default: + return false; + } +} +``` +In this example, case `hlsl` is required, since capability `_sm_6_6` inherits the base capability `hlsl`. Otherwise, this function would not be well-formed for HLSL capability level `_sm_6_5` and below. Similarly, `_GL_NV_compute_shader_derivatives` and `SPV_KHR_compute_shader_derivatives` inherit from `glsl` and `spirv`, respectively, and hence, the `glsl` and `spirv` cases are also required as the target-specific catch-alls. The rationale for this behavior is that when a feature requires specific handling by one or more targets, the default case will no longer provide a possibly unintended fallback in case of unmet requirements. + +Currently, the following targets are supported in a `case` statement: `cpp`, `cuda`, `glsl`, `hlsl`, `metal`, `spirv`, and `wgsl`. + +## Inline SPIRV Assembly + +When targeting SPIRV, Slang allows you to directly write a SPIRV assembly block and use it as part of an expression. For example: +```cpp +int test() +{ + int localVar = 5; + return 1 + spirv_asm { + %temp: $$int = OpIMul $localVar $(2); + result: $$int = OpIAdd %temp %temp + }; + // returns 21 +} +``` +A SPIRV assembly block contains one or more SPIRV instructions, separated by semicolons. Each SPIRV instruction has the form: +``` +%identifier : = ... ; +``` +where `` defines a value named `identifier` of ``, or simply: +``` + ... ; +``` +When `` does not define a return value. + +When used as part of an expression, the Slang type of the `spirv_asm` construct is defined by the last instruction, which must be in the form of: +``` +result: = ... +``` + +You can use the `$` prefix to begin an anti-quote of a Slang expression inside a `spirv_asm` block. This is commonly used to refer to a Slang variable, such as `localVar` in the example, as an operand. Additionally, the `$$` prefix is used to reference a Slang type, such as the `$$uint` references in the example. + +You can also use the `&` prefix to refer to an l-value as a pointer-typed value in SPIRV, for example: +```cpp +float modf(float x, out float ip) +{ + return spirv_asm + { + result:$$float = OpExtInst glsl450 Modf $x &ip + }; +} +``` + +Opcodes such as `OpCapability`, `OpExtension` and type definitions are allowed inside a `spirv_asm` block. These instructions will be deduplicated and inserted into the correct sections defined by the SPIRV specification, for example: +```cpp +uint4 WaveMatch(T value) +{ + return spirv_asm + { + OpCapability GroupNonUniformPartitionedNV; + OpExtension "SPV_NV_shader_subgroup_partitioned"; + OpGroupNonUniformPartitionNV $$uint4 result $value + }; +} +``` + +You may use SPIRV enum values directly as operands, for example: +```cpp +void memoryBarrierImage() +{ + spirv_asm + { + OpMemoryBarrier Device AcquireRelease|ImageMemory + }; +} +``` + +To access SPIRV builtin variables, you can use the `builtin(VarName:type)` syntax as an operand: +```cpp +uint InstanceIndex() +{ + return spirv_asm { + result:$$uint = OpLoad builtin(InstanceId:uint); + }; +} +``` + diff --git a/lib/All/slang/share/doc/slang/user-guide/a1-05-uniformity.md b/lib/All/slang/share/doc/slang/user-guide/a1-05-uniformity.md new file mode 100644 index 0000000..f98e045 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a1-05-uniformity.md @@ -0,0 +1,104 @@ +--- +layout: user-guide +--- + +Uniformity Analysis +=========== + +On certain hardware, accessing resources with a non-uniform index may lead to significant performance degradation. Developers can often benefit from a compiler warning for unintentional non-uniform resource access. + +Starting from v2024.1.0, Slang provides uniformity analysis that can warn users if a non-dynamically-uniform value is being used unintentionally. This feature is not enabled by default but can be turned on with the `-validate-uniformity` command-line option when using `slangc`, or the `CompilerOptionName::ValidateUniformity` compiler option when using the API. + +In addition to specifying the compiler option, the source code must be augmented with the `dynamic_uniform` modifier to mark function parameters, struct fields or local variables as expecting a dynamic uniform value. + +For example, the following code will trigger a warning: +```csharp +// Indicate that the `v` parameter needs to be dynamic uniform. +float f(dynamic_uniform float v) +{ + return v + 1.0; +} + +[numthread(1,1,1)] +[shader("compute")] +void main(int tid : SV_DispatchThreadID) +{ + f(tid); // warning: tid is not dynamically uniform. +} +``` + +Currently, the analysis is being conservative for `struct` typed values, in that if any member of the `struct` is known to be non-uniform, the entire composite is +treated as non-uniform: +```csharp +struct MyType +{ + int a; + int b; +} + +void expectUniform(dynamic_uniform int a){} + +void main(int tid : SV_DispatchThreadID) +{ + MyType t; + t.a = tid; + t.b = 0; + + // Generates a warning here despite t.b is non-uniform, because + // t.a is non-uniform and that assignment makes `t` non-uniform. + expectUniform(t.b); +} +``` + +To allow the compiler to provide more accurate analysis, you can use mark struct fields as +`dynamic_uniform`: + +```csharp +struct MyType +{ + int a; + dynamic_uniform int b; +} + +void expectUniform(dynamic_uniform int a){} + +void main(int tid : SV_DispatchThreadID) +{ + MyType t; + t.a = tid; + t.b = 0; + + // OK, because MyType::b is marked as dynamic_uniform. + expectUniform(t.b); + + // Warning: trying to assign non-uniform value to dynamic_uniform location. + t.b = tid; +} +``` + +## Treat Values as Uniform + +In some cases, the compiler might not be able to deduce a value to be non-uniform. If you are certain that a value can +be treated as dynamic uniform, you can call `asDynamicUniform()` function to force the compiler to treat the value as +dynamic uniform. For example: +```csharp +void main(int tid: SV_DispatchThreadID) +{ + expectUniform(asDynamicUniform(tid)); // OK. +} +``` + +## Treat Function Return Values as Non-uniform + +The uniformity analysis will automatically propagate uniformity to function return values. However, if you have +an intrinsic function that does not have a body, or you simply wish the return value of a function to be always +treated as non-uniform, you can mark the function with the `[NonUniformReturn]` attribute: +```csharp +[NonUniformReturn] +int f() { return 0; } +void expectUniform(dynamic_uniform int x) {} +void main() +{ + expectUniform(f()); // Warning. +} +``` diff --git a/lib/All/slang/share/doc/slang/user-guide/a1-special-topics.md b/lib/All/slang/share/doc/slang/user-guide/a1-special-topics.md new file mode 100644 index 0000000..0e4edd2 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a1-special-topics.md @@ -0,0 +1,28 @@ +--- +layout: user-guide +--- + +Special Topics +============================ + +This chapter covers several additional topics on using Slang. These topics do not belong to any categories covered in previous chapters, but they address specific issues that developers may frequently encounter. + +In this chapter: +1. [Handling matrix layout differences on different platforms](a1-01-matrix-layout.md) +2. [Using Slang to write PyTorch kernels](../deprecated/a1-02-slangpy.md) +3. [Obfuscation](a1-03-obfuscation.md) +4. [Interoperation with target-specific code](a1-04-interop.md) +5. [Uniformity Analysis](a1-05-uniformity.md) + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/a2-01-spirv-target-specific.md b/lib/All/slang/share/doc/slang/user-guide/a2-01-spirv-target-specific.md new file mode 100644 index 0000000..2209f72 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a2-01-spirv-target-specific.md @@ -0,0 +1,479 @@ +--- +layout: user-guide +permalink: /user-guide/spirv-target-specific +--- + +# SPIR-V-Specific Functionalities + +This chapter provides information for SPIR-V specific functionalities and behaviors. + +## Experimental support for the older versions of SPIR-V + +Slang's SPIR-V backend is stable when emitting SPIR-V 1.3 and later, however, support for SPIR-V 1.0, 1.1 and 1.2 is still experimental. +When targeting the older SPIR-V profiles, Slang may produce SPIR-V that uses the instructions and keywords that were introduced in the later versions of SPIR-V. + +## Memory model + +By default, the Slang compiler produces the SPIRV code using GLSL450 memory model. The user can opt-in to Vulkan Memory Model by specifying `-capability vk_mem_model`. For using APIs, the following lines can be added to explicitly specify the capability. + +``` + slang::CompilerOptionEntry entry; + entry.name = slang::CompilerOptionName::Capability; + entry.value.kind = slang::CompilerOptionValueKind::String; + entry.value.stringValue0 = "vk_mem_model"; + + slang::SessionDesc sessionDesc = {}; + sessionDesc.compilerOptionEntries = &entry; + sessionDesc.compilerOptionEntryCount = 1; +``` + +If the shader uses `CoopVec` or `CoopMat` intrinsics, then the Slang compiler will automatically use `vk_mem_model` capability. + +## Combined texture sampler + +Slang supports Combined texture sampler such as `Sampler2D`. +Slang emits SPIR-V code with `OpTypeSampledImage` instruction. + +For SPIR-V targets, explicit bindings may be provided through a single `vk::binding` decoration. + +``` +[[vk::binding(1,2)]] +Sampler2D explicitBindingSampler; +``` + +For other targets (HLSL or others) where combined texture samplers are _not_ supported intrinsically, they are emulated by Slang using separate objects for Texture and Sampler. +For explicit binding on such targets, you can specify two different register numbers for each: one for the texture register and another for the sampler register. + +``` +Sampler2D explicitBindingSampler : register(t4): register(s3); +``` + +## System-Value semantics + +The system-value semantics are translated to the following SPIR-V code. + +| SV semantic name | SPIR-V Code | +| ------------------------------ | ------------------------------------------------ | +| `SV_Barycentrics` | `BuiltIn BaryCoordKHR` | +| `SV_ClipDistance` | `BuiltIn ClipDistance` | +| `SV_CullDistance` | `BuiltIn CullDistance` | +| `SV_Coverage` | `BuiltIn SampleMask` | +| `SV_CullPrimitive` | `BuiltIn CullPrimitiveEXT` | +| `SV_Depth` | `BuiltIn FragDepth` | +| `SV_DepthGreaterEqual` | `BuiltIn FragDepth` | +| `SV_DepthLessEqual` | `BuiltIn FragDepth` | +| `SV_DispatchThreadID` | `BuiltIn GlobalInvocationId` | +| `SV_DomainLocation` | `BuiltIn TessCoord` | +| `SV_DrawIndex`\* | `Builtin DrawIndex` | +| `SV_DeviceIndex` | `Builtin DeviceIndex` | +| `SV_FragInvocationCount` | `Builtin FragInvocationCountExt` | +| `SV_FragSize` | `Builtin FragSizeExt` | +| `SV_GSInstanceID` | `BuiltIn InvocationId` | +| `SV_GroupID` | `BuiltIn WorkgroupId` | +| `SV_GroupIndex` | `BuiltIn LocalInvocationIndex` | +| `SV_GroupThreadID` | `BuiltIn LocalInvocationId` | +| `SV_InnerCoverage` | `BuiltIn FullyCoveredEXT` | +| `SV_InsideTessFactor` | `BuiltIn TessLevelInner` | +| `SV_InstanceID`\*\* | `BuiltIn InstanceIndex` - `Builtin BaseInstance` | +| `SV_IntersectionAttributes` | _Not supported_ | +| `SV_IsFrontFace` | `BuiltIn FrontFacing` | +| `SV_OutputControlPointID` | `BuiltIn InvocationId` | +| `SV_PointSize`\* | `BuiltIn PointSize` | +| `SV_PointCoord`\* | `BuiltIn PointCoord` | +| `SV_Position` | `BuiltIn Position/FragCoord` | +| `SV_PrimitiveID` | `BuiltIn PrimitiveId` | +| `SV_RenderTargetArrayIndex` | `BuiltIn Layer` | +| `SV_SampleIndex` | `BuiltIn SampleId` | +| `SV_ShadingRate` | `BuiltIn PrimitiveShadingRateKHR` | +| `SV_StartVertexLocation` | `BuiltIn BaseVertex` | +| `SV_StartInstanceLocation` | `BuiltIn BaseInstance` | +| `SV_StencilRef` | `BuiltIn FragStencilRefEXT` | +| `SV_Target` | `Location` | +| `SV_TessFactor` | `BuiltIn TessLevelOuter` | +| `SV_VertexID`\*\* | `BuiltIn VertexIndex` - `Builtin BaseVertex` | +| `SV_ViewID` | `BuiltIn ViewIndex` | +| `SV_ViewportArrayIndex` | `BuiltIn ViewportIndex` | +| `SV_VulkanInstanceID` | `BuiltIn InstanceIndex` | +| `SV_VulkanSamplePosition` | `BuiltIn SamplePosition` | +| `SV_VulkanVertexID` | `BuiltIn VertexIndex` | + +_Note_ that `SV_DrawIndex`, `SV_FragInvocationCount`, `SV_FragSize`, `SV_PointSize`, `SV_PointCoord` and `SV_VulkanSamplePosition` are Slang-specific semantics that are not defined in HLSL. +Also _Note_ that `SV_InstanceID`/`SV_VertexID` counts all instances/vertices in a draw call, unlike how `InstanceIndex`/`VertexIndex` is relative to `BaseInstance`/`BaseVertex`. +See [Using SV_InstanceID/SV_VertexID with SPIR-V target](#using-sv_instanceid-and-sv_vertexid-with-spir-v-target) + +## Using SV_InstanceID and SV_VertexID with SPIR-V target + +When using `SV_InstanceID` and `SV_VertexID` with SPIR-V target, it is equivalent to the difference between the index and base builtins. +This matches the behavior of D3D where `SV_InstanceID` and `SV_VertexID` starts from zero for each draw call, while in SPIR-V, +`InstanceIndex` and `VertexIndex` includes the base instance. + +If you need direct access to `InstanceIndex` and `VertexIndex` values, use `SV_VulkanInstanceID` and `SV_VulkanVertexID` semantic names. These are supported for all targets except HLSL. +Alternatively you can use parameters with `SV_InstanceID`(or `SV_VertexID`) and `SV_StartInstanceLocation`(or `SV_StartVertexLocation`) semantics: + +```slang +void myVertexShader( + uint instanceID : SV_InstanceID, // InstanceIndex - BaseInstance + uint baseInstance : SV_StartInstanceLocation) // BaseInstance +{ + // If you need InstanceIndex, just add them: + uint instanceIndex = instanceID + baseInstance; + + // Use instanceID, baseInstance, or instanceIndex as needed +} +``` + +## Behavior of `discard` after SPIR-V 1.6 + +`discard` is translated to OpKill in SPIR-V 1.5 and earlier. But it is translated to OpDemoteToHelperInvocation in SPIR-V 1.6. +You can use OpDemoteToHelperInvocation by explicitly specifying the capability, "SPV_EXT_demote_to_helper_invocation". + +As an example, the following command-line arguments can control the behavior of `discard` when targeting SPIR-V. + +``` +slangc.exe test.slang -target spirv -profile spirv_1_5 # emits OpKill +slangc.exe test.slang -target spirv -profile spirv_1_6 # emits OpDemoteToHelperInvocation +slangc.exe test.slang -target spirv -capability SPV_EXT_demote_to_helper_invocation -profile spirv_1_5 # emits OpDemoteToHelperInvocation +``` + +## Supported HLSL features when targeting SPIR-V + +Slang supports the following HLSL feature sets when targeting SPIR-V. + +- ray tracing, +- inline ray tracing, +- mesh shader, +- tessellation shader, +- geometry shader, +- wave intrinsics, +- barriers, +- atomics, +- and more + +## Unsupported GLSL keywords when targeting SPIR-V + +Slang doesn't support the following Precision qualifiers in Vulkan. + +- lowp : RelaxedPrecision, on storage variable and operation +- mediump : RelaxedPrecision, on storage variable and operation +- highp : 32-bit, same as int or float + +Slang ignores the keywords above and all of them are treated as `highp`. + +## Supported atomic types for each target + +Shader Model 6.2 introduced [16-bit scalar types](https://github.com/microsoft/DirectXShaderCompiler/wiki/16-Bit-Scalar-Types) such as `float16` and `int16_t`, but they didn't come with any atomic operations. +Shader Model 6.6 introduced [atomic operations for 64-bit integer types and bitwise atomic operations for 32-bit float type](https://microsoft.github.io/DirectX-Specs/d3d/HLSL_SM_6_6_Int64_and_Float_Atomics.html), but 16-bit integer types and 16-bit float types are not a part of it. + +[GLSL 4.3](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.30.pdf) introduced atomic operations for 32-bit integer types. +GLSL 4.4 with [GL_EXT_shader_atomic_int64](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GL_EXT_shader_atomic_int64.txt) can use atomic operations for 64-bit integer types. +GLSL 4.6 with [GLSL_EXT_shader_atomic_float](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GLSL_EXT_shader_atomic_float.txt) can use atomic operations for 32-bit float type. +GLSL 4.6 with [GLSL_EXT_shader_atomic_float2](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GLSL_EXT_shader_atomic_float2.txt) can use atomic operations for 16-bit float type. + +SPIR-V 1.5 with [SPV_EXT_shader_atomic_float_add](https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_shader_atomic_float_add.asciidoc) and [SPV_EXT_shader_atomic_float_min_max](https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_shader_atomic_float_min_max.asciidoc) can use atomic operations for 32-bit float type and 64-bit float type. +SPIR-V 1.5 with [SPV_EXT_shader_atomic_float16_add](https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_shader_atomic_float16_add.asciidoc) can use atomic operations for 16-bit float type + +| | 32-bit integer | 64-bit integer | 32-bit float | 64-bit float | 16-bit float | +| ------ | -------------- | --------------- | --------------------- | ---------------- | ---------------- | +| HLSL | Yes (SM5.0) | Yes (SM6.6) | Only bit-wise (SM6.6) | No | No | +| GLSL | Yes (GL4.3) | Yes (GL4.4+ext) | Yes (GL4.6+ext) | Yes (GL4.6+ext) | Yes (GL4.6+ext) | +| SPIR-V | Yes | Yes | Yes (SPV1.5+ext) | Yes (SPV1.5+ext) | Yes (SPV1.5+ext) | + +## ConstantBuffer, StructuredBuffer and ByteAddressBuffer + +Each member in a `ConstantBuffer` will be emitted as `uniform` parameter in a uniform block. +StructuredBuffer and ByteAddressBuffer are translated to a shader storage buffer with `readonly` access. +RWStructuredBuffer and RWByteAddressBuffer are translated to a shader storage buffer with `read-write` access. +RasterizerOrderedStructuredBuffer and RasterizerOrderedByteAddressBuffer will use an extension, `SPV_EXT_fragment_shader_interlock`. + +If you need to apply a different buffer layout for individual `ConstantBuffer` or `StructuredBuffer`, you can specify the layout as a second generic argument. E.g., `ConstantBuffer`, `StructuredBuffer`, `StructuredBuffer`, `StructuredBuffer` or `StructuredBuffer`. + +Note that there are compiler options, "-fvk-use-scalar-layout" / "-force-glsl-scalar-layout", "-fvk-use-dx-layout" and "-fvk-use-c-layout". +These options do the same but they are applied globally. + +## ParameterBlock for SPIR-V target + +`ParameterBlock` is a Slang generic type for binding uniform parameters. +In contrast to `ConstantBuffer`, a `ParameterBlock` introduces a new descriptor set ID for resource/sampler handles defined in the element type `T`. + +`ParameterBlock` is designed specifically for D3D12/Vulkan/Metal/WebGPU, so that parameters defined in `T` can be placed into an independent descriptor table/descriptor set/argument buffer/binding group. + +For example, when targeting Vulkan, when a ParameterBlock doesn't contain nested parameter block fields, it will always map to a single descriptor set, with a dedicated set number and every resources is placed into the set with binding index starting from 0. This allows the user application to create and pre-populate the descriptor set and reuse it during command encoding, without explicitly specifying the binding index for each individual parameter. + +When both ordinary data fields and resource typed fields exist in a parameter block, all ordinary data fields will be grouped together into a uniform buffer and appear as a binding 0 of the resulting descriptor set. + +## Push Constants + +By default, a `uniform` parameter defined in the parameter list of an entrypoint function is translated to a push constant in SPIRV, if the type of the parameter is ordinary data type (no resources/textures). +All `uniform` parameters defined in global scope are grouped together and placed in a default constant buffer. You can make a global uniform parameter laid out as a push constant by using the `[vk::push_constant]` attribute +on the uniform parameter. All push constants follow the std430 layout by default. + +## Specialization Constants + +You can specify a global constant to translate into a SPIRV specialization constant with the `[SpecializationConstant]` attribute. +For example: + +```csharp +[SpecializationConstant] +const int myConst = 1; // Maps to a SPIRV specialization constant +``` + +By default, Slang will automatically assign `constant_id` number for specialization constants. If you wish to explicitly specify them, use `[vk::constant_id]` attribute: + +```csharp +[vk::constant_id(1)] +const int myConst = 1; +``` + +Alternatively, the GLSL `layout` syntax is also supported by Slang: + +```glsl +layout(constant_id = 1) const int MyConst = 1; +``` + +## SPIR-V specific Attributes + +DXC supports a few attributes and command-line arguments for targeting SPIR-V. Similar to DXC, Slang supports a few of the attributes as following: + +### [[vk::binding(binding: int, set: int = 0)]] + +Similar to `binding` layout qualifier in Vulkan. It specifies the uniform buffer binding point, and the descriptor set for Vulkan. + +### [[vk::location(X)]] + +Same as `location` layout qualifier in Vulkan. For vertex shader inputs, it specifies the number of the vertex attribute from which input values are taken. For inputs of all other shader types, the location specifies a vector number that can be used to match against outputs from a previous shader stage. + +### [[vk::index(Y)]] + +Same as `index` layout qualifier in Vulkan. It is valid only when used with [[location(X)]]. For fragment shader outputs, the location and index specify the color output number and index receiving the values of the output. For outputs of all other shader stages, the location specifies a vector number that can be used to match against inputs in a subsequent shader stage. + +### [[vk::input_attachment_index(i)]] + +Same as `input_attachment_index` layout qualifier in Vulkan. It selects which subpass input is being read from. It is valid only when used on subpassInput type uniform variables. + +### [[vk::push_constant]] + +Same as `push_constant` layout qualifier in Vulkan. It is applicable only to a uniform block and it will be copied to a special memory location where GPU may have a more direct access to. + +### [vk::image_format(format : String)] + +Same as `[[vk::image_format("XX")]]` layout qualifier in DXC. Vulkan/GLSL allows the format string to be specified without the keyword, `image_format`. Consider the following Slang code, as an example, + +```csharp +[vk::image_format("r32f")] RWTexture2D typicalTexture; +``` + +It will generate the following GLSL, + +> layout(r32f) uniform image2D typicalTexture_0; + +Or it will generate the following SPIR-V code, + +> %18 = OpTypeImage %float 2D 2 0 0 2 R32f + +### [vk::shader_record] + +Same as `shaderRecordEXT` layout qualifier in [GL_EXT_ray_tracing extension](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GLSL_EXT_ray_tracing.txt). +It can be used on a buffer block that represents a buffer within a shader record as defined in the Ray Tracing API. + +## Multiple entry points support + +To use multiple entry points, you will need to use a compiler option, `-fvk-use-entrypoint-name`. + +Because GLSL requires the entry point to be named, "main", a GLSL shader can have only one entry point. +The default behavior of Slang is to rename all entry points to "main" when targeting SPIR-V. + +When there are more than one entry point, the default behavior will prevent a shader from having more than one entry point. +To generate a valid SPIR-V with multiple entry points, use `-fvk-use-entrypoint-name` compiler option to disable the renaming behavior and preserve the entry point names. + +## Global memory pointers + +Slang supports global memory pointers when targeting SPIRV. See [an example and explanation](03-convenience-features.md#pointers-limited). + +`float4*` in user code will be translated to a pointer in PhysicalStorageBuffer storage class in SPIRV. +When a slang module uses a pointer type, the resulting SPIRV will be using the SpvAddressingModelPhysicalStorageBuffer64 addressing mode. Modules without use of pointers will use SpvAddressingModelLogical addressing mode. + +## Matrix type translation + +A m-row-by-n-column matrix in Slang, represented as float`m`x`n` or matrix, is translated to OpTypeMatrix (OpTypeVector(T, n), m) in SPIRV. Note that in SPIR-V terminology, this type is referred to a m-column-by-n-row matrix. + +The swap of row and column terminology may seem to be confusing at first, but this is the only translation without needing extra operations that may have negative performance consequences. For example, consider the following Slang code: + +``` +float3x4 v; +for (int i = 0; i < 3; ++i) +{ + for (int j = 0; j < 4; ++j) + { + v[i][j] = i * 4 + j; + } +} +``` + +The Slang shader above can iterate each element of a `float3x4` matrix. This is similar to how a multi-dimensional array is handled in C and HLSL. When a matrix type is `float3x4`, the first dimension indexing, `i`, corresponds to the first value specified in the matrix type `3`. And the second dimension indexing, `j`, corresponds to the second value specified in the matrix type `4`. + +A matrix in Slang can be also seen as an array of a vector type. And the following code is same as above. + +``` +float3x4 v; +for (int i = 0; i < 3; ++i) +{ + v[i] = float4(0, 1, 2, 3); + v[i] += i * 4; +} +``` + +For the given example above, when targeting SPIR-V, Slang emits a matrix that consists of three vectors each of which has four elements, + +``` +%float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 ; <= float4 type +%mat3v4float = OpTypeMatrix %v4float 3 ; <= three of float4 +``` + +An alternative way to emit SPIR-V code is to emit four vectors and each vector has three elements. Slang doesn't do this but this is a more direct translation because SPIR-V spec defines OpTypeMatrix to take "Column Count" not row. + +``` +; NOT SLANG EMITTED CODE +%v3float = OpTypeVector %float 3 ; <= float3 type +%mat4v3float = OpTypeMatrix %v3float 4 ; <= four of float3 +``` + +However, this results in a more complicated access pattern to the elements in a matrix, because `v[i]` will no longer correspond to a vector natively when emitted to SPIR-V. + +Another way to put, Slang treats column as row and row as column when targeting GLSL or SPIR-V. This is same to [how DXC handles a matrix when emitting SPIR-V](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#appendix-a-matrix-representation). + +Due to the swap of row and column in terminology, the matrix multiplication needs to be performed little differently. Slang translates a matrix multiplication, `mul(mat1, mat2)`, to `transpose(mul(transpose(mat2), transpose(mat1)))` when targeting SPIR-V. + +Note that the matrix translation explained above is orthogonal to the memory layout of a matrix. The memory layout is related to how CPU places matrix values in the memory and how GPU reads them. It is like how `std140` or `std430` works. DXC by default uses `column_major` memory layout and Slang uses row-major memory layout. For more information about the matrix memory layout, please see [a1-01-matrix-layout](a1-01-matrix-layout.md). + +## Legalization + +Legalization is a process where Slang applies slightly different approach to translate the input Slang shader to the target. +This process allows Slang shaders to be written in a syntax that SPIR-V may not be able to achieve natively. + +Slang allows to use opaque resource types as members of a struct. These members will be hoisted out of struct types and become global variables. + +Slang allows functions that return any resource types as return type or `out` parameter as long as things are statically resolvable. + +Slang allows functions that return arrays. These functions will be converted to return the array via an out parameter in SPIRV. + +Slang allows putting scalar/vector/matrix/array types directly as element type of a constant buffer or structured buffers. Such element types will be wrapped in a struct type when emitting to SPIRV. + +When RasterizerOrder resources are used, the order of the rasterization is guaranteed by the instructions from `SPV_EXT_fragment_shader_interlock` extension. + +A `StructuredBuffer` with a primitive type such as `StructuredBuffer v` is translated to a buffer with a struct that has the primitive type, which is more like `struct Temp { int v; }; StructuredBuffer v;`. It is because, SPIR-V requires buffer variables to be declared within a named buffer block. + +When `pervertex` keyword is used, the given type for the varying input will be translated into an array of the given type whose element size is 3. It is because each triangle consists of three vertices. + +## Tessellation + +In HLSL and Slang, Hull shader requires two functions: a Hull shader and patch function. +A typical example of a Hull shader will look like the following. + +``` +// Hull Shader (HS) +[domain("quad")] +[patchconstantfunc("constants")] +HS_OUT main(InputPatch patch, uint i : SV_OutputControlPointID) +{ + ... +} +HSC_OUT constants(InputPatch patch) +{ + ... +} +``` + +When targeting SPIR-V, the patch function is merged as a part of the Hull shader, because SPIR-V doesn't have a same concept as `patchconstantfunc`. +The function used for `patchconstantfunc` should be called only once for each patch. + +As an example, the Hull shader above will be emitted as following, + +``` +void main() { + ... + main(patch, gl_InvocationID); + barrier(); // OpControlBarrier + if (gl_InvocationID == 0) + { + constants(path); + } +} +``` + +This behavior is same to [how DXC translates Hull shader from HLSL to SPIR-V](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#patch-constant-function). + +## SPIR-V specific Compiler options + +The following compiler options are specific to SPIR-V. + +### -emit-spirv-directly + +Generate SPIR-V output directly (default) +It cannot be used with -emit-spirv-via-glsl + +### -emit-spirv-via-glsl + +Generate SPIR-V output by compiling to glsl source first, then use glslang compiler to produce SPIRV from the glsl. +It cannot be used with -emit-spirv-directly + +### -g + +Include debug information in the generated code, where possible. +When targeting SPIR-V, this option emits [SPIR-V NonSemantic Shader DebugInfo Instructions](https://github.com/KhronosGroup/SPIRV-Registry/blob/main/nonsemantic/NonSemantic.Shader.DebugInfo.100.asciidoc). + +### -O + +Set the optimization level. +Under `-O0` option, Slang will not perform extensive inlining for all functions calls, instead it will preserve the call graph as much as possible to help with understanding the SPIRV structure and diagnosing any downstream toolchain issues. + +### -fvk-{b|s|t|u}-shift + +For example '-fvk-b-shift ' shifts by N the inferred binding +numbers for all resources in 'b' registers of space . For a resource attached with :register(bX, ) +but not [vk::binding(...)], sets its Vulkan descriptor set to and binding number to X + N. If you need to +shift the inferred binding numbers for more than one space, provide more than one such option. If more than one +such option is provided for the same space, the last one takes effect. If you need to shift the inferred binding +numbers for all sets, use 'all' as . + +For more information, see the following pages: + +- [DXC description](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#implicit-binding-number-assignment) +- [GLSL wiki](https://github.com/KhronosGroup/glslang/wiki/HLSL-FAQ#auto-mapped-binding-numbers) + +### -fvk-bind-globals + +Places the $Globals cbuffer at descriptor set and binding . +It lets you specify the descriptor for the source at a certain register. + +For more information, see the following pages: + +- [DXC description](https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#hlsl-global-variables-and-vulkan-binding) + +### -fvk-use-scalar-layout, -force-glsl-scalar-layout + +Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, ByteAddressBuffer and general pointers follow the 'scalar' layout when targeting GLSL or SPIRV. + +### -fvk-use-gl-layout + +Use std430 layout instead of D3D buffer layout for raw buffer load/stores. + +### -fvk-use-dx-layout + +Pack members using FXCs member packing rules when targeting GLSL or SPIRV. + +### -fvk-use-c-layout + +Make data accessed through ConstantBuffer, ParameterBlock, StructuredBuffer, ByteAddressBuffer and general pointers follow the C/C++ structure layout rules when targeting SPIRV. + +### -fvk-use-entrypoint-name + +Uses the entrypoint name from the source instead of 'main' in the spirv output. + +### -fspv-reflect + +Include reflection decorations in the resulting SPIR-V for shader parameters. + +### -spirv-core-grammar + +A path to a specific spirv.core.grammar.json to use when generating SPIR-V output diff --git a/lib/All/slang/share/doc/slang/user-guide/a2-02-metal-target-specific.md b/lib/All/slang/share/doc/slang/user-guide/a2-02-metal-target-specific.md new file mode 100644 index 0000000..62af51a --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a2-02-metal-target-specific.md @@ -0,0 +1,305 @@ +--- +layout: user-guide +permalink: /user-guide/metal-target-specific +--- + +# Metal-Specific Functionalities + +This chapter provides information for Metal-specific functionalities and +behaviors in Slang. + +## Entry Point Parameter Handling + +Slang performs several transformations on entry point parameters when targeting Metal: + +- Struct parameters are flattened to eliminate nested structures +- Input parameters with varying inputs are packed into a single struct +- System value semantics are translated to Metal attributes +- Parameters without semantics are given automatic attribute indices + +## System-Value semantics + +The system-value semantics are translated to the following Metal attributes: + +| SV semantic name | Metal attribute | +| --------------------------- | ---------------------------------------------------- | +| `SV_Position` | `[[position]]` | +| `SV_Coverage` | `[[sample_mask]]` | +| `SV_Depth` | `[[depth(any)]]` | +| `SV_DepthGreaterEqual` | `[[depth(greater)]]` | +| `SV_DepthLessEqual` | `[[depth(less)]]` | +| `SV_DispatchThreadID` | `[[thread_position_in_grid]]` | +| `SV_FragInvocationCount` | `(Not supported)` | +| `SV_FragSize` | `(Not supported)` | +| `SV_GroupID` | `[[threadgroup_position_in_grid]]` | +| `SV_GroupThreadID` | `[[thread_position_in_threadgroup]]` | +| `SV_GroupIndex` | Calculated from `SV_GroupThreadID` and group extents | +| `SV_InstanceID` | `[[instance_id]]` | +| `SV_IsFrontFace` | `[[front_facing]]` | +| `SV_PointSize` | `[[point_size]]` | +| `SV_PointCoord` | `[[point_coord]]` | +| `SV_PrimitiveID` | `[[primitive_id]]` | +| `SV_RenderTargetArrayIndex` | `[[render_target_array_index]]` | +| `SV_SampleIndex` | `[[sample_id]]` | +| `SV_Target` | `[[color(N)]]` | +| `SV_VertexID` | `[[vertex_id]]` | +| `SV_ViewportArrayIndex` | `[[viewport_array_index]]` | +| `SV_StartVertexLocation` | `[[base_vertex]]` | +| `SV_StartInstanceLocation` | `[[base_instance]]` | +| `SV_VulkanInstanceID` | `[[instance_id]]` | +| `SV_VulkanSamplePosition` | `(Not supported)` | +| `SV_VulkanVertexID` | `[[vertex_id]]` | + +Custom semantics are mapped to user attributes: + +- `[[user(SEMANTIC_NAME)]]` For non-system value semantics +- `[[user(SEMANTIC_NAME_INDEX)]]` When semantic has an index + +## Interpolation Modifiers + +Slang maps interpolation modifiers to Metal's interpolation attributes: + +| Slang Interpolation | Metal Attribute | +| ------------------- | --------------------------- | +| `nointerpolation` | `[[flat]]` | +| `noperspective` | `[[center_no_perspective]]` | +| `linear` | `[[sample_no_perspective]]` | +| `sample` | `[[sample_perspective]]` | +| `centroid` | `[[center_perspective]]` | + +## Resource Types + +Resource types are translated with appropriate Metal qualifiers: + +| Slang Type | Metal Translation | +| --------------------- | ------------------ | +| `Texture2D` | `texture2d` | +| `RWTexture2D` | `texture2d` | +| `ByteAddressBuffer` | `uint32_t device*` | +| `StructuredBuffer` | `device* T` | +| `ConstantBuffer` | `constant* T` | + +| Slang Type | Metal Translation | +| --------------------------------- | ------------------------------------- | +| `Texture1D` | `texture1d` | +| `Texture1DArray` | `texture1d_array` | +| `RWTexture1D` | `texture1d` | +| `RWTexture1DArray` | `texture1d_array` | +| `Texture2D` | `texture2d` | +| `Texture2DArray` | `texture2d_array` | +| `RWTexture2D` | `texture2d` | +| `RWTexture2DArray` | `texture2d_array` | +| `Texture3D` | `texture3d` | +| `RWTexture3D` | `texture3d` | +| `TextureCube` | `texturecube` | +| `TextureCubeArray` | `texturecube_array` | +| `Buffer` | `device* T` | +| `RWBuffer` | `device* T` | +| `ByteAddressBuffer` | `device* uint32_t` | +| `RWByteAddressBuffer` | `device* uint32_t` | +| `StructuredBuffer` | `device* T` | +| `RWStructuredBuffer` | `device* T` | +| `AppendStructuredBuffer` | `device* T` | +| `ConsumeStructuredBuffer` | `device* T` | +| `ConstantBuffer` | `constant* T` | +| `SamplerState` | `sampler` | +| `SamplerComparisonState` | `sampler` | +| `RaytracingAccelerationStructure` | `(Not supported)` | +| `RasterizerOrderedTexture2D` | `texture2d [[raster_order_group(0)]]` | +| `RasterizerOrderedBuffer` | `device* T [[raster_order_group(0)]]` | + +Raster-ordered access resources receive the `[[raster_order_group(0)]]` +attribute, for example `texture2d tex +[[raster_order_group(0)]]`. + +## Array Types + +Array types in Metal are declared using the array template: + +| Slang Type | Metal Translation | +| ------------------- | -------------------------- | +| `ElementType[Size]` | `array` | + +## Matrix Layout + +Metal exclusively uses column-major matrix layout. Slang automatically handles +the translation of matrix operations to maintain correct semantics: + +- Matrix multiplication is transformed to account for layout differences +- Matrix types are declared as `matrix`, for example + `float3x4` is represented as `matrix` + +## Mesh Shader Support + +Mesh shaders can be targeted using the following types and syntax. The same as task/mesh shaders generally in Slang. + +```slang +[outputtopology("triangle")] +[numthreads(12, 1, 1)] +void meshMain( + in uint tig: SV_GroupIndex, + in payload MeshPayload meshPayload, + OutputVertices verts, + OutputIndices triangles, + OutputPrimitives primitives + ) +``` + +## Header Inclusions and Namespace + +When targeting Metal, Slang automatically includes the following headers, these +are available to any intrinsic code. + +```cpp +#include +#include +#include +using namespace metal; +``` + +## Parameter blocks and Argument Buffers + +`ParameterBlock` values are translated into _Argument Buffers_ potentially +containing nested resources. For example, this Slang code... + +```slang +struct MyParameters +{ + int x; + int y; + StructuredBuffer buffer1; + RWStructuredBuffer buffer2; +} + +ParameterBlock gObj; + +void main(){ ... gObj ... } +``` + +... results in this Metal output: + +```cpp +struct MyParameters +{ + int x; + int y; + float device* buffer1; + uint3 device* buffer2; +}; + +[[kernel]] void main(MyParameters constant* gObj [[buffer(1)]]) +``` + +## Struct Parameter Flattening + +When targeting Metal, top-level nested struct parameters are automatically +flattened. For example: + +```slang +struct NestedStruct +{ + float2 uv; +}; +struct InputStruct +{ + float4 position; + float3 normal; + NestedStruct nested; +}; +``` + +Will be flattened to: + +```cpp +struct InputStruct +{ + float4 position; + float3 normal; + float2 uv; +}; +``` + +## Return Value Handling + +Non-struct return values from entry points are automatically wrapped in a +struct with appropriate semantics. For example: + +```slang +float4 main() : SV_Target +{ + return float4(1,2,3,4); +} +``` + +becomes: + +```c++ +struct FragmentOutput +{ + float4 value : SV_Target; +}; +FragmentOutput main() +{ + return { float4(1,2,3,4) }; +} +``` + +## Value Type Conversion + +Metal enforces strict type requirements for certain operations. Slang +automatically performs the following conversions: + +- Vector size expansion (e.g., `float2` to `float4`), for example when the user + specified `float2` but the semantic type in Metal is `float4`. +- Image store value expansion to 4-components + +For example: + +```slang +RWTexture2D tex; +tex[coord] = float2(1,2); // Automatically expanded to float4(1,2,0,0) +``` + +## Conservative Rasterization + +Since Metal doesn't support conservative rasterization, SV_InnerCoverage is always false. + +## Address Space Assignment + +Metal requires explicit address space qualifiers. Slang automatically assigns appropriate address spaces: + +| Variable Type | Metal Address Space | +| --------------------- | ------------------- | +| Local Variables | `thread` | +| Global Variables | `device` | +| Uniform Buffers | `constant` | +| RW/Structured Buffers | `device` | +| Group Shared | `threadgroup` | +| Parameter Blocks | `constant` | + +## Explicit Parameter Binding + +The HLSL `:register()` semantic is respected when emitting Metal code. + +Since Metal does not differentiate between a constant buffer, a shader resource (read-only) buffer and an unordered access buffer, Slang will map `register(tN)`, `register(uN)` and `register(bN)` to `[[buffer(N)]]` when such `register` semantic is declared on a buffer-typed parameter. + +`spaceN` specifiers inside `register` semantics are ignored. + +The `[vk::location(N)]` attributes on stage input/output parameters are respected. + +## Specialization Constants + +Specialization constants declared with the `[SpecializationConstant]` or `[vk::constant_id]` attribute will be translated into a `function_constant` when generating Metal source. +For example: + +```csharp +[vk::constant_id(7)] +const int a = 2; +``` + +Translates to: + +```metal +constant int fc_a_0 [[function_constant(7)]]; +constant int a_0 = is_function_constant_defined(fc_a_0) ? fc_a_0 : 2; +``` diff --git a/lib/All/slang/share/doc/slang/user-guide/a2-03-wgsl-target-specific.md b/lib/All/slang/share/doc/slang/user-guide/a2-03-wgsl-target-specific.md new file mode 100644 index 0000000..18e5209 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a2-03-wgsl-target-specific.md @@ -0,0 +1,184 @@ +--- +layout: user-guide +permalink: /user-guide/wgsl-target-specific +--- + +WGSL-Specific Functionalities +============================= + +This chapter provides information for WGSL (WebGPU Shading Language)-specific functionalities and behaviors. + + +System-Value semantics +---------------------- + +The system-value semantics are translated to the following WGSL code. + +| SV semantic name | WGSL code | +|--|--| +| SV_Barycentrics | *Not supported* | +| SV_ClipDistance | *Not supported* | +| SV_CullDistance | *Not supported* | +| SV_Coverage | `@builtin(sample_mask)` | +| SV_CullPrimitive | *Not supported* | +| SV_Depth | `@builtin(frag_depth)` | +| SV_DepthGreaterEqual | *Not supported* | +| SV_DepthLessEqual | *Not supported* | +| SV_DispatchThreadID | `@builtin(global_invocation_id)` | +| SV_DomainLocation | *Not supported* | +| SV_FragInvocationCount | *Not supported* | +| SV_FragSize | *Not supported* | +| SV_GSInstanceID | *Not supported* | +| SV_GroupID | `@builtin(workgroup_id)` | +| SV_GroupIndex | `@builtin(local_invocation_index)` | +| SV_GroupThreadID | `@builtin(local_invocation_id)` | +| SV_InnerCoverage | *Not supported* | +| SV_InsideTessFactor | *Not supported* | +| SV_InstanceID | `@builtin(instance_index)` | +| SV_IntersectionAttributes | *Not supported* | +| SV_IsFrontFace | `@builtin(front_facing)` | +| SV_OutputControlPointID | *Not supported* | +| SV_PointSize | *Not supported* | +| SV_Position | `@builtin(position)` | +| SV_PrimitiveID | *Not supported* | +| SV_RenderTargetArrayIndex | *Not supported* | +| SV_SampleIndex | `@builtin(sample_index)` | +| SV_ShadingRate | *Not supported* | +| SV_StartVertexLocation | *Not supported* | +| SV_StartInstanceLocation | *Not supported* | +| SV_StencilRef | *Not supported* | +| SV_Target | *Not supported* | +| SV_TessFactor | *Not supported* | +| SV_VertexID | `@builtin(vertex_index)` | +| SV_ViewID | *Not supported* | +| SV_ViewportArrayIndex | *Not supported* | +| SV_VulkanInstanceID | `@builtin(instance_index)` | +| SV_VulkanSamplePosition | *Not supported* | +| SV_VulkanVertexID | `@builtin(vertex_index)` | + + +Supported HLSL features when targeting WGSL +------------------------------------------- + +The following table lists Slang's support for various HLSL feature sets, when targeting WGSL. + +| Feature set | Supported | +| -- | -- | +| ray tracing | No | +| inline ray tracing | No | +| mesh shader | No | +| tessellation shader | No | +| geometry shader | No | +| wave intrinsics | No | +| barriers | Yes | +| atomics | Yes | +| switch fall-through | Restructured (warning 41026) | + +### Switch Fall-Through + +WGSL does not support fall-through in switch statements. When Slang encounters switch fall-through in source code targeting WGSL, it restructures the code by duplicating the fall-through destination into each source case. This produces correct results but may affect wave convergence if the duplicated code contains subgroup operations. See the [target compatibility documentation](../target-compatibility.md#switch-fallthrough) for details. + + +Supported atomic types +---------------------- + +The following table shows what is supported when targeting WGSL: + +| | 32-bit integer | 64-bit integer | 32-bit float | 64-bit float | 16-bit float | +|--------------|-----------------|-----------------|-----------------------|------------------|------------------| +| Supported? | Yes | No | No | No | No | + + +ConstantBuffer, (RW/RasterizerOrdered)StructuredBuffer, (RW/RasterizerOrdered)ByteAddressBuffer +----------------------------------------------------------------------------------------------- + +ConstantBuffer translates to the `uniform` address space with `read` access mode in WGSL. +ByteAddressBuffer and RWByteAddressBuffer translate to `array` in the `storage` address space, with the `read` and `read_write` access modes in WGSL, respectively. +StructuredBuffer and RWStructuredBuffer with struct type T translate to `array` in the `storage` address space, with with the `read` and `read_write` access modes in WGSL, respectively. + +Interlocked operations +---------------------- + +The InterlockedAdd, InterlockedAnd, etc... functions are not supported when targeting WGSL. +Instead, operations on [`Atomic`](https://shader-slang.com/stdlib-reference/types/atomic-0/index) types should be used. + + +Entry Point Parameter Handling +------------------------------ + +Slang performs several transformations on entry point parameters when targeting WGSL: + +- Struct parameters and returned structs are flattened to eliminate nested structures. +- System value semantics are translated to WGSL built-ins. (See the `@builtin` attribute, and the table above.) +- Parameters without semantics are given automatic location indices. (See the `@location` attribute.) + + +Parameter blocks +---------------- + +Each `ParameterBlock` is assigned its own bind group in WGSL. + + +Write-only Textures +--------------- + +Many image formats supported by WebGPU can only be accessed in compute shader as a write-only image. +Use `WTexture2D` type (similar to `RWTexture2D`) to write to an image when possible. +The write-only texture types are also supported when targeting HLSL/GLSL/SPIR-V/Metal and CUDA. + + +Pointers +-------- + +`out` and `inout` parameters in Slang are translated to pointer-typed parameters in WGSL. +At callsites, a pointer value is formed and passed as argument using the `&` operator in WGSL. + +Since WGSL cannot form pointers to fields of structs (or fields of fields of structs, etc...), the described transformation cannot be done in a direct way when a function argument expression is an "access chain" like `myStruct.myField` or `myStruct.myStructField.someField`. +In those cases, the argument is copied to a local variable, the address of the local variable is passed to the function, and then the local +variable is written back to the struct field after the function call. + +Address Space Assignment +------------------------ + +WGSL requires explicit address space qualifiers. Slang automatically assigns appropriate address spaces: + +| Variable Type | WGSL Address Space | +| --------------------- | ------------------- | +| Local Variables | `function` | +| Global Variables | `private` | +| Uniform Buffers | `uniform` | +| RW/Structured Buffers | `storage` | +| Group Shared | `workgroup` | +| Parameter Blocks | `uniform` | + + +Matrix type translation +----------------------- + +A m-row-by-n-column matrix in Slang, represented as float`m`x`n` or matrix, is translated to `mat[n]x[m]` in WGSL, i.e. a matrix with `n` columns and `m` rows. +The rationale for this inversion of terminology is the same as [the rationale for SPIR-V](a2-01-spirv-target-specific.md#matrix-type-translation). +Since the WGSL matrix multiplication convention is the normal one, where inner products of rows of the matrix on the left are taken with columns of the matrix on the right, the order of matrix products is also reversed in WGSL. This is relying on the fact that the transpose of a matrix product equals the product of the transposed matrix operands in reverse order. + +## Explicit Parameter Binding + +The `[vk::binding(index,set)]` attribute is respected when emitting WGSL code, and will translate to `@binding(index) @group(set)` in WGSL. + +If the `[vk::binding()]` attribute is not specified but a `:register()` semantic is present, Slang will derive the binding from the `register` semantic the same way as the SPIR-V and GLSL backends. + +The `[vk::location(N)]` attributes on stage input/output parameters are respected. + +## Specialization Constants + +Specialization constants declared with the `[SpecializationConstant]` or `[vk::constant_id]` attribute will be translated into a global `override` declaration when generating WGSL source. +For example: + +```csharp +[vk::constant_id(7)] +const int a = 2; +``` + +Translates to: + +```wgsl +@id(7) override a : i32 = 2; +``` diff --git a/lib/All/slang/share/doc/slang/user-guide/a2-04-glsl-target-specific.md b/lib/All/slang/share/doc/slang/user-guide/a2-04-glsl-target-specific.md new file mode 100644 index 0000000..2a36c3d --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a2-04-glsl-target-specific.md @@ -0,0 +1,90 @@ +--- +layout: user-guide +permalink: /user-guide/glsl-target-specific +--- + +# GLSL-Specific Functionalities + +This page documents features and behaviors unique to the GLSL target in Slang. For any features or translation rules that are identical to the SPIR-V target, see the [SPIR-V Target Specific](./a2-01-spirv-target-specific.md) page. + +> **Note:** The GLSL target in Slang is currently less mature than the SPIR-V target and has several known limitations. While basic functionality works, some advanced features may not be fully supported or may behave differently than expected. Due to fundamental limitations of GLSL, the GLSL target is not expected to achieve feature parity with other backends. For cross-platform use cases, we recommend using the SPIR-V target for more complete and reliable shader compilation. This document is a work in progress and will be updated as the GLSL target matures and more limitations are documented. + +## Combined Texture Sampler + +Combined texture samplers (e.g., `Sampler2D`) are mapped directly to GLSL sampler types. See SPIR-V page for details on explicit bindings and emulation on other targets. + +## System-Value Semantics + +System-value semantics are mapped to the corresponding GLSL built-in variables (e.g., `gl_Position`, `gl_FragCoord`, etc.). For a full mapping table, refer to the [SPIR-V Target Specific](./a2-01-spirv-target-specific.md) page. + +## `discard` Statement + +The `discard` statement in Slang maps directly to GLSL's `discard` keyword, which exits the current fragment shader invocation. No special handling is required. + +## HLSL Features Supported in GLSL + +Slang supports many HLSL features when targeting GLSL, including: +- Geometry shaders +- Tessellation shaders +- Compute shaders +- Atomics (see below for type support) +- Wave intrinsics (where supported by GLSL extensions) + +## Atomic Types + +GLSL supports atomic operations on: +- 32-bit integer types (GLSL 4.3+) +- 64-bit integer types (GLSL 4.4+ with `GL_EXT_shader_atomic_int64`) +- 32-bit float types (GLSL 4.6+ with `GLSL_EXT_shader_atomic_float`) +- 16-bit float types (GLSL 4.6+ with `GLSL_EXT_shader_atomic_float2`) +See the SPIR-V page for a comparative table. + +## Buffer Types + +- `ConstantBuffer` members are emitted as `uniform` parameters in a uniform block. +- `StructuredBuffer` and `ByteAddressBuffer` are translated to shader storage buffers (`buffer` in GLSL 4.3+). +- Layouts can be controlled with `std140`, `std430`, or `scalar` layouts (see options below). + +## Matrix Layout + +GLSL uses column-major layout by default. Slang will handle row-major to column-major translation as needed. For more on matrix layout and memory layout, see the [SPIR-V Target Specific](./a2-01-spirv-target-specific.md) and [Matrix Layout](./a1-01-matrix-layout.md) pages. + +## Entry Points + +GLSL requires the entry point to be named `main`. Only one entry point per shader is supported. For multiple entry points or advanced scenarios, see the SPIR-V page. + +## Specialization Constants + +Slang supports specialization constants in GLSL using the `layout(constant_id = N)` syntax or the `[SpecializationConstant]` attribute. See the SPIR-V page for details. + +## Attributes and Layout Qualifiers + +Slang attributes such as `[[vk::location]]`, `[[vk::binding]]`, etc., are mapped to GLSL `layout` qualifiers where possible. + +## GLSL-Specific Compiler Options + +Relevant options for GLSL output: + +### -profile glsl_ +Select the GLSL version to target (e.g., `-profile glsl_450`). + +### -force-glsl-scalar-layout +Use scalar layout for buffer types. + +> **Note:** Scalar layout is generally only supported by Vulkan consumers of GLSL, and is not expected to be usable for OpenGL. + +### -fvk-use-dx-layout +Use D3D buffer layout rules. + +### -fvk-use-gl-layout +Use std430 layout for raw buffer load/stores. + +### -line-directive-mode glsl +Emit GLSL-style `#line` directives. + +### -default-downstream-compiler glsl +Set the downstream GLSL compiler (e.g., glslang). + +> **Note:** The GLSL target has a known limitation with constant buffer packing for 3-element vectors, where it cannot always reproduce the same exact buffer layout. For example, when a 3-element vector follows a scalar in a constant buffer, the alignment differs from a 4-element vector, causing incorrect packing. + +For all other behaviors, translation rules, and advanced features, refer to the [SPIR-V Target Specific](./a2-01-spirv-target-specific.md) page. diff --git a/lib/All/slang/share/doc/slang/user-guide/a2-target-specific-features.md b/lib/All/slang/share/doc/slang/user-guide/a2-target-specific-features.md new file mode 100644 index 0000000..e2456f7 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a2-target-specific-features.md @@ -0,0 +1,26 @@ +--- +layout: user-guide +--- + +# Target-Specific Features + +Slang can produce code for a variety of targets. When producing code for a target, Slang attempts to translate HLSL intrinsics to the closest functionality provided by the target. In addition, Slang also supports target-specific intrinsics and language extensions that allow users to make best use of the target. This chapter documents all the important target-specific behaviors. + +In this chapter: + +1. [SPIR-V target specific](./a2-01-spirv-target-specific.md) +2. [Metal target specific](./a2-02-metal-target-specific.md) +3. [WGSL target specific](./a2-03-wgsl-target-specific.md) +4. [GLSL target specific](./a2-04-glsl-target-specific.md) + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/a3-01-reference-capability-profiles.md b/lib/All/slang/share/doc/slang/user-guide/a3-01-reference-capability-profiles.md new file mode 100644 index 0000000..e54f212 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a3-01-reference-capability-profiles.md @@ -0,0 +1,49 @@ +--- +layout: user-guide +--- + +Capability Profiles +============================ + +### Accepted Values of `-profile`: + +> Note: To create your own profiles, try mixing capabilities with `-capability`. + +`sm_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + +`vs_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + vertex shader + +`ps_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + pixel shader + +`hs_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + hull shader + +`gs_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + geometry shader + +`ds_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + domain shader + +`cs_{4_0,4_1,5_0,5_1,6_0,6_1,6_2,6_3,6_4,6_5,6_6,6_7}` +* HLSL shader model + compute shader + +`ms_6_{5,6,7}` +* HLSL shader model + mesh shader + +`as_6_{5,6,7}` +* HLSL shader model + amplification shader + +`lib_6_{1,2,3,4,5,6,7}` +* HLSL shader model for libraries + +`glsl_{110,120,130,140,150,330,400,410,420,430,440,450,460}` +* GLSL versions + +`spirv_1_{1,2,3,4,5,6}` +* SPIR-V versions + +`metallib_2_{3,4}` +* Metal versions diff --git a/lib/All/slang/share/doc/slang/user-guide/a3-02-reference-capability-atoms.md b/lib/All/slang/share/doc/slang/user-guide/a3-02-reference-capability-atoms.md new file mode 100644 index 0000000..5010048 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a3-02-reference-capability-atoms.md @@ -0,0 +1,1599 @@ +--- +layout: user-guide +--- + +Capability Atoms +============================ + +### Sections: + +1. [Targets](#targets) +2. [Stages](#stages) +3. [Versions](#versions) +4. [Extensions](#extensions) +5. [Compound Capabilities](#compound-capabilities) +6. [Other](#other) + +Targets +---------------------- +*Capabilities to specify code generation targets (`glsl`, `spirv`...)* + +`c` +> Represents the C programming language code generation target. + +`cpp` +> Represents the C++ programming language code generation target. + +`cuda` +> Represents the CUDA code generation target. + +`glsl` +> Represents the GLSL code generation target. + +`hlsl` +> Represents the HLSL code generation target. + +`llvm` +> Represents the LLVM IR target. + +`metal` +> Represents the Metal programming language code generation target. + +`slangvm` +> Represents the Slang VM bytecode target. + +`spirv` +> Represents the SPIR-V code generation target. + +`textualTarget` +> Represents a non-assembly code generation target. + +`wgsl` +> Represents the WebGPU shading language code generation target. + +Stages +---------------------- +*Capabilities to specify code generation stages (`vertex`, `fragment`...)* + +`amplification` +> Amplification shader stage & mesh shader capabilities + +`anyhit` +> Any-Hit shader stage & ray-tracing capabilities + +`callable` +> Callable shader stage & ray-tracing capabilities + +`closesthit` +> Closest-Hit shader stage & ray-tracing capabilities + +`compute` +> Compute shader stage + +`dispatch` +> Dispatch shader stage + +`domain` +> Domain shader stage + +`fragment` +> Fragment shader stage + +`geometry` +> Geometry shader stage + +`hull` +> Hull shader stage + +`intersection` +> Intersection shader stage & ray-tracing capabilities + +`mesh` +> Mesh shader stage & mesh shader capabilities + +`miss` +> Ray-Miss shader stage & ray-tracing capabilities + +`pixel` +> Pixel shader stage + +`raygen` +> Ray-Generation shader stage & ray-tracing capabilities + +`raygeneration` +> Ray-Generation shader stage & ray-tracing capabilities + +`task` +> Task shader stage & mesh shader capabilities + +`tesscontrol` +> Tessellation Control shader stage + +`tesseval` +> Tessellation Evaluation shader stage + +`vertex` +> Vertex shader stage + +Versions +---------------------- +*Capabilities to specify versions of a code generation target (`sm_5_0`, `GLSL_400`...)* + +`GLSL_130` +> GLSL 130 and related capabilities of other targets. + +`GLSL_140` +> GLSL 140 and related capabilities of other targets. + +`GLSL_150` +> GLSL 150 and related capabilities of other targets. + +`GLSL_330` +> GLSL 330 and related capabilities of other targets. + +`GLSL_400` +> GLSL 400 and related capabilities of other targets. + +`GLSL_410` +> GLSL 410 and related capabilities of other targets. + +`GLSL_420` +> GLSL 420 and related capabilities of other targets. + +`GLSL_430` +> GLSL 430 and related capabilities of other targets. + +`GLSL_440` +> GLSL 440 and related capabilities of other targets. + +`GLSL_450` +> GLSL 450 and related capabilities of other targets. + +`GLSL_460` +> GLSL 460 and related capabilities of other targets. + +`cuda_sm_1_0` +> cuda 1.0 and related capabilities of other targets. + +`cuda_sm_2_0` +> cuda 2.0 and related capabilities of other targets. + +`cuda_sm_3_0` +> cuda 3.0 and related capabilities of other targets. + +`cuda_sm_3_5` +> cuda 3.5 and related capabilities of other targets. + +`cuda_sm_4_0` +> cuda 4.0 and related capabilities of other targets. + +`cuda_sm_5_0` +> cuda 5.0 and related capabilities of other targets. + +`cuda_sm_6_0` +> cuda 6.0 and related capabilities of other targets. + +`cuda_sm_7_0` +> cuda 7.0 and related capabilities of other targets. + +`cuda_sm_8_0` +> cuda 8.0 and related capabilities of other targets. + +`cuda_sm_9_0` +> cuda 9.0 and related capabilities of other targets. + +`dxil_lib` +> Represents capabilities required for DXIL Library compilation. + +`glsl_spirv_1_0` +> Represents SPIR-V 1.0 through glslang. + +`glsl_spirv_1_1` +> Represents SPIR-V 1.1 through glslang. + +`glsl_spirv_1_2` +> Represents SPIR-V 1.2 through glslang. + +`glsl_spirv_1_3` +> Represents SPIR-V 1.3 through glslang. + +`glsl_spirv_1_4` +> Represents SPIR-V 1.4 through glslang. + +`glsl_spirv_1_5` +> Represents SPIR-V 1.5 through glslang. + +`glsl_spirv_1_6` +> Represents SPIR-V 1.6 through glslang. + +`hlsl_2018` +> Represent HLSL compatibility support. + +`hlsl_nvapi` +> Represents HLSL NVAPI support. + +`metallib_2_3` +> Represents MetalLib 2.3. + +`metallib_2_4` +> Represents MetalLib 2.4. + +`metallib_3_0` +> Represents MetalLib 3.0. + +`metallib_3_1` +> Represents MetalLib 3.1. + +`metallib_latest` +> Represents the latest MetalLib version. + +`sm_4_0` +> HLSL shader model 4.0 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_4_0_version` +> HLSL shader model 4.0 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_4_1` +> HLSL shader model 4.1 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_4_1_version` +> HLSL shader model 4.1 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_5_0` +> HLSL shader model 5.0 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_5_0_version` +> HLSL shader model 5.0 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_5_1` +> HLSL shader model 5.1 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_5_1_version` +> HLSL shader model 5.1 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_0` +> HLSL shader model 6.0 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_0_version` +> HLSL shader model 6.0 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_1` +> HLSL shader model 6.1 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_1_version` +> HLSL shader model 6.1 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_2` +> HLSL shader model 6.2 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_2_version` +> HLSL shader model 6.2 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_3` +> HLSL shader model 6.3 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_3_version` +> HLSL shader model 6.3 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_4` +> HLSL shader model 6.4 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_4_version` +> HLSL shader model 6.4 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_5` +> HLSL shader model 6.5 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_5_version` +> HLSL shader model 6.5 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_6` +> HLSL shader model 6.6 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_6_version` +> HLSL shader model 6.6 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_7` +> HLSL shader model 6.7 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_7_version` +> HLSL shader model 6.7 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_8` +> HLSL shader model 6.8 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_8_version` +> HLSL shader model 6.8 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`sm_6_9` +> HLSL shader model 6.9 and related capabilities of other targets. +> Includes related GLSL/SPIRV extensions. + +`sm_6_9_version` +> HLSL shader model 6.9 and related capabilities of other targets. +> Does not include related GLSL/SPIRV extensions. + +`spirv_1_0` +> Represents SPIR-V 1.0 version. + +`spirv_1_1` +> Represents SPIR-V 1.1 version, which includes SPIR-V 1.0. + +`spirv_1_2` +> Represents SPIR-V 1.2 version, which includes SPIR-V 1.1. + +`spirv_1_3` +> Represents SPIR-V 1.3 version, which includes SPIR-V 1.2. + +`spirv_1_4` +> Represents SPIR-V 1.4 version, which includes SPIR-V 1.3. + +`spirv_1_5` +> Represents SPIR-V 1.5 version, which includes SPIR-V 1.4 and additional extensions. + +`spirv_1_6` +> Represents SPIR-V 1.6 version, which includes SPIR-V 1.5 and additional extensions. + +`spirv_latest` +> Represents the latest SPIR-V version. + +Extensions +---------------------- +*Capabilities to specify extensions (`GL_EXT`, `SPV_EXT`...)* + +`GL_ARB_derivative_control` +> Represents the GL_ARB_derivative_control extension. + +`GL_ARB_fragment_shader_interlock` +> Represents the GL_ARB_fragment_shader_interlock extension. + +`GL_ARB_gpu_shader5` +> Represents the GL_ARB_gpu_shader5 extension. + +`GL_ARB_gpu_shader_int64` +> Represents the GL_ARB_gpu_shader_int64 extension. + +`GL_ARB_shader_clock` +> Represents the GL_ARB_shader_clock extension. + +`GL_ARB_shader_clock64` +> Represents the GL_ARB_shader_clock64 extension. + +`GL_ARB_shader_image_load_store` +> Represents the GL_ARB_shader_image_load_store extension. + +`GL_ARB_shader_image_size` +> Represents the GL_ARB_shader_image_size extension. + +`GL_ARB_shader_texture_image_samples` +> Represents the GL_ARB_shader_texture_image_samples extension. + +`GL_ARB_sparse_texture` +> Represents the GL_ARB_sparse_texture extension. + +`GL_ARB_sparse_texture2` +> Represents the GL_ARB_sparse_texture2 extension. + +`GL_ARB_sparse_texture_clamp` +> Represents the GL_ARB_sparse_texture_clamp extension. + +`GL_ARB_texture_gather` +> Represents the GL_ARB_texture_gather extension. + +`GL_ARB_texture_multisample` +> Represents the GL_ARB_texture_multisample extension. + +`GL_ARB_texture_query_levels` +> Represents the GL_ARB_texture_query_levels extension. + +`GL_EXT_buffer_reference` +> Represents the GL_EXT_buffer_reference extension. + +`GL_EXT_buffer_reference_uvec2` +> Represents the GL_EXT_buffer_reference_uvec2 extension. + +`GL_EXT_debug_printf` +> Represents the GL_EXT_debug_printf extension. + +`GL_EXT_demote_to_helper_invocation` +> Represents the GL_EXT_demote_to_helper_invocation extension. + +`GL_EXT_device_group` +> Represents the GL_EXT_device_group extension. + +`GL_EXT_fragment_shader_barycentric` +> Represents the GL_EXT_fragment_shader_barycentric extension. + +`GL_EXT_maximal_reconvergence` +> Represents the GL_EXT_maximal_reconvergence extension. + +`GL_EXT_mesh_shader` +> Represents the GL_EXT_mesh_shader extension. + +`GL_EXT_nonuniform_qualifier` +> Represents the GL_EXT_nonuniform_qualifier extension. + +`GL_EXT_ray_query` +> Represents the GL_EXT_ray_query extension. + +`GL_EXT_ray_tracing` +> Represents the GL_EXT_ray_tracing extension. + +`GL_EXT_ray_tracing_position_fetch` +> Represents the GL_EXT_ray_tracing_position_fetch extension. + +`GL_EXT_ray_tracing_position_fetch_ray_query` +> Represents the GL_EXT_ray_tracing_position_fetch_ray_query extension. + +`GL_EXT_ray_tracing_position_fetch_ray_tracing` +> Represents the GL_EXT_ray_tracing_position_fetch_ray_tracing extension. + +`GL_EXT_samplerless_texture_functions` +> Represents the GL_EXT_samplerless_texture_functions extension. + +`GL_EXT_shader_atomic_float` +> Represents the GL_EXT_shader_atomic_float extension. + +`GL_EXT_shader_atomic_float2` +> Represents the GL_EXT_shader_atomic_float2 extension. + +`GL_EXT_shader_atomic_float_min_max` +> Represents the GL_EXT_shader_atomic_float_min_max extension. + +`GL_EXT_shader_atomic_int64` +> Represents the GL_EXT_shader_atomic_int64 extension. + +`GL_EXT_shader_explicit_arithmetic_types` +> Represents the GL_EXT_shader_explicit_arithmetic_types extension. + +`GL_EXT_shader_explicit_arithmetic_types_int64` +> Represents the GL_EXT_shader_explicit_arithmetic_types_int64 extension. + +`GL_EXT_shader_image_load_store` +> Represents the GL_EXT_shader_image_load_store extension. + +`GL_EXT_shader_invocation_reorder` +> Represents the GL_EXT_shader_invocation_reorder extension (cross-vendor standard). + +`GL_EXT_shader_invocation_reorder_motion` +> Represents the GL_EXT_shader_invocation_reorder + motion blur combined extension (cross-vendor SER with NV motion blur). +> Used for motion blur variants of EXT SER functions. + +`GL_EXT_shader_quad_control` +> Represents the GL_EXT_shader_quad_control extension. + +`GL_EXT_shader_realtime_clock` +> Represents the GL_EXT_shader_realtime_clock extension. + +`GL_EXT_texture_query_lod` +> Represents the GL_EXT_texture_query_lod extension. + +`GL_EXT_texture_shadow_lod` +> Represents the GL_EXT_texture_shadow_lod extension. + +`GL_KHR_memory_scope_semantics` +> Represents the GL_KHR_memory_scope_semantics extension. + +`GL_KHR_shader_subgroup_arithmetic` +> Represents the GL_KHR_shader_subgroup_arithmetic extension. + +`GL_KHR_shader_subgroup_ballot` +> Represents the GL_KHR_shader_subgroup_ballot extension. + +`GL_KHR_shader_subgroup_basic` +> Represents the GL_KHR_shader_subgroup_basic extension. + +`GL_KHR_shader_subgroup_clustered` +> Represents the GL_KHR_shader_subgroup_clustered extension. + +`GL_KHR_shader_subgroup_quad` +> Represents the GL_KHR_shader_subgroup_quad extension. + +`GL_KHR_shader_subgroup_rotate` +> Represents the GL_KHR_shader_subgroup_rotate extension. + +`GL_KHR_shader_subgroup_shuffle` +> Represents the GL_KHR_shader_subgroup_shuffle extension. + +`GL_KHR_shader_subgroup_shuffle_relative` +> Represents the GL_KHR_shader_subgroup_shuffle_relative extension. + +`GL_KHR_shader_subgroup_vote` +> Represents the GL_KHR_shader_subgroup_vote extension. + +`GL_NV_cluster_acceleration_structure` +> Represents the GL_NV_cluster_acceleration_structure extension. + +`GL_NV_compute_shader_derivatives` +> Represents the GL_NV_compute_shader_derivatives extension. +> +> This capability enables the use of implicit derivatives in compute, ray tracing, and mesh stages. +> +> This capability changes the interpretation of GLSL implicit-LOD texture sampling functions as follows, matching +> the GLSL shader specification: +> - Derivatives enabled: Implicit-LOD `texture()` functions are assumed to use implicit LOD. +> - Derivatives disabled: Implicit-LOD `texture()` functions are assumed to use the base texture. +> +> This applies to GLSL as both source and target. + +`GL_NV_cooperative_vector` +> Represents the GL_NV_cooperative_vector extension. + +`GL_NV_fragment_shader_barycentric` +> Represents the GL_NV_fragment_shader_barycentric extension. + +`GL_NV_gpu_shader5` +> Represents the GL_NV_gpu_shader5 extension. + +`GL_NV_ray_tracing` +> Represents the GL_NV_ray_tracing extension. + +`GL_NV_ray_tracing_motion_blur` +> Represents the GL_NV_ray_tracing_motion_blur extension. + +`GL_NV_shader_atomic_fp16_vector` +> Represents the GL_NV_shader_atomic_fp16_vector extension. + +`GL_NV_shader_invocation_reorder` +> Represents the GL_NV_shader_invocation_reorder extension (NVIDIA-specific). + +`GL_NV_shader_invocation_reorder_motion` +> Represents the GL_NV_shader_invocation_reorder + motion blur combined extension (NVIDIA-specific). +> Used for motion blur variants of SER functions that require both extensions. + +`GL_NV_shader_subgroup_partitioned` +> Represents the GL_NV_shader_subgroup_partitioned extension. + +`GL_NV_shader_texture_footprint` +> Represents the GL_NV_shader_texture_footprint extension. + +`SPV_EXT_demote_to_helper_invocation` +> Represents the SPIR-V extension for demoting to helper invocation. + +`SPV_EXT_descriptor_indexing` +> Represents the SPIR-V extension for descriptor indexing. + +`SPV_EXT_float8` +> Represents the SPIR-V extension for SPV_EXT_float8. + +`SPV_EXT_fragment_fully_covered` +> Represents the SPIR-V extension for SPV_EXT_fragment_fully_covered. + +`SPV_EXT_fragment_shader_interlock` +> Represents the SPIR-V extension for fragment shader interlock operations. + +`SPV_EXT_mesh_shader` +> Represents the SPIR-V extension for mesh shaders. + +`SPV_EXT_physical_storage_buffer` +> Represents the SPIR-V extension for physical storage buffer. + +`SPV_EXT_replicated_composites` +> Represents the SPIR-V extension for SPV_EXT_replicated_composites. + +`SPV_EXT_shader_atomic_float16_add` +> Represents the SPIR-V extension for atomic float16 add operations. + +`SPV_EXT_shader_atomic_float_add` +> Represents the SPIR-V extension for atomic float add operations. + +`SPV_EXT_shader_atomic_float_min_max` +> Represents the SPIR-V extension for atomic float min/max operations. + +`SPV_EXT_shader_invocation_reorder` +> Represents the SPIR-V extension for shader invocation reorder (cross-vendor standard). +> Requires SPV_KHR_ray_tracing and SPIR-V 1.5 (which includes physical storage buffer). +> Note: Spec allows SPIR-V 1.4 + physical_storage_buffer extension, but we require 1.5 for simplicity. + +`SPV_GOOGLE_user_type` +> Represents the SPIR-V extension for SPV_GOOGLE_user_type. + +`SPV_KHR_bfloat16` +> Represents the SPIR-V extension for BFloat16 types. + +`SPV_KHR_compute_shader_derivatives` +> Represents the SPIR-V extension for compute shader derivatives. + +`SPV_KHR_cooperative_matrix` +> Represents the SPIR-V extension for SPV_KHR_cooperative_matrix. + +`SPV_KHR_device_group` +> Represents the SPIR-V extension for device-group information. + +`SPV_KHR_fragment_shader_barycentric` +> Represents the SPIR-V extension for fragment shader barycentric. + +`SPV_KHR_maximal_reconvergence` +> Represents the SPIR-V extension for maximal reconvergence. + +`SPV_KHR_non_semantic_info` +> Represents the SPIR-V extension for non-semantic information. + +`SPV_KHR_quad_control` +> Represents the SPIR-V extension for quad group control. + +`SPV_KHR_ray_query` +> Represents the SPIR-V extension for ray queries. + +`SPV_KHR_ray_tracing` +> Represents the SPIR-V extension for ray tracing. + +`SPV_KHR_ray_tracing_position_fetch` +> Represents the SPIR-V extension for ray tracing position fetch. +> Should be used with either SPV_KHR_ray_query or SPV_KHR_ray_tracing. + +`SPV_KHR_shader_clock` +> Represents the SPIR-V extension for shader clock. + +`SPV_KHR_subgroup_rotate` +> Represents the SPIR-V extension enables rotating values across invocations within a subgroup. + +`SPV_KHR_vulkan_memory_model` +> Represents the SPIR-V extension for SPV_KHR_vulkan_memory_model. + +`SPV_NV_bindless_texture` +> Represents the SPIR-V extension for SPV_NV_bindless_texture. + +`SPV_NV_cluster_acceleration_structure` +> Represents the SPIR-V extension for cluster acceleration structure. + +`SPV_NV_compute_shader_derivatives` +> Represents the SPIR-V extension for compute shader derivatives. + +`SPV_NV_cooperative_matrix2` +> Represents the SPIR-V extension for SPV_NV_cooperative_matrix2. + +`SPV_NV_cooperative_vector` +> Represents the SPIR-V extension for SPV_NV_cooperative_vector. + +`SPV_NV_linear_swept_spheres` +> Represents the SPIR-V extension for linear swept spheres. + +`SPV_NV_ray_tracing_motion_blur` +> Represents the SPIR-V extension for ray tracing motion blur. + +`SPV_NV_shader_image_footprint` +> Represents the SPIR-V extension for shader image footprint. + +`SPV_NV_shader_invocation_reorder` +> Represents the SPIR-V extension for shader invocation reorder (NVIDIA-specific). +> Requires SPV_KHR_ray_tracing. + +`SPV_NV_shader_subgroup_partitioned` +> Represents the SPIR-V extension for shader subgroup partitioned. + +`SPV_NV_tensor_addressing` +> Represents the SPIR-V extension for SPV_NV_tensor_addressing. + +`ser_hlsl_native` +> DXR 1.3 native SER support (SM 6.9, no NVAPI required) + +`spvAtomicFloat16AddEXT` +> Represents the SPIR-V capability for atomic float 16 add operations. + +`spvAtomicFloat16MinMaxEXT` +> Represents the SPIR-V capability for atomic float 16 min/max operations. + +`spvAtomicFloat32AddEXT` +> Represents the SPIR-V capability for atomic float 32 add operations. + +`spvAtomicFloat32MinMaxEXT` +> Represents the SPIR-V capability for atomic float 32 min/max operations. + +`spvAtomicFloat64AddEXT` +> Represents the SPIR-V capability for atomic float 64 add operations. + +`spvAtomicFloat64MinMaxEXT` +> Represents the SPIR-V capability for atomic float 64 min/max operations. + +`spvBFloat16KHR` +> Represents the SPIR-V capability for using bf16 floating point type. + +`spvBindlessTextureNV` +> Represents the SPIR-V capability for the bindless texture. + +`spvCooperativeMatrixBlockLoadsNV` +> Represents the SPIR-V capability for cooperative matrix 2 + +`spvCooperativeMatrixConversionsNV` +> Represents the SPIR-V capability for cooperative matrix 2 + +`spvCooperativeMatrixKHR` +> Represents the SPIR-V capability for cooperative matrices + +`spvCooperativeMatrixPerElementOperationsNV` +> Represents the SPIR-V capability for cooperative matrix 2 + +`spvCooperativeMatrixReductionsNV` +> Represents the SPIR-V capability for cooperative matrix 2 + +`spvCooperativeMatrixTensorAddressingNV` +> Represents the SPIR-V capability for cooperative matrix 2 + +`spvCooperativeVectorNV` +> Represents the SPIR-V capability for cooperative vectors + +`spvCooperativeVectorTrainingNV` +> Represents the SPIR-V capability for cooperative vector training + +`spvDemoteToHelperInvocation` +> Represents the SPIR-V capability for demoting to helper invocation. + +`spvDemoteToHelperInvocationEXT` +> Represents the SPIR-V capability for demoting to helper invocation. + +`spvDerivativeControl` +> Represents the SPIR-V capability for 'derivative control' operations. + +`spvDeviceGroup` +> Represents the SPIR-V capability for DeviceGroup. + +`spvFloat8EXT` +> Represents the SPIR-V capability for using 8-bit floating point types. + +`spvFragmentBarycentricKHR` +> Represents the SPIR-V capability for using SPV_KHR_fragment_shader_barycentric. + +`spvFragmentFullyCoveredEXT` +> Represents the SPIR-V capability for using SPV_EXT_fragment_fully_covered functionality. + +`spvFragmentShaderPixelInterlockEXT` +> Represents the SPIR-V capability for using SPV_EXT_fragment_shader_interlock. + +`spvGroupNonUniformArithmetic` +> Represents the SPIR-V capability for group non-uniform arithmetic operations. + +`spvGroupNonUniformBallot` +> Represents the SPIR-V capability for group non-uniform ballot operations. + +`spvGroupNonUniformPartitionedNV` +> Represents the SPIR-V capability for group non-uniform partitioned operations. + +`spvGroupNonUniformQuad` +> Represents the SPIR-V capability for group non-uniform quad operations. + +`spvGroupNonUniformRotateKHR` +> Represents the SPIR-V capability for group non-uniform rotate operations. + +`spvGroupNonUniformShuffle` +> Represents the SPIR-V capability for group non-uniform shuffle operations. + +`spvGroupNonUniformVote` +> Represents the SPIR-V capability for group non-uniform vote operations. + +`spvImageFootprintNV` +> Represents the SPIR-V capability for image footprint. + +`spvImageGatherExtended` +> Represents the SPIR-V capability for extended image gather operations. + +`spvImageQuery` +> Represents the SPIR-V capability for image query operations. + +`spvInt64Atomics` +> Represents the SPIR-V capability for 64-bit integer atomics. + +`spvMaximalReconvergenceKHR` +> Represents the SPIR-V capability for maximal reconvergence. + +`spvMeshShadingEXT` +> Represents the SPIR-V capability for mesh shading. + +`spvMinLod` +> Represents the SPIR-V capability for using minimum LOD operations. + +`spvQuadControlKHR` +> Represents the SPIR-V capability for quad group control. + +`spvRayQueryKHR` +> Represents the SPIR-V capability for ray query. + +`spvRayQueryPositionFetchKHR` +> Represents the SPIR-V capability for ray query position fetch. + +`spvRayTracingClusterAccelerationStructureNV` +> Represents the SPIR-V capability for cluster acceleration structure. + +`spvRayTracingKHR` +> Represents the SPIR-V capability for ray tracing. + +`spvRayTracingLinearSweptSpheresGeometryNV` +> Represents the SPIR-V capability for linear swept spheres. + +`spvRayTracingMotionBlurNV` +> Represents the SPIR-V capability for ray tracing motion blur. + +`spvRayTracingPositionFetchKHR` +> Represents the SPIR-V capability for ray tracing position fetch. + +`spvReplicatedCompositesEXT` +> Represents the SPIR-V capability for replicated composites + +`spvShaderClockKHR` +> Represents the SPIR-V capability for shader clock. + +`spvShaderInvocationReorderEXT` +> Represents the SPIR-V capability for shader invocation reorder (cross-vendor standard). + +`spvShaderInvocationReorderMotionEXT` +> Represents the SPIR-V capability for shader invocation reorder EXT + motion blur (cross-vendor SER with NV motion blur). +> Used for motion blur variants of EXT SER functions. + +`spvShaderInvocationReorderMotionNV` +> Represents the SPIR-V capability for shader invocation reorder + motion blur (NVIDIA-specific). +> Used for motion blur variants of SER functions that require both extensions. + +`spvShaderInvocationReorderNV` +> Represents the SPIR-V capability for shader invocation reorder (NVIDIA-specific). + +`spvShaderNonUniform` +> Represents the SPIR-V capability for non-uniform resource indexing. + +`spvShaderNonUniformEXT` +> Represents the SPIR-V capability for non-uniform resource indexing. + +`spvSparseResidency` +> Represents the SPIR-V capability for sparse residency. + +`spvTensorAddressingNV` +> Represents the SPIR-V capability for tensor addressing + +`spvVulkanMemoryModelDeviceScopeKHR` +> Represents the SPIR-V capability for vulkan memory model. + +`spvVulkanMemoryModelKHR` +> Represents the SPIR-V capability for vulkan memory model. + +Compound Capabilities +---------------------- +*Capabilities to specify capabilities created by other capabilities (`raytracing`, `meshshading`...)* + +`amplification_mesh` +> Collection of shader stages + +`any_cpp_target` +> All "cpp syntax" code-gen targets + +`any_gfx_target` +> All slang-gfx compatible code-gen targets + +`any_stage` +> Collection of all shader stages + +`any_target` +> All code-gen targets + +`any_textual_target` +> All non-asm code-gen targets + +`anyhit_closesthit` +> Collection of shader stages + +`anyhit_closesthit_intersection` +> Collection of shader stages + +`anyhit_closesthit_intersection_miss` +> Collection of shader stages + +`anyhit_intersection` +> Collection of shader stages (for OptiX ObjectRayOrigin/Direction which excludes closesthit) + +`appendstructuredbuffer` +> Capabilities required to use AppendStructuredBuffer + +`atomic64` +> Capabilities needed for int64/uint64 atomic operations + +`atomic_bfloat16` +> Atomic operations on BFloat16 types. Requires SM 9.0 (Hopper) or higher on CUDA. + +`atomic_glsl` +> (GLSL/SPIRV) Capabilities required to use GLSL-400 atomic operations + +`atomic_glsl_float1` +> (GLSL/SPIRV) Capabilities required to use GLSL-tier-1 float-atomic operations + +`atomic_glsl_float2` +> (GLSL/SPIRV) Capabilities required to use GLSL-tier-2 float-atomic operations + +`atomic_glsl_halfvec` +> (GLSL/SPIRV) Capabilities required to use NVAPI GLSL-fp16 float-atomic operations + +`atomic_glsl_hlsl_cuda9_int64` +> (All implemented targets) Capabilities required to use atomic operations (cuda_sm_9 tier atomics) + +`atomic_glsl_hlsl_cuda_metal` +> (All implemented targets) Capabilities required to use atomic operations + +`atomic_glsl_hlsl_nvapi_cuda5_int64` +> (All implemented targets) Capabilities required to use atomic operations of int64 (cuda_sm_5 tier atomics) + +`atomic_glsl_hlsl_nvapi_cuda6_int64` +> (All implemented targets) Capabilities required to use atomic operations of int64 (cuda_sm_6 tier atomics) + +`atomic_glsl_hlsl_nvapi_cuda9_int64` +> (All implemented targets) Capabilities required to use atomic operations of int64 (cuda_sm_9 tier atomics) + +`atomic_glsl_hlsl_nvapi_cuda_metal_float1` +> (All implemented targets) Capabilities required to use atomic operations of GLSL tier-1 float atomics + +`atomic_glsl_int64` +> (GLSL/SPIRV) Capabilities required to use int64/uint64 atomic operations + +`atomic_hlsl` +> (hlsl only) Capabilities required to use hlsl atomic operations + +`atomic_hlsl_nvapi` +> (hlsl only) Capabilities required to use hlsl NVAPI atomics + +`atomic_hlsl_sm_6_6` +> (hlsl only) Capabilities required to use hlsl sm_6_6 atomics + +`atomic_reduce` +> Atomic reduction operations using PTX `red` instruction. Requires SM 7.0 on CUDA. +> On non-CUDA targets, falls back to regular atomic operations with no additional requirement. + +`atomicfloat` +> Capabilities needed to use GLSL-tier-1 float-atomic operations + +`atomicfloat2` +> Capabilities needed to use GLSL-tier-2 float-atomic operations + +`breakpoint` +> Capabilities required to enable shader breakpoints + +`bufferreference` +> Capabilities needed to use GLSL buffer-reference's + +`bufferreference_int64` +> Capabilities needed to use GLSL buffer-reference's with int64 + +`byteaddressbuffer` +> Capabilities required to use ByteAddressBuffer + +`byteaddressbuffer_rw` +> Capabilities required to use RWByteAddressBuffer + +`compute_fragment` +> Collection of shader stages + +`compute_fragment_geometry_vertex` +> Collection of shader stages + +`compute_tesscontrol_tesseval` +> Collection of shader stages + +`consumestructuredbuffer` +> Capabilities required to use ConsumeStructuredBuffer + +`cooperative_matrix` +> Capabilities needed to use cooperative matrices + +`cooperative_matrix_2` +> Capabilities needed to use tensor addressing + +`cooperative_matrix_block_load` +> Capabilities needed to use decodeFunc with cooperative matrix load + +`cooperative_matrix_conversion` +> Capabilities needed to convert cooperative matrices, all the conversions can be supported by cuda + +`cooperative_matrix_map_element` +> Capabilities needed to use MapElement operation with cooperative matrix + +`cooperative_matrix_reduction` +> Capabilities needed to use reduction operations with cooperative matrix + +`cooperative_matrix_spirv` +> Capabilities needed to use reduction operations with cooperative matrix + +`cooperative_matrix_tensor_addressing` +> Capabilities needed to load or store with tensor_addressing extension + +`cooperative_vector` +> Capabilities needed to use cooperative vectors +> Note that cpp and cuda are supported via a fallback non-cooperative implementation +> No HLSL shader model bound yet + +`cooperative_vector_training` +> Capabilities needed to train cooperative vectors + +`cpp_cuda` +> CPP and CUDA code-gen targets + +`cpp_cuda_glsl_hlsl` +> CPP, CUDA, GLSL, and HLSL code-gen targets + +`cpp_cuda_glsl_hlsl_llvm` +> CPP, CUDA, GLSL, HLSL, and LLVM code-gen targets + +`cpp_cuda_glsl_hlsl_metal_spirv` +> CPP, CUDA, GLSL, HLSL, Metal and SPIRV code-gen targets + +`cpp_cuda_glsl_hlsl_metal_spirv_llvm` +> CPP, CUDA, GLSL, HLSL, Metal, SPIRV, and LLVM code-gen targets + +`cpp_cuda_glsl_hlsl_metal_spirv_wgsl` +> CPP, CUDA, GLSL, HLSL, Metal, SPIRV and WGSL code-gen targets + +`cpp_cuda_glsl_hlsl_metal_spirv_wgsl_llvm` +> CPP, CUDA, GLSL, HLSL, Metal, SPIRV, WGSL and LLVM code-gen targets + +`cpp_cuda_glsl_hlsl_spirv` +> CPP, CUDA, GLSL, HLSL, and SPIRV code-gen targets + +`cpp_cuda_glsl_hlsl_spirv_llvm` +> CPP, CUDA, GLSL, HLSL, SPIRV, and LLVM code-gen targets + +`cpp_cuda_glsl_hlsl_spirv_wgsl` +> CPP, CUDA, GLSL, HLSL, SPIRV and WGSL code-gen targets + +`cpp_cuda_glsl_hlsl_spirv_wgsl_llvm` +> CPP, CUDA, GLSL, HLSL, SPIRV, WGSL and LLVM code-gen targets + +`cpp_cuda_glsl_spirv` +> CPP, CUDA, GLSL and SPIRV code-gen targets + +`cpp_cuda_hlsl` +> CPP, CUDA, and HLSL code-gen targets + +`cpp_cuda_hlsl_metal_spirv` +> CPP, CUDA, HLSL, Metal, and SPIRV code-gen targets + +`cpp_cuda_hlsl_spirv` +> CPP, CUDA, HLSL, and SPIRV code-gen targets + +`cpp_cuda_llvm` +> CPP, CUDA and LLVM code-gen targets + +`cpp_cuda_metal_spirv` +> CPP, CUDA, Metal, and SPIRV code-gen targets + +`cpp_cuda_spirv` +> CPP, CUDA and SPIRV code-gen targets + +`cpp_cuda_spirv_llvm` +> CPP, CUDA, SPIRV and LLVM code-gen targets + +`cpp_glsl` +> CPP, and GLSL code-gen targets + +`cpp_glsl_hlsl_metal_spirv` +> CPP, GLSL, HLSL, Metal, and SPIRV code-gen targets + +`cpp_glsl_hlsl_metal_spirv_wgsl` +> CPP, GLSL, HLSL, Metal, SPIRV and WGSL code-gen targets + +`cpp_glsl_hlsl_spirv` +> CPP, GLSL, HLSL, and SPIRV code-gen targets + +`cpp_glsl_hlsl_spirv_wgsl` +> CPP, GLSL, HLSL, SPIRV and WGSL code-gen targets + +`cpp_hlsl` +> CPP, and HLSL code-gen targets + +`cpp_llvm` +> CPP and LLVM code-gen targets + +`cuda_glsl_hlsl` +> CUDA, GLSL, and HLSL code-gen targets + +`cuda_glsl_hlsl_metal_spirv` +> CUDA, GLSL, HLSL, Metal, and SPIRV code-gen targets + +`cuda_glsl_hlsl_metal_spirv_wgsl` +> CUDA, GLSL, HLSL, Metal, SPIRV and WGSL code-gen targets + +`cuda_glsl_hlsl_spirv` +> CUDA, GLSL, HLSL, and SPIRV code-gen targets + +`cuda_glsl_hlsl_spirv_llvm` +> CUDA, GLSL, HLSL, SPIRV, and LLVM code-gen targets + +`cuda_glsl_hlsl_spirv_wgsl` +> CUDA, GLSL, HLSL, SPIRV, and WGSL code-gen targets + +`cuda_glsl_metal_spirv` +> CUDA, GLSL, Metal, and SPIRV code-gen targets + +`cuda_glsl_metal_spirv_wgsl` +> CUDA, GLSL, Metal, SPIRV and WGSL code-gen targets + +`cuda_glsl_metal_spirv_wgsl_llvm` +> CUDA, GLSL, Metal, SPIRV, WGSL and LLVM code-gen targets + +`cuda_glsl_spirv` +> CUDA, GLSL, and SPIRV code-gen targets + +`cuda_hlsl` +> CUDA, and HLSL code-gen targets + +`cuda_hlsl_metal_spirv` +> CUDA, HLSL, Metal, and SPIRV code-gen targets + +`cuda_hlsl_spirv` +> CUDA, HLSL, SPIRV code-gen targets + +`cuda_spirv` +> CUDA and SPIRV code-gen targets + +`descriptor_handle` +> Targets that support DescriptorHandle types for bindless descriptor access. + +`domain_hull` +> Collection of shader stages + +`fragmentprocessing` +> Capabilities required to use fragment derivative operations (without GLSL derivativecontrol) + +`fragmentprocessing_derivativecontrol` +> Capabilities required to use fragment derivative operations (with GLSL derivativecontrol) + +`fragmentshaderbarycentric` +> Capabilities needed to use fragment-shader-barycentric's + +`fragmentshaderinterlock` +> Capabilities needed for interlocked-fragment operations + +`getattributeatvertex` +> Capabilities required to use 'getAttributeAtVertex' + +`glsl_hlsl_metal_spirv` +> GLSL, HLSL, Metal, and SPIRV code-gen targets + +`glsl_hlsl_metal_spirv_wgsl` +> GLSL, HLSL, Metal, SPIRV and WGSL code-gen targets + +`glsl_hlsl_spirv` +> GLSL, HLSL, and SPIRV code-gen targets + +`glsl_hlsl_spirv_wgsl` +> GLSL, HLSL, SPIRV and WGSL code-gen targets + +`glsl_metal_spirv` +> GLSL, Metal, and SPIRV code-gen targets + +`glsl_metal_spirv_wgsl` +> GLSL, Metal, SPIRV and WGSL code-gen targets + +`glsl_spirv` +> GLSL, and SPIRV code-gen targets + +`glsl_spirv_wgsl` +> GLSL, SPIRV, and WGSL code-gen targets + +`helper_lane` +> Capabilities required to enable helper-lane demotion + +`hlsl_spirv` +> HLSL, and SPIRV code-gen targets + +`image_loadstore` +> (GLSL/SPIRV) Capabilities required to use image load/image store operations + +`image_samples` +> Capabilities required to query image (RWTexture) sample info + +`image_size` +> Capabilities required to query image (RWTexture) size info + +`implicit_derivatives_sampling` +> Capabilities required for implicit derivatives sampling. +> +> This capability is required by texture sampling functions such as `_Texture.Sample()` +> where the level of detail is determined by implicit derivatives. +> +> @remark In GLSL, implicit level-of-detail `texture()` functions use the base texture when +> the implicit derivatives are unavailable. When this capability is not present, invocations of +> these functions are translated to invocations of `_Texture.SampleLevelZero()`. +> +> @remark Implicit derivatives for the compute stage can be enabled by declaring capability `GL_NV_compute_shader_derivatives` (GLSL), +> `SPV_KHR_compute_shader_derivatives` (SPIR-V), or profile `cs_6_6` (HLSL). +> + +`memorybarrier` +> Capabilities required to use sm_5_0 style memory barriers + +`meshshading` +> Ccapabilities required to use mesh shading features + +`motionblur_nv` +> Capabilities needed for raytracing-motionblur (NVIDIA-specific) + +`nonuniformqualifier` +> Capabilities required to use NonUniform qualifier + +`nvapi` +> NVAPI capability for HLSL + +`pack_vector` +> Capabilities required to use pack/unpack intrinsics on packed vector data + +`printf` +> Capabilities required to use 'printf' + +`quad_control` +> Capabilities required to enable quad group control + +`raygen_closesthit_miss` +> Collection of shader stages + +`raygen_closesthit_miss_callable` +> Collection of shader stages + +`rayquery` +> Capabilities needed for compute-shader rayquery + +`rayquery_position` +> Collection of capabilities for rayquery + ray_tracing_position_fetch. + +`raytracing` +> Capabilities needed for minimal raytracing support + +`raytracing_allstages` +> Collection of capabilities for raytracing with all raytracing stages. + +`raytracing_anyhit` +> Collection of capabilities for raytracing with the shader stage of anyhit. + +`raytracing_anyhit_closesthit` +> Collection of capabilities for raytracing with the shader stages of anyhit and closesthit. + +`raytracing_anyhit_closesthit_intersection` +> Collection of capabilities for raytracing with the shader stages of anyhit, closesthit, and intersection. + +`raytracing_anyhit_closesthit_intersection_miss` +> Collection of capabilities for raytracing with the shader stages of anyhit, closesthit, intersection, and miss. + +`raytracing_intersection` +> Collection of capabilities for raytracing with the shader stage of intersection. + +`raytracing_lss` +> Collection of capabilities for linear swept spheres. + +`raytracing_lss_ho` +> hit object APIs allow raygen shaders, but not the non-hit object APIs. So we have this special +> capdef specifically for the hitobject variant. +> Collection of capabilities for linear swept spheres. + +`raytracing_motionblur` +> Capabilities needed for compute-shader rayquery and motion-blur + +`raytracing_motionblur_anyhit_closesthit_intersection_miss` +> Collection of capabilities for raytracing + motion blur and the shader stages of anyhit, closesthit, intersection, and miss. + +`raytracing_motionblur_raygen_closesthit_miss` +> Collection of capabilities for raytracing + motion blur and the shader stages of raygen, closesthit, and miss. + +`raytracing_object_space_ray` +> Collection of capabilities for ObjectRayOrigin/ObjectRayDirection. +> CUDA/OptiX only supports anyhit and intersection stages, while other targets also support closesthit. + +`raytracing_position` +> Collection of capabilities for raytracing + ray_tracing_position_fetch and the shader stages of anyhit and closesthit. + +`raytracing_raygen_closesthit_miss` +> Collection of capabilities for raytracing with the shader stages of raygen, closesthit, and miss. + +`raytracing_raygen_closesthit_miss_callable` +> Collection of capabilities for raytracing the shader stages of raygen, closesthit, miss, and callable. + +`raytracing_stages` +> Collection of shader stages + +`raytracingstages_compute` +> Collection of shader stages + +`raytracingstages_compute_amplification_mesh` +> Collection of shader stages + +`raytracingstages_compute_fragment` +> Collection of shader stages + +`raytracingstages_compute_fragment_geometry_vertex` +> Collection of shader stages + +`raytracingstages_fragment` +> Collection of shader stages + +`ser` +> Capabilities needed for shader-execution-reordering (all paths) +> Includes NVIDIA-specific (NV), cross-vendor standard (EXT), DXR 1.3 native, and CUDA paths + +`ser_any_closesthit_intersection_miss` +> Collection of capabilities for raytracing + shader execution reordering and the shader stages of anyhit, closesthit, intersection, and miss. + +`ser_anyhit_closesthit` +> Collection of capabilities for raytracing + shader execution reordering and the shader stages of anyhit and closesthit. + +`ser_anyhit_closesthit_intersection` +> Collection of capabilities for raytracing + shader execution reordering and the shader stages of anyhit, closesthit, and intersection. + +`ser_dxr` +> Capabilities needed for shader-execution-reordering (native DXR 1.3 path) + +`ser_dxr_raygen` +> Collection of capabilities for DXR 1.3 native SER (HLSL only) with raygen stage. + +`ser_dxr_raygen_closesthit_miss` +> Collection of capabilities for DXR 1.3 native SER (HLSL only) with raygen, closesthit, miss stages. + +`ser_motion` +> Capabilities needed for shader-execution-reordering and motion-blur + +`ser_motion_raygen` +> Collection of capabilities for raytracing raytracing + motion blur + shader execution reordering and the shader stage of raygen. + +`ser_motion_raygen_closesthit_miss` +> Collection of capabilities for raytracing + motion blur + shader execution reordering and the shader stages of raygen, closesthit, and miss. + +`ser_nv` +> NVIDIA-specific SER capabilities (excludes cross-vendor EXT) +> Includes GL_NV_shader_invocation_reorder (GLSL/SPIRV) and CUDA paths + +`ser_nv_motion` +> NVIDIA-specific SER + motion blur + +`ser_nv_motion_raygen_closesthit_miss` +> NVIDIA-specific SER + motion blur for raygen, closesthit, miss stages + +`ser_nv_raygen` +> NVIDIA-specific SER for raygen stage (GLSL/SPIRV NV paths) + +`ser_nv_raygen_closesthit_miss` +> NVIDIA-specific SER for raygen, closesthit, miss stages (GLSL/SPIRV NV paths) + +`ser_nvapi` +> Capabilities needed for shader-execution-reordering (NVAPI path for HLSL) + +`ser_raygen` +> Collection of capabilities for raytracing + shader execution reordering and the shader stage of raygen. + +`ser_raygen_closesthit_miss` +> Collection of capabilities for raytracing + shader execution reordering and the shader stages of raygen, closesthit, and miss. + +`shader5_sm_4_0` +> Capabilities required to use sm_4_0 features apart of GL_ARB_gpu_shader5 + +`shader5_sm_5_0` +> Capabilities required to use sm_5_0 features apart of GL_ARB_gpu_shader5 + +`shaderclock` +> Capabilities needed for realtime clocks + +`shaderinvocationgroup` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_vote' + +`shadermemorycontrol` +> (gfx targets) Capabilities needed to use memory barriers + +`shadermemorycontrol_compute` +> (gfx targets) Capabilities required to use memory barriers that only work for raytracing & compute shader stages + +`structuredbuffer` +> Capabilities required to use StructuredBuffer + +`structuredbuffer_rw` +> Capabilities required to use RWStructuredBuffer + +`subgroup_arithmetic` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_arithmetic' + +`subgroup_ballot` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_ballot' + +`subgroup_ballot_activemask` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_ballot_activemask' + +`subgroup_basic` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_basic' + +`subgroup_basic_ballot` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_basic_ballot' + +`subgroup_clustered` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_clustered' + +`subgroup_partitioned` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_partitioned' + +`subgroup_quad` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_quad' + +`subgroup_rotate` +> Capabilities required to use GLSL-style subgroup rotate operations 'subgroup_rotate' + +`subgroup_shuffle` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_shuffle' + +`subgroup_shufflerelative` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_shuffle_relative' + +`subgroup_vote` +> Capabilities required to use GLSL-style subgroup operations 'subgroup_vote' + +`subpass` +> Capabilities required to use Subpass-Input's + +`tensor_addressing` +> Capabilities needed to use tensor addressing + +`texture_gather` +> Capabilities required to use 'vertex/fragment/geometry shader only' texture gather operations + +`texture_querylevels` +> Capabilities required to query texture level info + +`texture_querylod` +> Capabilities required to query texture LOD info + +`texture_shadowgrad` +> Capabilities required for shadow texture sampling with bias and gradients. +> New in HLSL SM6.8 but existed in older GLSL and SPIRV targets. + +`texture_shadowlod` +> Capabilities required to query shadow texture lod info + +`texture_size` +> Capabilities required to query texture sample info + +`texture_sm_4_0` +> Capabilities required to use sm_4_0 texture operations + +`texture_sm_4_0_fragment` +> Capabilities required to use 'fragment shader only' texture operations + +`texture_sm_4_1` +> Capabilities required to use sm_4_1 texture operations + +`texture_sm_4_1_clamp_fragment` +> Capabilities required to use 'fragment shader only' texture clamp operations + +`texture_sm_4_1_compute_fragment` +> Capabilities required to use 'compute/fragment shader only' texture operations. +> We do not require 'compute'/'fragment' shader capabilities since this seems to be incorrect behavior despite what official documentation says. + +`texture_sm_4_1_samplerless` +> Capabilities required to use sm_4_1 samplerless texture operations + +`texture_sm_4_1_vertex_fragment_geometry` +> Capabilities required to use 'fragment/geometry shader only' texture clamp operations + +`texturefootprint` +> Capabilities required to use basic TextureFootprint operations + +`texturefootprintclamp` +> Capabilities required to use TextureFootprint clamp operations + +`vk_mem_model` +> Capabilities needed to use vulkan memory model + +Other +---------------------- +*Capabilities which may be deprecated* + +`DX_4_0` +> Use `sm_4_0` instead + +`DX_4_1` +> Use `sm_4_1` instead + +`DX_5_0` +> Use `sm_5_0` instead + +`DX_5_1` +> Use `sm_5_1` instead + +`DX_6_0` +> Use `sm_6_0` instead + +`DX_6_1` +> Use `sm_6_1` instead + +`DX_6_2` +> Use `sm_6_2` instead + +`DX_6_3` +> Use `sm_6_3` instead + +`DX_6_4` +> Use `sm_6_4` instead + +`DX_6_5` +> Use `sm_6_5` instead + +`DX_6_6` +> Use `sm_6_6` instead + +`DX_6_7` +> Use `sm_6_7` instead + +`DX_6_8` +> Use `sm_6_8` instead + +`DX_6_9` +> Use `sm_6_9` instead + +`GLSL_410_SPIRV_1_0` +> User should not use this capability + +`GLSL_420_SPIRV_1_0` +> User should not use this capability + +`GLSL_430_SPIRV_1_0` +> User should not use this capability + +`GLSL_430_SPIRV_1_0_compute` +> User should not use this capability + +`METAL_2_3` +> Use `metallib_2_3` instead + +`METAL_2_4` +> Use `metallib_2_4` instead + +`METAL_3_0` +> Use `metallib_3_0` instead + +`METAL_3_1` +> Use `metallib_3_1` instead + +`SPIRV_1_0` +> Use `spirv_1_0` instead + +`SPIRV_1_1` +> Use `spirv_1_1` instead + +`SPIRV_1_2` +> Use `spirv_1_2` instead + +`SPIRV_1_3` +> Use `spirv_1_3` instead + +`SPIRV_1_4` +> Use `spirv_1_4` instead + +`SPIRV_1_5` +> Use `spirv_1_5` instead + +`SPIRV_1_6` +> Use `spirv_1_6` instead + +`SPV_KHR_variable_pointers` +> Represents the SPIRV-V Variable Pointers extension. + +`all` +> User should not use this capability + +`optix_coopvec` +> Represents capabilities required for optix cooperative vector support. + +`optix_multilevel_traversal` +> Represents capabilities required for optix multi-level traversal support. diff --git a/lib/All/slang/share/doc/slang/user-guide/a3-reference.md b/lib/All/slang/share/doc/slang/user-guide/a3-reference.md new file mode 100644 index 0000000..3e2fc83 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/a3-reference.md @@ -0,0 +1,21 @@ +--- +layout: user-guide +permalink: /user-guide/reference +--- + +Reference +============================ + +In this chapter: +1. [Reference for all Capability Profiles](a3-01-reference-capability-profiles.md) +2. [Reference for all Capability Atoms](a3-02-reference-capability-atoms.md) + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/index.md b/lib/All/slang/share/doc/slang/user-guide/index.md new file mode 100644 index 0000000..e683af1 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/index.md @@ -0,0 +1,37 @@ +--- +layout: user-guide +--- + +Slang User's Guide +============= + +Welcome to the Slang User's Guide, an introduction to the Slang language, compiler, and API. In this guide, you will learn: +- Slang's language features, including those inherited from HLSL and additional language features to make it easy to work with shaders. +- The compiler API that controls how to assemble shaders from different pieces of code, and how they are compiled for different targets. +- The reflection API that allows the host application to query the details of shader code in order to generate the right shader kernel and to set shader parameters correctly. + +Note: this documentation is still under active development. While the coverage on language features is complete, we are still working on the remaining chapters on Slang's compilation and reflection API. + + \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/user-guide/nav.html b/lib/All/slang/share/doc/slang/user-guide/nav.html new file mode 100644 index 0000000..af74986 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/nav.html @@ -0,0 +1,6 @@ +

    diff --git a/lib/All/slang/share/doc/slang/user-guide/toc.html b/lib/All/slang/share/doc/slang/user-guide/toc.html new file mode 100644 index 0000000..37ec0f6 --- /dev/null +++ b/lib/All/slang/share/doc/slang/user-guide/toc.html @@ -0,0 +1,297 @@ +
    • Slang User's Guide +
        +
      • Introduction +
          +
        • Why use Slang?
        • +
        • Who is Slang for?
        • +
        • Who is this guide for?
        • +
        • Goals and Non-Goals
        • +
        +
      • +
      • Getting Started with Slang +
          +
        • Installation
        • +
        • Your first Slang shader
        • +
        • The full example
        • +
        +
      • +
      • Conventional Language Features +
          +
        • Types
        • +
        • Expressions
        • +
        • Statements
        • +
        • Functions
        • +
        • Preprocessor
        • +
        • Attributes
        • +
        • Global Variables and Shader Parameters
        • +
        • Shader Entry Points
        • +
        • Mixed Shader Entry Points
        • +
        • Auto-Generated Constructors
        • +
        • Initializer Lists
        • +
        +
      • +
      • Basic Convenience Features +
          +
        • Type Inference in Variable Definitions
        • +
        • Immutable Values
        • +
        • Namespaces
        • +
        • Member functions
        • +
        • Properties
        • +
        • Initializers
        • +
        • Operator Overloading
        • +
        • Subscript Operator
        • +
        • Tuple Types
        • +
        • `Optional<T>` type
        • +
        • `Conditional<T, bool condition>` Type
        • +
        • `if_let` syntax
        • +
        • `reinterpret<T>` operation
        • +
        • Pointers (limited)
        • +
        • `DescriptorHandle` for Bindless Descriptor Access
        • +
        • Extensions
        • +
        • Multi-level break
        • +
        • Force inlining
        • +
        • Error handling
        • +
        • Special Scoping Syntax
        • +
        • User Defined Attributes (Experimental)
        • +
        +
      • +
      • Modules and Access Control +
          +
        • Defining a Module
        • +
        • Importing a Module
        • +
        • Access Control
        • +
        • Organizing File Structure of Modules
        • +
        • Legacy Modules
        • +
        +
      • +
      • Capabilities +
          +
        • Capability Atoms and Capability Requirements
        • +
        • Conflicting Capabilities
        • +
        • Capabilities Between Parent and Members
        • +
        • Capabilities Between Subtype and Supertype
        • +
        • Capabilities Between Requirement and Implementation
        • +
        • Capabilities of Functions
        • +
        • Capability Aliases
        • +
        • Validation of Capability Requirements
        • +
        +
      • +
      • Interfaces and Generics +
          +
        • Interfaces
        • +
        • Generics
        • +
        • Supported Constructs in Interface Definitions
        • +
        • Associated Types
        • +
        • Generic Value Parameters
        • +
        • Type Equality Constraints
        • +
        • Interface-typed Values
        • +
        • Extending a Type with Additional Interface Conformances
        • +
        • `is` and `as` Operator
        • +
        • Generic Interfaces
        • +
        • Generic Extensions
        • +
        • Extensions to Interfaces
        • +
        • Variadic Generics
        • +
        • Builtin Interfaces
        • +
        +
      • +
      • Automatic Differentiation +
          +
        • Auto-diff operations `fwd_diff` and `bwd_diff`
        • +
        • Differentiable Type System
        • +
        • User-Defined Derivative Functions
        • +
        • Using Auto-diff with Generics
        • +
        • Using Auto-diff with Interface Requirements and Interface Types
        • +
        • Primal Substitute Functions
        • +
        • Working with Mixed Differentiable and Non-Differentiable Code
        • +
        • Higher-Order Differentiation
        • +
        • Restrictions and Known Issues
        • +
        • Reference
        • +
        +
      • +
      • Compiling Code with Slang +
          +
        • Concepts
        • +
        • Command-Line Compilation with `slangc`
        • +
        • Using the Compilation API
        • +
        • Multithreading
        • +
        • Compiler Options
        • +
        • Debugging
        • +
        +
      • +
      • Using the Reflection API +
          +
        • Compiling a Program
        • +
        • Types and Variables
        • +
        • Layout for Types and Variables
        • +
        • Programs and Scopes
        • +
        • Calculating Cumulative Offsets
        • +
        • Determining Whether Parameters Are Used
        • +
        • Conclusion
        • +
        +
      • +
      • Supported Compilation Targets +
          +
        • Background and Terminology
        • +
        • Direct3D 11
        • +
        • Direct3D 12
        • +
        • Vulkan
        • +
        • OpenGL
        • +
        • Metal
        • +
        • CUDA and OptiX
        • +
        • CPU Compute
        • +
        • WebGPU
        • +
        • Summary
        • +
        +
      • +
      • Link-time Specialization and Module Precompilation +
          +
        • Link-time Constants
        • +
        • Link-time Types
        • +
        • Providing Default Settings
        • +
        • Using Precompiling Modules with the API
        • +
        • Additional Remarks
        • +
        +
      • +
      • language slang 2026 +
          +
        • The Legacy Slang Language
        • +
        • Slang 2025
        • +
        • Slang 2026
        • +
        +
      • +
      • Special Topics +
          +
        • Handling Matrix Layout Differences on Different Platforms +
            +
          • Two conventions of matrix transform math
          • +
          • Discussion
          • +
          • Matrix Layout
          • +
          • Overriding default matrix layout
          • +
          +
        • +
        • Obfuscation +
            +
          • Obfuscation in Slang
          • +
          • Using An Obfuscated Module
          • +
          • Accessing Source Maps
          • +
          • Accessing Source Maps without Files
          • +
          • Emit Source Maps
          • +
          • Issues/Future Work
          • +
          +
        • +
        • Interoperation with Target-Specific Code +
            +
          • Defining Intrinsic Functions for Textual Targets
          • +
          • Defining Intrinsic Types
          • +
          • Injecting Preludes
          • +
          • Managing Cross-Platform Code
          • +
          • Inline SPIRV Assembly
          • +
          +
        • +
        • Uniformity Analysis +
            +
          • Treat Values as Uniform
          • +
          • Treat Function Return Values as Non-uniform
          • +
          +
        • +
        +
      • +
      • Target-Specific Features +
          +
        • SPIR-V-Specific Functionalities +
            +
          • Experimental support for the older versions of SPIR-V
          • +
          • Memory model
          • +
          • Combined texture sampler
          • +
          • System-Value semantics
          • +
          • Using SV_InstanceID and SV_VertexID with SPIR-V target
          • +
          • Behavior of `discard` after SPIR-V 1.6
          • +
          • Supported HLSL features when targeting SPIR-V
          • +
          • Unsupported GLSL keywords when targeting SPIR-V
          • +
          • Supported atomic types for each target
          • +
          • ConstantBuffer, StructuredBuffer and ByteAddressBuffer
          • +
          • ParameterBlock for SPIR-V target
          • +
          • Push Constants
          • +
          • Specialization Constants
          • +
          • SPIR-V specific Attributes
          • +
          • Multiple entry points support
          • +
          • Global memory pointers
          • +
          • Matrix type translation
          • +
          • Legalization
          • +
          • Tessellation
          • +
          • SPIR-V specific Compiler options
          • +
          +
        • +
        • Metal-Specific Functionalities +
            +
          • Entry Point Parameter Handling
          • +
          • System-Value semantics
          • +
          • Interpolation Modifiers
          • +
          • Resource Types
          • +
          • Array Types
          • +
          • Matrix Layout
          • +
          • Mesh Shader Support
          • +
          • Header Inclusions and Namespace
          • +
          • Parameter blocks and Argument Buffers
          • +
          • Struct Parameter Flattening
          • +
          • Return Value Handling
          • +
          • Value Type Conversion
          • +
          • Conservative Rasterization
          • +
          • Address Space Assignment
          • +
          • Explicit Parameter Binding
          • +
          • Specialization Constants
          • +
          +
        • +
        • WGSL-Specific Functionalities +
            +
          • System-Value semantics
          • +
          • Supported HLSL features when targeting WGSL
          • +
          • Supported atomic types
          • +
          • ConstantBuffer, (RW/RasterizerOrdered)StructuredBuffer, (RW/RasterizerOrdered)ByteAddressBuffer
          • +
          • Interlocked operations
          • +
          • Entry Point Parameter Handling
          • +
          • Parameter blocks
          • +
          • Write-only Textures
          • +
          • Pointers
          • +
          • Address Space Assignment
          • +
          • Matrix type translation
          • +
          • Explicit Parameter Binding
          • +
          • Specialization Constants
          • +
          +
        • +
        • GLSL-Specific Functionalities +
            +
          • Combined Texture Sampler
          • +
          • System-Value Semantics
          • +
          • `discard` Statement
          • +
          • HLSL Features Supported in GLSL
          • +
          • Atomic Types
          • +
          • Buffer Types
          • +
          • Matrix Layout
          • +
          • Entry Points
          • +
          • Specialization Constants
          • +
          • Attributes and Layout Qualifiers
          • +
          • GLSL-Specific Compiler Options
          • +
          +
        • +
        +
      • +
      • Reference +
          +
        • Capability Profiles +
        • +
        • Capability Atoms +
            +
          • Targets
          • +
          • Stages
          • +
          • Versions
          • +
          • Extensions
          • +
          • Compound Capabilities
          • +
          • Other
          • +
          +
        • +
        +
      • +
      +
    • +
    \ No newline at end of file diff --git a/lib/All/slang/share/doc/slang/wave-intrinsics.md b/lib/All/slang/share/doc/slang/wave-intrinsics.md new file mode 100644 index 0000000..4156c47 --- /dev/null +++ b/lib/All/slang/share/doc/slang/wave-intrinsics.md @@ -0,0 +1,453 @@ + +Wave Intrinsics +=============== + +Slang has support for Wave intrinsics introduced to HLSL in [SM6.0](https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/hlsl-shader-model-6-0-features-for-direct3d-12) and [SM6.5](https://github.com/microsoft/DirectX-Specs/blob/master/d3d/HLSL_ShaderModel6_5.md). All intrinsics are available on D3D12 and Vulkan. + +On GLSL targets such as Vulkan wave intrinsics map to ['subgroup' extension] (https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_shader_subgroup.txt). Vulkan supports a number of masked wave operations through `SPV_NV_shader_subgroup_partitioned` that are not supported by HLSL. + +There is no subgroup support for Matrix types, and currently this means that Matrix is not a supported type for Wave intrinsics on Vulkan, but may be in the future. + + +Also introduced are some 'non standard' Wave intrinsics which are only available on Slang. All WaveMask intrinsics are non standard. Other non standard intrinsics expose more accurately different behaviours which are either not distinguished on HLSL, or perhaps currently unavailable. Two examples would be `WaveShuffle` and `WaveBroadcastLaneAt`. + +There are three styles of wave intrinsics... + +## WaveActive + +The majority of 'regular' HLSL Wave intrinsics which operate on implicit 'active' lanes. + +In the [DXC Wiki](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Wave-Intrinsics) active lanes are described as + +> These intrinsics are dependent on active lanes and therefore flow control. In the model of this document, implementations +> must enforce that the number of active lanes exactly corresponds to the programmer’s view of flow control. + +In practice this appears to imply that the programming model is that all lanes operate in 'lock step'. That the 'active lanes' are the lanes doing processing at a particular point in the control flow. On some hardware this may match how processing actually works. There is also a large amount of hardware in the field that doesn't follow this model, and allows lanes to diverge and not necessarily on flow control. On this style of hardware Active intrinsics may act to also converge lanes to give the appearance of 'in step' ness. + +## WaveMask + +The WaveMask intrinsics take an explicit mask of lanes to operate on, in the same vein as CUDA. Requesting data from a from an inactive lane, can lead to undefined behavior, that includes locking up the shader. The WaveMask is an integer type that can hold the maximum amount of active lanes for this model - currently 32. In the future the WaveMask type may be made an opaque type, but can largely be operated on as if it is an integer. + +Using WaveMask intrinsics is generally more verbose and prone to error than the 'Active' style, but it does have a few advantages + +* It works across all supported targets - including CUDA (currently WaveActive intrinics do not) +* Gives more fine control +* Might allow for higher performance (for example it gives more control of divergence) +* Maps most closely to CUDA + +For this to work across targets including CUDA, the mask must be calculated such that it exactly matches that of HLSL defined 'active' lanes, else the behavior is undefined. + +On D3D12 and Vulkan the WaveMask intrinsics can be used, but the mask may be ignored depending on target's support for partitioned/masked wave intrinsics. SPIRV provides support for a wide variety of operations through the `SPV_NV_shader_subgroup_partitioned` extension while HLSL only provides a small subset of operations through `WaveMultiPrefix*` intrinsics. The difference between Slang's `WaveMask` and these targets' partitioned wave intrinsics is that they accept a `uint4` mask instead of a `uint` mask. `WaveMask*` intrinsics effectively gets translated to `WaveMulti*` intrinsics when targeting SPIRV/GLSL and HLSL. Please consult [Wave Multi Intrinsics](#wave-multi-intrinsics) for more details, including what masked operations are supported by each target. + + +The WaveMask intrinsics are a non standard Slang feature, and may change in the future. + +``` +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + // It is the programmers responsibility to determine the initial mask, and that is dependent on the launch + // It's common to launch such that all lanes are active - with CUDA this would mean 32 lanes. + // Here the launch only has 4 lanes active, and so the initial mask is 0xf. + const WaveMask mask0 = 0xf; + + int idx = int(dispatchThreadID.x); + + int value = 0; + + // When there is a conditional/flow control we typically need to work out a new mask. + // This can be achieved by calling WaveMaskBallot with the current mask, and the condition + // used in the flow control - here the subsequent 'if'. + const WaveMask mask1 = WaveMaskBallot(mask0, idx == 2); + + if (idx == 2) + { + // At this point the mask is `mask1`, although no WaveMask intrinsics are used along this path, + // so it's not used. + + // diverge + return; + } + + // If we get here, the active lanes must be the opposite of mask1 (because we took the other side of the condition), but cannot include + // any lanes which were not active before. We can calculate this as mask0 & ~mask1. + + const WaveMask mask2 = mask0 & ~mask1; + + // mask2 holds the correct active mask to use with WaveMaskMin + value = WaveMaskMin(mask2, idx + 1); + + // Write out the result + outputBuffer[idx] = value; +} +``` + +Many of the nuances of writing code in this way are discussed in the [CUDA documentation](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#warp-vote-functions). + +The above example written via the regular intrinsics is significantly simpler, as we do not need to track 'active lanes' in the masks. + +``` +RWStructuredBuffer outputBuffer; + +[numthreads(4, 1, 1)] +void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int idx = int(dispatchThreadID.x); + + int value = 0; + + if (idx == 2) + { + // diverge + return; + } + + value = WaveActiveMin(idx + 1); + + // Write out the result + outputBuffer[idx] = value; +} +``` +## WaveMulti + +The standard 'Multi' intrinsics were added to HLSL is SM 6.5 and are available in SPIRV through `SPV_NV_shader_subgroup_partitioned`, they can specify a mask of lanes via uint4. SPIRV provide non-prefix (reduction) and prefix (scan) intrinsics for arithmetic and min/max operations, while HLSL only provides a subset of these, namely exclusive prefix arithmetic operations. + + +Standard Wave intrinsics +========================= + +The Wave Intrinsics supported on Slang are listed below. Note that typically T generic types also include vector and matrix forms. + +``` +// Lane info + +uint WaveGetLaneCount(); + +uint WaveGetLaneIndex(); + +bool WaveIsFirstLane(); + +// Ballot + +bool WaveActiveAllTrue(bool condition); + +bool WaveActiveAnyTrue(bool condition); + +uint4 WaveActiveBallot(bool condition); + +uint WaveActiveCountBits(bool value); + +// Across Lanes + +T WaveActiveBitAnd(T expr); + +T WaveActiveBitOr(T expr); + +T WaveActiveBitXor(T expr); + +T WaveActiveMax(T expr); + +T WaveActiveMin(T expr); + +T WaveActiveProduct(T expr); + +T WaveActiveSum(T expr); + +bool WaveActiveAllEqual(T value); + +// Prefix + +T WavePrefixProduct(T expr); + +T WavePrefixSum(T expr); + +// Communication + +T WaveReadLaneFirst(T expr); + +T WaveReadLaneAt(T value, int lane); + +// Prefix + +uint WavePrefixCountBits(bool value); + +// Shader model 6.5 stuff +// https://github.com/microsoft/DirectX-Specs/blob/master/d3d/HLSL_ShaderModel6_5.md + +uint4 WaveMatch(T value); + +uint WaveMultiPrefixCountBits(bool value, uint4 mask); + +T WaveMultiPrefixBitAnd(T expr, uint4 mask); + +T WaveMultiPrefixBitOr(T expr, uint4 mask); + +T WaveMultiPrefixBitXor(T expr, uint4 mask); + +T WaveMultiPrefixProduct(T value, uint4 mask); + +T WaveMultiPrefixSum(T value, uint4 mask); +``` + +Non Standard Wave Intrinsics +============================ + +The following intrinsics are not part of the HLSL Wave intrinsics standard, but were added to Slang for a variety of reasons. Within the following signatures T can be scalar, vector or matrix, except on Vulkan which doesn't (currently) support Matrix. + +``` +T WaveBroadcastLaneAt(T value, constexpr int lane); + +T WaveShuffle(T value, int lane); + +uint4 WaveGetActiveMulti(); + +uint4 WaveGetConvergedMulti(); + +uint WaveGetNumWaves(); // Number of waves in workgroup (equivalent to GLSL gl_NumSubgroups) + +// Prefix (exclusive scan operations, equivalent to GLSL subgroupExclusive*) + +T WavePrefixMin(T expr); // Exclusive prefix minimum + +T WavePrefixMax(T expr); // Exclusive prefix maximum + +T WavePrefixBitAnd(T expr); // Exclusive prefix bitwise AND + +T WavePrefixBitOr(T expr); // Exclusive prefix bitwise OR + +T WavePrefixBitXor(T expr); // Exclusive prefix bitwise XOR + +// Barriers + +void AllMemoryBarrierWithWaveSync(); + +void GroupMemoryBarrierWithWaveSync(); +``` + +## Description + +``` +T WaveBroadcastLaneAt(T value, constexpr int lane); +``` + +All lanes receive the value specified in lane. Lane must be an active lane, otherwise the result is undefined. +This is a more restrictive version of `WaveReadLaneAt` - which can take a non constexpr lane, *but* must be the same value for all lanes in the warp. Or 'dynamically uniform' as described in the HLSL documentation. + +``` +T WaveShuffle(T value, int lane); +``` + +Shuffle is a less restrictive version of `WaveReadLaneAt` in that it has no restriction on the lane value - it does *not* require the value to be same on all lanes. + +There isn't explicit support for WaveShuffle in HLSL, and for now it will emit `WaveReadLaneAt`. As it turns out for a sizable set of hardware WaveReadLaneAt does work correctly when the lane is not 'dynamically uniform'. This is not necessarily the case for hardware general though, so if targeting HLSL it is important to make sure that this does work correctly on your target hardware. + +Our intention is that Slang will support the appropriate HLSL mechanism that makes this work on all hardware when it's available. + +``` +void AllMemoryBarrierWithWaveSync(); +``` + +Synchronizes all lanes to the same AllMemoryBarrierWithWaveSync in program flow. Orders all memory accesses such that accesses after the barrier can be seen by writes before. + +``` +void GroupMemoryBarrierWithWaveSync(); +``` + +Synchronizes all lanes to the same GroupMemoryBarrierWithWaveSync in program flow. Orders group shared memory accesses such that accesses after the barrier can be seen by writes before. + + +Wave Rotate Intrinsics +====================== + +These intrinsics are specific to Slang and were added to support the subgroup rotate functionalities provided by SPIRV (through the `GroupNonUniformRotateKHR` capability), GLSL (through the `GL_KHR_shader_subgroup_rotate +` extension), and Metal. + +``` +// Supported on SPIRV, GLSL, and Metal targets. +T WaveRotate(T value, uint delta); + +// Supported on SPIRV and GLSL targets. +T WaveClusteredRotate(T value, uint delta, constexpr uint clusterSize); +``` + +Wave Multi Intrinsics +====================== + +`WaveMulti` intrinsics take an explicit `uint4` mask of lanes to operate on. They correspond to the subgroup partitioned intrinsics provided by `SPV_NV_shader_subgroup_partitioned` and the `WaveMultiPrefix*` intrinsics provided by HLSL SM 6.5. HLSL's `WaveMulti*` intrinsics only provide operations for exclusive prefix arithmetic operations, while Vulkan's `SPV_NV_shader_subgroup_partitioned` provides operations for both inclusive/exclusive prefix (scan) and non-prefix (reduction) arithmetic and min/max operations. + +Slang adds new `WaveMulti*` intrinsics in addition to HLSL's `WaveMultiPrefix*` to allow generating all partitioned intrinsics supported in SPIRV. The new, non-standard HLSL, `WaveMulti*` intrinsics are only supported when targeting SPIRV, GLSL and CUDA. The inclusive variants of HLSL's `WaveMultiPrefix*` intrinsics are emulated by Slang by performing an additional operation in the current invocation. Metal and WGSL targets do not support `WaveMulti` intrinsics. +``` +// Across lane ops. These are only supported when targeting SPIRV, GLSL and CUDA. + +T WaveMultiSum(T value, uint4 mask); + +T WaveMultiProduct(T value, uint4 mask); + +T WaveMultiMin(T value, uint4 mask); + +T WaveMultiMax(T value, uint4 mask); + +T WaveMultiBitAnd(T value, uint4 mask); + +T WaveMultiBitOr(T value, uint4 mask); + +T WaveMultiBitXor(T value, uint4 mask); + + +// Prefix arithmetic operations. Supported when targeting SPIRV, GLSL, CUDA and HLSL. +// In addition to these non-HLSL standard intrinsics are the standard `WaveMultiPrefix*` +// intrinsics provided by SM 6.5, detailed in the `Standard Wave Intrinsics` section. + +T WaveMultiPrefixInclusiveSum(T value, uint4 mask); + +T WaveMultiPrefixInclusiveProduct(T value, uint4 mask); + +T WaveMultiPrefixInclusiveBitAnd(T value, uint4 mask); + +T WaveMultiPrefixInclusiveBitOr(T value, uint4 mask); + +T WaveMultiPrefixInclusiveBitXor(T value, uint4 mask); + +T WaveMultiPrefixExclusiveSum(T value, uint4 mask); + +T WaveMultiPrefixExclusiveProduct(T value, uint4 mask); + +T WaveMultiPrefixExclusiveBitAnd(T value, uint4 mask); + +T WaveMultiPrefixExclusiveBitOr(T value, uint4 mask); + +T WaveMultiPrefixExclusiveBitXor(T value, uint4 mask); + + +// Prefix min/max operations. Supported when targeting SPIRV and GLSL. + +T WaveMultiPrefixInclusiveMin(T value, uint4 mask); + +T WaveMultiPrefixInclusiveMax(T value, uint4 mask); + +T WaveMultiPrefixExclusiveMin(T value, uint4 mask); + +T WaveMultiPrefixExclusiveMax(T value, uint4 mask); +``` + + +Wave Mask Intrinsics +==================== + +CUDA has a different programming model for inter warp/wave communication based around masks of active lanes. This is because the CUDA programming model allows for divergence that is more granualar than just on program flow, and that there isn't implied reconvergence at the end of a conditional. + +In the future Slang may have the capability to work out the masks required such that the regular HLSL Wave intrinsics work. As it stands there does not appear to be any way to implement the regular Wave intrinsics directly. To work around this problem we introduce 'WaveMask' intrinsics, which are essentially the same as the regular HLSL Wave intrinsics with the first parameter as the WaveMask which identifies the participating lanes. + +The WaveMask intrinsics will work across targets, but *only* if on CUDA targets the mask captures exactly the same lanes as the 'Active' lanes concept in HLSL. If the masks deviate then the behavior is undefined. On non CUDA based targets currently the mask *may* be ignored depending on the intrinsics supported by the target. + +Most of the `WaveMask` functions are identical to the regular Wave intrinsics, but they take a WaveMask as the first parameter, and the intrinsic name starts with `WaveMask`. Also note that the `WaveMask` functions are introduced in Slang before the `WaveMulti` intrinsics, and they effectively function the same other than the mask width in bits (`uint` vs `uint4`). The `WaveMulti` intrinsics map closer to SPIRV and HLSL, and are recommended to be used over `WaveMask` intrinsics whenever possible. We plan to deprecate the `WaveMask` intrinsics some time in the future. + +``` +WaveMask WaveGetConvergedMask(); +``` + +Gets the mask of lanes which are converged within the Wave. Note that this is *not* the same as Active threads, and may be some subset of that. It is equivalent to the `__activemask()` in CUDA. + +On non CUDA targets the the function will return all lanes as active - even though this is not the case. This is 'ok' in so far as on non CUDA targets the mask is ignored. It is *not* okay if the code uses the value other than as a superset of the 'really converged' lanes. For example testing the bit's and changing behavior would likely not work correctly on non CUDA targets. + +``` +void AllMemoryBarrierWithWaveMaskSync(WaveMask mask); +``` + +Same as AllMemoryBarrierWithWaveSync but takes a mask of active lanes to sync with. + +``` +void GroupMemoryBarrierWithWaveMaskSync(WaveMask mask); +``` + +Same as GroupMemoryBarrierWithWaveSync but takes a mask of active lanes to sync with. + +The intrinsics that make up the Slang `WaveMask` extension. + +``` +// Lane info + +WaveMask WaveGetConvergedMask(); + +WaveMask WaveGetActiveMask(); + +bool WaveMaskIsFirstLane(WaveMask mask); + +// Lane masks (equivalent to GLSL gl_SubgroupXxMask) + +uint4 WaveGetLaneEqMask(); // Mask with only current lane's bit set + +uint4 WaveGetLaneGeMask(); // Mask with bits set for lanes >= current lane + +uint4 WaveGetLaneGtMask(); // Mask with bits set for lanes > current lane + +uint4 WaveGetLaneLeMask(); // Mask with bits set for lanes <= current lane + +uint4 WaveGetLaneLtMask(); // Mask with bits set for lanes < current lane + +// Ballot + +bool WaveMaskAllTrue(WaveMask mask, bool condition); + +bool WaveMaskAnyTrue(WaveMask mask, bool condition); + +WaveMask WaveMaskBallot(WaveMask mask, bool condition); + +WaveMask WaveMaskCountBits(WaveMask mask, bool value); + +WaveMask WaveMaskMatch(WaveMask mask, T value); + +// Barriers + +void AllMemoryBarrierWithWaveMaskSync(WaveMask mask); + +void GroupMemoryBarrierWithWaveMaskSync(WaveMask mask); + +// Across lane ops + +T WaveMaskBitAnd(WaveMask mask, T expr); + +T WaveMaskBitOr(WaveMask mask, T expr); + +T WaveMaskBitXor(WaveMask mask, T expr); + +T WaveMaskMax(WaveMask mask, T expr); + +T WaveMaskMin(WaveMask mask, T expr); + +T WaveMaskProduct(WaveMask mask, T expr); + +T WaveMaskSum(WaveMask mask, T expr); + +bool WaveMaskAllEqual(WaveMask mask, T value); + +// Prefix + +T WaveMaskPrefixProduct(WaveMask mask, T expr); + +T WaveMaskPrefixSum(WaveMask mask, T expr); + +T WaveMaskPrefixMin(WaveMask mask, T expr); + +T WaveMaskPrefixMax(WaveMask mask, T expr); + +T WaveMaskPrefixBitAnd(WaveMask mask, T expr); + +T WaveMaskPrefixBitOr(WaveMask mask, T expr); + +T WaveMaskPrefixBitXor(WaveMask mask, T expr); + +uint WaveMaskPrefixCountBits(WaveMask mask, bool value); + +// Communication + +T WaveMaskReadLaneFirst(WaveMask mask, T expr); + +T WaveMaskBroadcastLaneAt(WaveMask mask, T value, constexpr int lane); + +T WaveMaskReadLaneAt(WaveMask mask, T value, int lane); + +T WaveMaskShuffle(WaveMask mask, T value, int lane); +``` diff --git a/lib/CMake/Linux/VulkanMemoryAllocatorlibConfig.cmake b/lib/CMake/Linux/VulkanMemoryAllocatorlibConfig.cmake new file mode 100644 index 0000000..d72d013 --- /dev/null +++ b/lib/CMake/Linux/VulkanMemoryAllocatorlibConfig.cmake @@ -0,0 +1 @@ +set(VMA_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/VulkanMemoryAllocator/include") diff --git a/lib/CMake/Linux/spirvreflectlibConfig.cmake b/lib/CMake/Linux/spirvreflectlibConfig.cmake new file mode 100644 index 0000000..c97aa72 --- /dev/null +++ b/lib/CMake/Linux/spirvreflectlibConfig.cmake @@ -0,0 +1,2 @@ +set(SPIRV_REFLECT_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/SPIRV-Reflect/include; ${CMAKE_CURRENT_SOURCE_DIR}/lib/All/SPIRV-Reflect") +set(SPIRV_EXT_SRC "${CMAKE_CURRENT_SOURCE_DIR}/lib/All/SPIRV-Reflect/spirv_reflect.c") diff --git a/src/Engine/Configurations/Configuration/CConfiguration.cpp b/src/Engine/Configurations/Configuration/CConfiguration.cpp index e0a1a9f..d5f17f0 100644 --- a/src/Engine/Configurations/Configuration/CConfiguration.cpp +++ b/src/Engine/Configurations/Configuration/CConfiguration.cpp @@ -4,7 +4,7 @@ #include -namespace CosmicCore { +namespace CosmicConfig { CModuleConfig CConfiguration::moduleConfiguration; diff --git a/src/Engine/Configurations/Configuration/CConfiguration.hpp b/src/Engine/Configurations/Configuration/CConfiguration.hpp index d8f3e51..aded165 100644 --- a/src/Engine/Configurations/Configuration/CConfiguration.hpp +++ b/src/Engine/Configurations/Configuration/CConfiguration.hpp @@ -3,7 +3,7 @@ #include "nlohmann/json_fwd.hpp" #include -namespace CosmicCore { +namespace CosmicConfig { class CModuleConfig{ private: std::filesystem::path modulesDirectory; diff --git a/src/Engine/Core/Component/CAbstractComponent.hpp b/src/Engine/Core/Component/CAbstractComponent.hpp index 4d563f5..568573e 100644 --- a/src/Engine/Core/Component/CAbstractComponent.hpp +++ b/src/Engine/Core/Component/CAbstractComponent.hpp @@ -27,7 +27,7 @@ namespace CosmicCore { CAbstractComponent(CEntity& entity): m_owningEntity(entity){}; virtual ~CAbstractComponent() = default; - CEntity& getEntity() { + CEntity getEntity() const { return m_owningEntity; } diff --git a/src/Engine/Core/Component/Camera/CAbstractCamera.cpp b/src/Engine/Core/Component/Camera/CAbstractCamera.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/Engine/Core/Component/Camera/CAbstractCamera.hpp b/src/Engine/Core/Component/Camera/CAbstractCamera.hpp deleted file mode 100644 index c0db9ce..0000000 --- a/src/Engine/Core/Component/Camera/CAbstractCamera.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CABSTRACTCAMERA_HPP -#define CABSTRACTCAMERA_HPP -#include "../CAbstractComponent.hpp" -namespace CosmicCore { - class CAbstractCamera: CAbstractComponent - { - - }; -} -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Camera/CCamera.hpp b/src/Engine/Core/Component/Camera/CCamera.hpp new file mode 100644 index 0000000..f95ab3a --- /dev/null +++ b/src/Engine/Core/Component/Camera/CCamera.hpp @@ -0,0 +1,153 @@ +#ifndef CCAMERA_HPP +#define CCAMERA_HPP + +#include "../CAbstractComponent.hpp" +//pour vulkan depth 0-1 (opengl [-1,1]) +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#include +#include +#include "../../Graphics/API/VulkanImpl.hpp" +#include "../Geometry/CTransform.hpp" +namespace CosmicCore { + +class CCamera : public CAbstractComponent { +private: + // paramètres de la caméra + float m_fov = 45.0f; + float m_near = 0.1f; + float m_far = 1000.0f; + float m_aspect = 16.0f / 9.0f; + + // matrices calculées + glm::mat4 m_view = glm::mat4(1.0f); + glm::mat4 m_projection = glm::mat4(1.0f); + + // GPU + struct CameraUBOData { + glm::mat4 view; + glm::mat4 projection; + }; + + std::array m_uniformBuffers; + std::array m_mappedData{}; + std::array m_descriptorSets; + + void recalcProjection() { + m_projection = glm::perspective(glm::radians(m_fov), m_aspect, m_near, m_far); + // Vulkan a l'axe Y inversé par rapport à OpenGL + m_projection[1][1] *= -1; + } + +public: + CCamera(CEntity& entity) : CAbstractComponent(entity) { + recalcProjection(); + } + + ~CCamera(){ + destroy(); + } + + void setFov(float fov) { + m_fov = fov; + recalcProjection(); + } + + void setAspect(float aspect) { + m_aspect = aspect; + recalcProjection(); + } + + void setNearFar(float near, float far) { + m_near = near; + m_far = far; + recalcProjection(); + } + + // getters + glm::mat4 getView(const CTransform& transform) const { + glm::quat q = transform.getOrientation(); + glm::vec3 position = transform.getCenter(); + + // rotation inverse (conjugué du quaternion) + translation inverse + glm::mat4 rotInverse = glm::toMat4(glm::conjugate(q)); + glm::mat4 transInverse = glm::translate(glm::mat4(1.0f), -position); + + return rotInverse * transInverse; + } + glm::mat4 getProjection() const { return m_projection; } + + // GPU + void initUniformBuffer(VmaAllocator allocator) { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = sizeof(CameraUBOData); + bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + + VmaAllocationCreateInfo allocInfo{}; + allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VmaAllocationInfo info{}; + vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, + &m_uniformBuffers[i].buffer, + &m_uniformBuffers[i].allocation, + &info); + m_mappedData[i] = info.pMappedData; + + m_descriptorSets[i] = api->getDescriptorPoolManager().allocate( + *api->getCameraLayout() + ); + + vk::DescriptorBufferInfo descriptorBufferInfo{ + vk::Buffer(m_uniformBuffers[i].buffer), + 0, + sizeof(CameraUBOData) + }; + vk::WriteDescriptorSet descriptorWrite{ + *m_descriptorSets[i].set, + 0, 0, 1, + vk::DescriptorType::eUniformBuffer, + {}, &descriptorBufferInfo + }; + static_cast(api->getDevice())->updateDescriptorSets(descriptorWrite, {}); + } + } + + void destroyUniformBuffer(VmaAllocator allocator) { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + api->getDescriptorPoolManager().free(m_descriptorSets[i]); + vmaDestroyBuffer(allocator, m_uniformBuffers[i].buffer, + m_uniformBuffers[i].allocation); + } + } + + void updateUniformBuffer(uint32_t frameIndex, const CTransform& transform) { + CameraUBOData data{ getView(transform), m_projection }; + memcpy(m_mappedData[frameIndex], &data, sizeof(data)); + } + + vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) { + return m_descriptorSets[frameIndex].set; + } + + void destroy() + { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + + api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex()); + api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex()); + } + } + + + nlohmann::json to_json(){}; +}; + +} // namespace CosmicCore +#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Geometry/CTransform.cpp b/src/Engine/Core/Component/Geometry/CTransform.cpp index fccd400..9fab206 100644 --- a/src/Engine/Core/Component/Geometry/CTransform.cpp +++ b/src/Engine/Core/Component/Geometry/CTransform.cpp @@ -1,5 +1,6 @@ #include "CTransform.hpp" - +#include "../../Graphics/API/VulkanImpl.hpp" +#include "../Relationships/CRelationship.hpp" namespace CosmicCore { @@ -22,7 +23,7 @@ namespace CosmicCore CTransform::CTransform(CEntity& entity) : CAbstractComponent(entity), m_center(0.0f, 0.0f, 0.0f), m_scale(1.0f, 1.0f, 1.0f), - m_orientation(), + m_orientation(glm::identity()), m_observers() { calcTranslation(); calcRotation(); @@ -41,6 +42,11 @@ namespace CosmicCore calcTranformation(); } + CTransform::~CTransform() + { + destroyUniformBuffer(); + } + glm::mat4 CTransform::getTranslation(void) const { return m_translation; } @@ -58,17 +64,18 @@ namespace CosmicCore } glm::mat4 CTransform::getInheritedTransformation(void) const { - /*const auto& entity = getEntity(); - if(entity) - { - if (entity->getParent().expired()) { - return m_transformation; - } - else { - auto p = entity->getParent().lock(); - return p->getTransform().getInheritedTransformation() * m_transformation; - } - }*/ + auto& registry = getEntity().getRegistry(); + + if (!registry().all_of(*getEntity())) + return m_transformation; + + auto& rel = registry().get(*getEntity()); + + if (rel.getParent() == entt::null) + return m_transformation; + + auto& parentTransform = registry().get(rel.getParent()); + return parentTransform.getInheritedTransformation() * m_transformation; } glm::vec3 CTransform::getCenter(void) const { @@ -158,7 +165,7 @@ namespace CosmicCore } } - void CTransform::forward(glm::vec3 value) { + void CTransform::forward(glm::vec3 value) { glm::vec3 relValue = m_orientation * value; m_center += relValue; calcTranslation(); @@ -177,4 +184,47 @@ namespace CosmicCore { //TODO } + + void CTransform::updateUniformBuffer(uint32_t frameIndex) { + auto data{ getInheritedTransformation() }; // utilise la transformation héritée + memcpy(m_mappedData[frameIndex], &data, sizeof(data)); + } + + void CTransform::initUniformBuffer(VmaAllocator allocator) { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = sizeof(glm::mat4); + bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + + VmaAllocationCreateInfo allocInfo{}; + allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VmaAllocationInfo info{}; + vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, + &m_uniformBuffers[i].buffer, + &m_uniformBuffers[i].allocation, + &info); + m_mappedData[i] = info.pMappedData; + + m_descriptorSets[i] = api->getDescriptorPoolManager().allocate(api->getTransformLayout()); + + vk::DescriptorBufferInfo descriptorBufferInfo{vk::Buffer(m_uniformBuffers[i].buffer), 0, sizeof(glm::mat4)}; + vk::WriteDescriptorSet descriptorWrite{m_descriptorSets[i].set, 0, 0,1, vk::DescriptorType::eUniformBuffer, {}, &descriptorBufferInfo}; + static_cast(api->getDevice())->updateDescriptorSets(descriptorWrite, {}); + } + } + + void CTransform::destroyUniformBuffer() { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + + api->destroyBuffer(m_uniformBuffers[i], api->getCurrentFrameIndex()); + api->destroyDescriptorSet(m_descriptorSets[i], api->getCurrentFrameIndex()); + } + } } \ No newline at end of file diff --git a/src/Engine/Core/Component/Geometry/CTransform.hpp b/src/Engine/Core/Component/Geometry/CTransform.hpp index 6010d32..71b464c 100644 --- a/src/Engine/Core/Component/Geometry/CTransform.hpp +++ b/src/Engine/Core/Component/Geometry/CTransform.hpp @@ -11,6 +11,9 @@ #include #include +#include "../../Graphics/API/VMABuffer.hpp" +#include "../../Graphics/API/ManagedDescriptorSet.hpp" + namespace CosmicCore { /** @@ -79,6 +82,10 @@ namespace CosmicCore * @brief Compute the full transformation of the object. */ void calcTranformation(void); + + std::array m_uniformBuffers; + std::array m_mappedData{}; + std::array m_descriptorSets; public: /** @@ -87,6 +94,13 @@ namespace CosmicCore */ CTransform(CEntity& m_entity); + ~CTransform(); + + CTransform(CTransform&&) = default; + CTransform& operator=(CTransform&&) = default; + + CTransform(const CTransform&) = delete; + CTransform& operator=(const CTransform&) = delete; /** * @brief CTransform's constructor. * @param[in, out] m_entity The entity to which the transform belongs. @@ -240,6 +254,17 @@ namespace CosmicCore t.setScale(glm::vec3(j["Scale"]["x"], j["Scale"]["y"], j["Scale"]["z"])); return t; }; + + void initUniformBuffer(VmaAllocator allocator); + void destroyUniformBuffer(); + void updateUniformBuffer(uint32_t frameIndex); + + VMABuffer& getUniformBuffer(uint32_t frameIndex) { + return m_uniformBuffers[frameIndex]; + }; + vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) { + return m_descriptorSets[frameIndex].set; + }; }; } #endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/CAbstractRenderer.hpp b/src/Engine/Core/Component/Graphics/CAbstractRenderer.hpp index da58106..fb17963 100644 --- a/src/Engine/Core/Component/Graphics/CAbstractRenderer.hpp +++ b/src/Engine/Core/Component/Graphics/CAbstractRenderer.hpp @@ -6,7 +6,6 @@ namespace CosmicCore { { public: CAbstractRenderer(CEntity& e): CAbstractComponent(e){}; - virtual void render() = 0; }; } #endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/CModel.hpp b/src/Engine/Core/Component/Graphics/CModel.hpp deleted file mode 100644 index 800e850..0000000 --- a/src/Engine/Core/Component/Graphics/CModel.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef CMODEL_HPP -#define CMODEL_HPP - -#include "Material/SMaterial.hpp" -#include "Mesh/CMesh.hpp" - -#include -#include - -/** - * @brief Class representing a 3D model. - */ -class CModel { -private: - /** - * @brief The meshes, a vector which contains all the meshes of the object. - */ - std::vector m_meshes; - - /** - * @brief A boolean representing the loading state of the model. - */ - bool m_loaded; - -public: - - /** - * @brief CModel's default constructor, disabled. - */ - CModel(void) = delete; - - /** - * @brief CModel constructor. - * @param meshes : The list of the meshes of the object. - */ - CModel(std::vector meshes); - - /** - * @brief CModel's destructor. - */ - ~CModel(void); - - /** - * @brief Load the model in the GPU. - */ - void load(void); - - /** - * @brief Render the model on the screen. - * @param[in] model The transform of the object. - * @param[in] view The view of the object. - * @param[in] projection The projection of the object. - * @param[in] lightPos The light's position. - * @param[in] intensity The light's intensity. - */ - void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity); - - /** - * @brief Getter to the meshes of the model. - * @return A vector which represent the list of meshes of the model, it's a direct reference to the member m_meshes. - */ - std::vector& getMeshes(void); - - /** - * @brief Setter to the meshes. - * @param[in] meshes The list of meshes to set to the model. - */ - void setMeshes(std::vector meshes); - - /** - * @brief Getter to m_loaded member, say if the model is loaded or not. - * @return A boolean representing the state of the model, loaded or not. - */ - bool isLoaded(void); - -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/CRenderer.cpp b/src/Engine/Core/Component/Graphics/CRenderer.cpp new file mode 100644 index 0000000..8579fc9 --- /dev/null +++ b/src/Engine/Core/Component/Graphics/CRenderer.cpp @@ -0,0 +1,3 @@ +#include "CRenderer.hpp" +namespace CosmicCore { +} \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/CRenderer.hpp b/src/Engine/Core/Component/Graphics/CRenderer.hpp new file mode 100644 index 0000000..79e731b --- /dev/null +++ b/src/Engine/Core/Component/Graphics/CRenderer.hpp @@ -0,0 +1,18 @@ +#ifndef CTESTRENDERER_HPP +#define CTESTRENDERER_HPP +#include "CAbstractRenderer.hpp" +#include "../../Graphics/Data/CModel.hpp" +namespace CosmicCore { + class CRenderer: public CAbstractRenderer + { + CModel* m_model = nullptr; + public: + CRenderer() = delete; + CRenderer(CEntity& e): CAbstractRenderer(e){}; + CRenderer(CEntity& e, CModel* mod): CAbstractRenderer(e), m_model(mod){}; + nlohmann::json to_json() override{return nlohmann::json();}; + CModel* getModel(){return m_model;}; + }; +} +#endif + diff --git a/src/Engine/Core/Component/Graphics/CTestRenderer.cpp b/src/Engine/Core/Component/Graphics/CTestRenderer.cpp deleted file mode 100644 index e46d0a0..0000000 --- a/src/Engine/Core/Component/Graphics/CTestRenderer.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "CTestRenderer.hpp" -#include -namespace CosmicCore { - void CTestRenderer::render() - { - int a = 2*25; - int b = a +2; - std::cout << b << std::endl; - }; -} \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/CTestRenderer.hpp b/src/Engine/Core/Component/Graphics/CTestRenderer.hpp deleted file mode 100644 index 72b8e32..0000000 --- a/src/Engine/Core/Component/Graphics/CTestRenderer.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef CTESTRENDERER_HPP -#define CTESTRENDERER_HPP -#include "CAbstractRenderer.hpp" - -namespace CosmicCore { - class CTestRenderer: public CAbstractRenderer - { - public: - CTestRenderer() = delete; - CTestRenderer(CEntity& e): CAbstractRenderer(e){}; - void render() override; - nlohmann::json to_json(){return nlohmann::json();}; - - }; -} -#endif - diff --git a/src/Engine/Core/Component/Graphics/Material/SMaterial.hpp b/src/Engine/Core/Component/Graphics/Material/SMaterial.hpp deleted file mode 100644 index 30266d1..0000000 --- a/src/Engine/Core/Component/Graphics/Material/SMaterial.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef SMATERIAL_HPP -#define SMATERIAL_HPP - -#include "../Shader/CShader.hpp" -#include "../Texture/CAbstractTexture.hpp" -#include "SColor.hpp" - -#include - -/** - * @file SMaterial.hpp - * @brief File for the material struct. - */ - -/** - * @brief The struct material. - */ -typedef struct SMaterial { - /** - * @brief List of textures for the material. - */ - std::vector m_textures; - - /** - * @brief List of colors for the material. - */ - std::vector m_colors; - - /** - * @brief The shader used to render. - */ - CShader* m_shader = nullptr; - - ~SMaterial() { for (unsigned int i = 0; i < m_textures.size(); ++i) { - delete m_textures[i]; - } }; -} SMaterial; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Mesh/CMesh.cpp b/src/Engine/Core/Component/Graphics/Mesh/CMesh.cpp deleted file mode 100644 index b68abd3..0000000 --- a/src/Engine/Core/Component/Graphics/Mesh/CMesh.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "CMesh.hpp" - -void CMesh::bindMaterial(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) { - // Test the material. - if (m_material == nullptr) { - throw CLogicException("This mesh is not linked to a material."); - } - - // Active the shader. - m_material->m_shader->use(); - - // Give the matrix to the shader. - m_material->m_shader->setMat4("model", model); - m_material->m_shader->setMat4("view", view); - m_material->m_shader->setMat4("projection", projection); - m_material->m_shader->setVec3("lightPos", lightPos); - m_material->m_shader->setFloat("intensity", intensity); - - // Counter for each Texture Type : - unsigned int countTex[TEXTURE_TYPE_NUMBER]; - for (unsigned int i = 0; i < TEXTURE_TYPE_NUMBER; i++) { - countTex[i] = 0; - } - - // For each texture in the material : - for (unsigned int i = 0; i < m_material->m_textures.size(); i++) { - - // Active the shader unit. - glActiveTexture(GL_TEXTURE0 + i); - - // Retrieve texture name. - std::string name; - - switch (m_material->m_textures[i]->getType()) { - case TEXTURE_DIFFUSE: - name = "textureDiffuse" + std::to_string(countTex[0]); - countTex[0]++; - break; - case TEXTURE_SPECULAR: - name = "textureSpecular" + std::to_string(countTex[1]); - countTex[1]++; - break; - case TEXTURE_NORMAL: - name = "textureNormal" + std::to_string(countTex[2]); - countTex[2]++; - break; - case TEXTURE_HEIGHT: - name = "textureHeight" + std::to_string(countTex[3]); - countTex[3]++; - break; - default: - break; - } - - // Get the uniform storage space of the shader. - glUniform1i(glGetUniformLocation(m_material->m_shader->getId(), name.c_str()), i); - - // And finally bind the texture. - glBindTexture(GL_TEXTURE_2D, m_material->m_textures[i]->getId()); - } - - // Always good practice to set everything back to defaults once configured. - glActiveTexture(GL_TEXTURE0); - - - - // Counter for each color Type : - unsigned int countCol[COLOR_TYPE_NUMBER]; - for (unsigned int i = 0; i < COLOR_TYPE_NUMBER; i++) { - countCol[i] = 0; - } - - // For each color in the material : - for (unsigned int i = 0; i < m_material->m_colors.size(); i++) { - - // Retrieve texture name. - std::string name; - - switch (m_material->m_colors[i].m_type) { - case COLOR_DIFFUSE: - name = "colorDiffuse" + std::to_string(countCol[0]); - countCol[0]++; - break; - case COLOR_SPECULAR: - name = "colorSpecular" + std::to_string(countCol[1]); - countCol[1]++; - break; - default: - break; - } - - // Give the color as a vector 4. - m_material->m_shader->setVec4(name, m_material->m_colors[i].m_vector); - } - - // Active the shader. - //m_material->m_shader->use(); -} - -CMesh::CMesh(void) : - m_vertexes(), - m_indexes(), - m_material(nullptr), - m_vertexBufferObject(0), - m_elementBufferObject(0), - m_vertexArrayObject(0) { -} - -CMesh::~CMesh(void) { - // Delete the VAO. - if (m_vertexArrayObject != 0) { - glDeleteVertexArrays(1, &m_vertexArrayObject); - } - - if (m_material != nullptr) - { - delete m_material; - } -} - -std::vector& CMesh::getVertexes(void) { - return m_vertexes; -} - -std::vector& CMesh::getIndexes(void) { - return m_indexes; -} - -SMaterial* CMesh::getMaterial(void) { - return m_material; -} - -void CMesh::setMaterial(SMaterial* material) { - m_material = material; -} - -void CMesh::setVertices(std::vector vertices) -{ - m_vertexes = vertices; -} - -void CMesh::setIndexes(std::vector indexes) -{ - m_indexes = indexes; -} - -void CMesh::load(void) { - if (m_vertexes.empty() || m_indexes.empty()) { - throw CLogicException("This mesh do no contain vertex data."); - } - - // Create the VAO. - glGenVertexArrays(1, &m_vertexArrayObject); - - // Create the VBO. - glGenBuffers(1, &m_vertexBufferObject); - - // Create the EBO. - glGenBuffers(1, &m_elementBufferObject); - - - // Open the VAO. - glBindVertexArray(m_vertexArrayObject); - - // Open the VBO, and link it to the VAO. - glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferObject); - - // Give the block of memory of vertexes vector (so, it works like a c list), and the struct is transparent du to their conception). - glBufferData(GL_ARRAY_BUFFER, m_vertexes.size() * sizeof(SVertex), &m_vertexes[0], GL_STATIC_DRAW); - - // Open the EBO, and link it to the VAO. - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBufferObject); - - // Give the block of memory of indexes vector (so, it works like a c list), and the struct is transparent du to their conception). - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexes.size() * sizeof(unsigned int), &m_indexes[0], GL_STATIC_DRAW); - - - // Set the vertex attribute pointers. - // Vertex Positions. - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)0); - // Vertex normals. - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_normal)); - // Vertex texture coords. - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_texCoords)); - // Vertex tangent. - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_tangent)); - // Vertex bitangent. - glEnableVertexAttribArray(4); - glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)offsetof(SVertex, m_bitangent)); - - - // Unbind the VAO. - glBindVertexArray(0); -} - -void CMesh::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) { - if (m_vertexArrayObject == 0) { - throw CLogicException("This mesh is not loaded in GPU, you can not draw it."); - } - - // Bind the material. - bindMaterial(model, view, projection, lightPos, intensity); - - // Enable the vertex array object, so the shader use the vertex attribute in this vao. - glBindVertexArray(m_vertexArrayObject); - - // Render the triangles in the vertex array object. - glDrawElements(GL_TRIANGLES, (GLsizei)m_indexes.size(), GL_UNSIGNED_INT, 0); - - // Disable the vertex array object. - glBindVertexArray(0); -} \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Mesh/CMesh.hpp b/src/Engine/Core/Component/Graphics/Mesh/CMesh.hpp deleted file mode 100644 index f9e21a7..0000000 --- a/src/Engine/Core/Component/Graphics/Mesh/CMesh.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef CMESH_HPP -#define CMESH_HPP - -#include "../Material/SMaterial.hpp" -#include "../Texture/CAbstractTexture.hpp" -#include "SVertex.hpp" -#include "../../../Controller/Exception/CLogicException.hpp" - -#ifdef WIN32 -#include -#else -#include -#endif - -#include -#define GLM_ENABLE_EXPERIMENTAL -#include - -/** - * @file CMesh.hpp - * @brief File for the mesh struct. - */ - -/** - * @brief Class CMesh, used to represent a mesh, a set of vertex (which can be indexed), ready to be drawn. - */ -class CMesh { -private: - /** - * @brief List of the vertices of the mesh. - */ - std::vector m_vertexes; - - /** - * @brief List of the indices of the mesh. - */ - std::vector m_indexes; - - /** - * @brief A pointer to the material containing textures, colors and the shader used for the mesh. - */ - SMaterial* m_material; - - /** - * @brief The vertex buffer. - */ - unsigned int m_vertexBufferObject; - - /** - * @brief The index buffer. - */ - unsigned int m_elementBufferObject; - - /** - * @brief Vertex array object, all the data. - */ - unsigned int m_vertexArrayObject; - - /** - * @brief Apply material to use for drawing. - * @param[in] model the model matrix. - * @param[in] view the view matrix. - * @param[in] projection the projection matrix. - * @param[in] lightPos the position of the light source. - * @param[in] intensity the intensity of the light source. - */ - void bindMaterial(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity); - -public: - /** - * @brief the constructor. - */ - CMesh(void); - - /** - * @brief the destructor. - */ - ~CMesh(void); - - /** - * @brief The vertex array getter. - * @return std::vector&, A reference to the list of vertex. - */ - std::vector& getVertexes(void); - - /** - * @brief The index array getter. - * @return std::vector&, A reference to the list of index. - */ - std::vector& getIndexes(void); - - /** - * @brief The material getter. - * @return SMaterial*, the material. - */ - SMaterial* getMaterial(void); - - /** - * @brief The material setter. - * @param[in] material the wanted material. - */ - void setMaterial(SMaterial* material); - - /** - * @brief The vertex setter. - * @param[in] vertices list of the vertices to give to the GPU. - */ - void setVertices(std::vector vertices); - - /** - * @brief The indexes setter. - * @param[in] indexes list of the indexes for the index buffer - */ - void setIndexes(std::vector indexes); - - /** - * @brief Load the mesh in GPU. - */ - void load(void); - - /** - * @brief draw the mesh. - * @param[in] model the model matrix. - * @param[in] view the view matrix. - * @param[in] projection the projection matrix. - * @param[in] lightPos the position of the light source. - * @param[in] intensity the intensity of the light source. - */ - void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity); -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Mesh/SVertex.hpp b/src/Engine/Core/Component/Graphics/Mesh/SVertex.hpp deleted file mode 100644 index 77a1427..0000000 --- a/src/Engine/Core/Component/Graphics/Mesh/SVertex.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef SVERTEX_HPP -#define SVERTEX_HPP - -#include - -/** - * @file SVertex.hpp - * @brief File for the vertex struct. - */ - -/** - * @brief the struct Vertex, use to represent vertex and vertex attribute. - */ -typedef struct { - /** - * @brief Position attribute. - * 3D vector. - */ - glm::vec3 m_position; - - /** - * @brief Normal attribute. - * 3D vector. - */ - glm::vec3 m_normal; - - /** - * @brief Texture coordinates attribute. - * 2D vector. - */ - glm::vec2 m_texCoords; - - /** - * @brief Tangent attribute. - * 3D vector. - */ - glm::vec3 m_tangent; - - /** - * @brief Bitangent attribute. - * 3D vector (perpendicular to m_tangent vector). - */ - glm::vec3 m_bitangent; - - // m_normal, m_tangent, m_bitangent are supposed to create a vector base to compute normal map. -} SVertex; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.cpp b/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.cpp deleted file mode 100644 index 5ea9a53..0000000 --- a/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "CAbstractTexture.hpp" - -void CAbstractTexture::setId(unsigned int newId) { - m_glId = newId; -} - -CAbstractTexture::CAbstractTexture(ETextureType type) : - m_glId(0), - m_type(type) { -} - -unsigned int CAbstractTexture::getId(void) { - return m_glId; -} - -ETextureType CAbstractTexture::getType(void) { - return m_type; -} \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.hpp b/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.hpp deleted file mode 100644 index 5ccff04..0000000 --- a/src/Engine/Core/Component/Graphics/Texture/CAbstractTexture.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef CABSTRACTTEXTURE_HPP -#define CABSTRACTTEXTURE_HPP - -#define TEXTURE_TYPE_NUMBER 4 - -/** - * @brief enum representing every type of texture available. - */ -enum ETextureType { - TEXTURE_DIFFUSE, - TEXTURE_SPECULAR, - TEXTURE_NORMAL, - TEXTURE_HEIGHT, -}; - -/** - * @brief Class representing a texture. - */ -class CAbstractTexture { -private: - - /** - * @brief OpenGL ID. - */ - unsigned int m_glId; - - /** - * @brief The texture's type. - */ - ETextureType m_type; - -protected: - - /** - * @brief Setter to the m_glId member. - * @param newId : OpenGL id to set. - */ - void setId(unsigned int newId); -public: - - /** - * @brief CAbstractTexture's default constructor, disabled. - */ - CAbstractTexture(void) = delete; - - /** - * @brief CAbstractTexture's constructor. - * @param[in] type The texture's type. - */ - CAbstractTexture(ETextureType type); - - virtual ~CAbstractTexture() {}; - - /** - * @brief Getter to the m_glId member. - * @return The m_glId member. - */ - unsigned int getId(void); - - /** - * @brief Getter to the texture's type. - * @return The texture's type. - */ - ETextureType getType(void); - - /** - * @brief Load the texture in the GPU (uses only redefined function in the child classes). - */ - virtual void init(void) = 0; -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CImageTexture.cpp b/src/Engine/Core/Component/Graphics/Texture/CImageTexture.cpp deleted file mode 100644 index 9d5a057..0000000 --- a/src/Engine/Core/Component/Graphics/Texture/CImageTexture.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "CImageTexture.hpp" - -CImageTexture::CImageTexture(ETextureType type, std::string filePath) : - CAbstractTexture(type), - m_filePath(filePath) { -} - -std::string CImageTexture::getFilePath(void) { - return m_filePath; -} - -void CImageTexture::setFilePath(std::string filePath) { - m_filePath = filePath; -} - -void CImageTexture::init(void) { - // Read the image file. - SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str()); - - if (sdlSurface == NULL) { - throw CLibException(std::string("Image file \"") + m_filePath + std::string("\" can not be opened : ") + std::string(SDL_GetError())); - } - - // Create the id. - unsigned int id; - glGenTextures(1, &id); - setId(id); - - // Image format. - GLenum internalFormat(0); - GLenum externalFormat(0); - - if (sdlSurface->format->BytesPerPixel == 3) { - // We use RGB as internal format. - internalFormat = GL_RGB; - - // Choose the external format. - if (sdlSurface->format->Rmask == 0xff) - externalFormat = GL_RGB; - else - externalFormat = GL_BGR; - } - else if (sdlSurface->format->BytesPerPixel == 4) { - // We use RGBA as internal format. - internalFormat = GL_RGBA; - - // Choose the external format. - if (sdlSurface->format->Rmask == 0xff) - externalFormat = GL_RGBA; - else - externalFormat = GL_BGRA; - } - else { - SDL_FreeSurface(sdlSurface); - throw CRuntimeException("Unknow image internal format."); - } - - // Lock the texture to use it. - glBindTexture(GL_TEXTURE_2D, getId()); - - // Fill the GL texture. - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, sdlSurface->w, sdlSurface->h, 0, externalFormat, GL_UNSIGNED_BYTE, sdlSurface->pixels); - - // Set filters : the near texture have a linear filter. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - // The far texture have a nearest filter, meaning no filter. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // Unlock the texture. - glBindTexture(GL_TEXTURE_2D, 0); - - // Free the surface. - SDL_FreeSurface(sdlSurface); -} \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CImageTexture.hpp b/src/Engine/Core/Component/Graphics/Texture/CImageTexture.hpp deleted file mode 100644 index 4792976..0000000 --- a/src/Engine/Core/Component/Graphics/Texture/CImageTexture.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CIMAGETEXTURE_HPP -#define CIMAGETEXTURE_HPP - -#include "../../../Controller/Exception/CLibException.hpp" -#include "../../../Controller/Exception/CRuntimeException.hpp" -#include "../../../Controller/Exception/CLogicException.hpp" -#include "CAbstractTexture.hpp" - -#include -#include -#include -#ifdef WIN32 - #include -#else - #include -#endif - -class CImageTexture : public CAbstractTexture { -private: - // Path of the file. - std::string m_filePath; -public: - CImageTexture(void) = delete; - ~CImageTexture(void) {}; - CImageTexture(ETextureType type, std::string filePath); - std::string getFilePath(void); - void setFilePath(std::string filePath); - virtual void init(void); -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Relationships/CRelationship.hpp b/src/Engine/Core/Component/Relationships/CRelationship.hpp new file mode 100644 index 0000000..38fe225 --- /dev/null +++ b/src/Engine/Core/Component/Relationships/CRelationship.hpp @@ -0,0 +1,29 @@ +#ifndef CRELATIONSHIP_HPP +#define CRELATIONSHIP_HPP + +#include "../CAbstractComponent.hpp" +#include "nlohmann/json_fwd.hpp" +#include +#include + +namespace CosmicCore { + class CRelationship : public CAbstractComponent{ + private: + EntityId parent = entt::null; + std::vector children; + public: + CRelationship(CEntity& entity): CAbstractComponent(entity){} + CRelationship(CEntity& entity, EntityId p): CAbstractComponent(entity), parent(p){} + CRelationship(CEntity& entity, std::vector childs): CAbstractComponent(entity), children(childs){} + CRelationship(CEntity& entity, EntityId p, std::vector childs): CAbstractComponent(entity), parent(p), children(childs){} + + nlohmann::json to_json(){return nlohmann::json();} + void setParent(EntityId par){parent = par;} + void addChild(EntityId child){children.emplace_back(child);} + EntityId getParent(){return parent;} + std::vector& getChildren(){return children;} + }; + +} + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Context/CContext.cpp b/src/Engine/Core/Context/CContext.cpp deleted file mode 100644 index a5d52f8..0000000 --- a/src/Engine/Core/Context/CContext.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "CContext.hpp" - -bool CContext::m_screenSaver = false; - -void CContext::init(unsigned int sdlFlags, unsigned int imageFlags) { - // Log initialisation. - initLog(); - DEBUG_LOG(trace, "Kernel", "Context", "Log initialized!") - - // SDL Initialization. - DEBUG_LOG(trace, "Kernel", "Context", "SDL initialization...") - if (SDL_Init(sdlFlags) < 0) { - SDL_Quit(); - HandleException(CLibException(std::string("Unable to initialize SDL: ") + SDL_GetError()), true); - } - DEBUG_LOG(trace, "Kernel", "Context", "SDL initialized!") - - - // SDL_Image Initialization. - int initted = IMG_Init(imageFlags); - DEBUG_LOG(trace, "Kernel", "Context", "SDL_Image initialization...") - if ((initted & imageFlags) != imageFlags) { - HandleException(CLibException(std::string("Unable to initialize SDL Image: ") + IMG_GetError()), true); - } - DEBUG_LOG(trace, "Kernel", "Context", "SDL_Image initialized!") - - // SDL_TTF Initialization. - DEBUG_LOG(trace, "Kernel", "Context", "SDL_TTF initialization...") - if (TTF_Init() == -1) { - HandleException(CLibException(std::string("Unable to initialize SDL TTF: ") + TTF_GetError()), true); - } - DEBUG_LOG(trace, "Kernel", "Context", "SDL_TTF initialized!") -} - -bool CContext::isScreenSaverEnable(void) { - return m_screenSaver; -} - -void CContext::setScreenSaverEnable(bool newScreenSaver) { - m_screenSaver = newScreenSaver; - if (m_screenSaver) { - SDL_EnableScreenSaver(); - } - else { - SDL_DisableScreenSaver(); - } -} - -void CContext::quit(void) { - TTF_Quit(); - IMG_Quit(); - SDL_Quit(); -} - -void CContext::initLog(void) { - static const std::string COMMON_FMT("[%TimeStamp%][%Severity%]%Message%"); - - boost::log::register_simple_formatter_factory< boost::log::trivial::severity_level, char >("Severity"); - - // Output message to console. - boost::log::add_console_log( - std::cout, - boost::log::keywords::format = COMMON_FMT, - boost::log::keywords::auto_flush = true - ); - - // Output message to file, rotates when file reached 1mb or at midnight every day. Each log file - // is capped at 1mb and total is 50mb. - boost::log::add_file_log( - boost::log::keywords::file_name = LOG_FILE, - boost::log::keywords::rotation_size = LOG_ROTATION_SIZE, - boost::log::keywords::max_size = LOG_MAX_SIZE, - boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0), - boost::log::keywords::format = COMMON_FMT, - boost::log::keywords::auto_flush = true - ); - - boost::log::add_common_attributes(); - - // Only output message with INFO or higher severity in Release. - #ifndef _DEBUG - boost::log::core::get()->set_filter( - boost::log::trivial::severity >= boost::log::trivial::info - ); - #endif -} \ No newline at end of file diff --git a/src/Engine/Core/Context/CContext.hpp b/src/Engine/Core/Context/CContext.hpp deleted file mode 100644 index f953253..0000000 --- a/src/Engine/Core/Context/CContext.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef CCONTEXT_HPP -#define CCONTEXT_HPP - -#include "../Controller/Exception/CLibException.hpp" -#include "../Controller/Exception/CExceptionManager.hpp" - -#define BOOST_LOG_DYN_LINK 1 -#include -#include - -#include -#ifdef WIN32 - #include -#else - #include -#endif -#include -#include - -#ifdef _DEBUG -#define DEBUG_LOG(level, object, component, message) \ - BOOST_LOG_TRIVIAL(level) << "[" << object << "]" << "[" << component << "] : " << message; -#else -#define DEBUG_LOG(level, object, component, message) - -#endif -#define ERROR_LOG(level, object, component, message) \ - BOOST_LOG_TRIVIAL(level) << "[" << object << "]" << "[" << component << "] : " << message; - -#define LOG_FILE "CosmicEngine_%3N.log" -#define LOG_ROTATION_SIZE 1 * 1024 * 1024 -#define LOG_MAX_SIZE 50 * 1024 * 1024 - -/** - * @file CContext.hpp - * @brief File of CContext, a class reprensenting a SDL context, using SDL2 lib. - */ - -/** - * @brief Class reprensenting a SDL context, using SDL2 lib. - */ -class CContext { -private: - // Say if the screenSaver is enabled. - static bool m_screenSaver; - -public: - CContext(void) = delete; - - static void init(unsigned int sdlFlags, unsigned int imageFlags); - - static void quit(void); - /** - * @brief Say if the screen saver is enabled. - * @return bool, a boolean which say the screen saver status. - */ - static bool isScreenSaverEnable(void); - - /** - * @brief Set the screen saver status. - * @param[in] newScreenSaver New value of screen saver status. - */ - static void setScreenSaverEnable(bool newScreenSaver); - -private: - /** - * @brief Init the logging system. - */ - static void initLog(void); -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CGameWindow.hpp b/src/Engine/Core/Context/Window/CGameWindow.hpp deleted file mode 100644 index 8318756..0000000 --- a/src/Engine/Core/Context/Window/CGameWindow.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef CGAMEWINDOW_HPP -#define CGAMEWINDOW_HPP - -#include "CWindow.hpp" -#include "../../Controller/Exception/CLibException.hpp" -#include "../../Controller/Exception/CLogicException.hpp" - -#include -#include -#include -#include -#include -#include -#ifdef WIN32 - #include -#else - #include -#endif - -/** - * @file CGameWindow.hpp - * @brief File of CGameWindow, a class reprensenting a OpenGL Window, using SDL2 lib. - */ - -/** - * @brief Class reprensenting a OpenGL Window, using SDL2 lib. - */ -class CGameWindow : public CWindow { -private: - // Say if the mouse is grabbed. - bool m_grabCursor; - - // Say if the mouse is in relative mode. - bool m_relativeCursor; - - // The anti-aliasing. - unsigned char m_msaa; - -public: - CGameWindow(void) = delete; - CGameWindow(const CGameWindow& param) = delete; - CGameWindow& operator=(const CGameWindow& param) = delete; - - /** - * @brief The default constructor, build a non visible window with size of widthxheight. - * @param[in] title The title of the window. - * @param[in] iconPath The iconPath of the window. - * @param[in] width The width of the window. - * @param[in] height The height of the window. - * @param[in] resizable The define the resizable property of the window. - * @param[in] fullscreen The define the fullscreen property of the window. - * @param[in] sdlFlags Allow to add SDL flags. - * @param[in] imageFlags Allow to add SDL_Image flags. - */ - CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen); - - CGameWindow(std::string title, SDL_Window* window); - - /** - * @brief The destructor. - */ - ~CGameWindow(void); - - /** - * @brief Say if the mouse is grabbed. - * @return bool, a boolean which say the mouse grab status. - */ - bool isCursorGrabbed(void) const; - - /** - * @brief Set the mouse grab status. - * @param[in] newMouseGrab New value of mouse grab status. - */ - void setCursorGrabbed(bool newMouseGrab); - - /** - * @brief Say if the mouse is relative. - * @return bool, a boolean which say the mouse relative status. - */ - bool isCursorRelative(void) const; - - /** - * @brief Set the mouse relative status, if true, the cursor grabb is also forced to true if not. - * @param[in] newMouseRelative New value of mouse relative status. - */ - void setCursorRelative(bool newMouseRelative); - - /** - * @brief Get the MSAA value. - * @return unsigned char, the MSAA value. - */ - unsigned char getAntiAliasing(void) const; - - /** - * @brief Set the MSAA of the window. - * @param[in] newMsaa New value of MSAA, must be 2, 4, 8, 16. - * @post if newMsaa not equal 2, 4, 8, 16, the value is set to 0. - */ - void setAntiAliasing(unsigned char newMsaa); - - /** - * @brief Launched before the creation of the window, usefull for setting OpenGL attribute. - */ - virtual void preinitialization(); - - /** - * @brief Launched after the creation of the window, usefull for setting others attribute. - */ - virtual void postinitialization(); - - /** - * @brief Get the OpenGLContext of the window. - * @return SDL_GLContext the OpenGL context of the window, in SDL2 format, we need to destroy it after using, with SDL_GL_DeleteContext(SDL_GLContext);. - * @post Give a error if the window is not initialized. - */ - SDL_GLContext getOpenGLContext(void); -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CWindow.hpp b/src/Engine/Core/Context/Window/CWindow.hpp deleted file mode 100644 index 2b8cc75..0000000 --- a/src/Engine/Core/Context/Window/CWindow.hpp +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef CWINDOW_HPP -#define CWINDOW_HPP - -#include "../../Controller/Exception/CLibException.hpp" -#include "../../Controller/Exception/CLogicException.hpp" - -#include -#include -#include -#include -#include -#include -#ifdef WIN32 - #include -#else - #include -#endif - -/** - * @file CWindow.hpp - * @brief File of CWindow, a class reprensenting a Window, using SDL2 lib. - */ - -/** - * @brief Class reprensenting a Window, using SDL2 lib. - */ -class CWindow { -private: - // The title of the window. - std::string m_title; - - // The path to the icon. - std::string m_iconPath; - - // First is the width, second is the height. - std::pair m_size; - - // Say if the window is fullscreen. - bool m_fullscreen; - - // Say if the window is visible. - bool m_visible; - - // Say if the window is resizable. - bool m_resizable; - - // SDL flags for creating the window. - unsigned int m_sdlFlags; - - // The pointer to the window. - SDL_Window* m_pwindow; - -public: - CWindow(void) = delete; - CWindow(const CWindow& param) = delete; - CWindow& operator=(const CWindow& param) = delete; - - /** - * @brief The default constructor, build a non visible window with size of widthxheight. - * @param[in] title The title of the window. - * @param[in] iconPath The iconPath of the window. - * @param[in] width The width of the window. - * @param[in] height The height of the window. - * @param[in] sdlFlags Allow to add SDL flags. - */ - CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, unsigned int sdlFlags); - - /** - * @brief The default constructor, build a non visible window with size of widthxheight. - * @param[in] title The title of the window. - * @param[in] The window to embed the game in. - * @param[in] sdlFlags Allow to add SDL flags. - * @param[in] imageFlags Allow to add SDL_Image flags. - */ - CWindow(std::string title, SDL_Window* window, unsigned int sdlFlags, unsigned int imageFlags); - - - /** - * @brief The destructor. - */ - ~CWindow(void); - - /** - * @brief Get the SDL_Window* of the window. - * @return SDL_Window The window, in SDL2 format. - */ - SDL_Window* getWindow(void); - - void setWindow(SDL_Window* window){m_pwindow = window; }; - /** - * @brief Say if the window is fullscreen. - * @return bool, a boolean which say the fullscreen status. - */ - bool isFullscreen(void) const; - - /** - * @brief Set the fullscreen status. - * @param[in] newFullscreen New value of fullscreen status. - */ - void setFullscreen(bool newFullscreen); - - /** - * @brief Say if the window is visible. - * @return bool, a boolean which say the visible status. - */ - bool isVisible(void) const; - - /** - * @brief Set the visibility status. - * @param[in] newVisible New value of visibility status. - */ - void setVisible(bool newVisible); - - /** - * @brief Get the window icon path. - * @return std::string, the path. - */ - std::string getIconPath(void) const; - - /** - * @brief Get the window title. - * @return std::string, the title. - */ - std::string getTitle(void) const; - - /** - * @brief Change the window title. - * @param[in] newTitle New title of the window. - */ - void setTitle(std::string newTitle); - - /** - * @brief Change the window icon. - * @param[in] newIconPath New icon path of the window. - */ - void setIconPath(std::string newIconPath); - - /** - * @brief Get the window width. - * @return unsigned int, the window width (in pixel). - */ - unsigned int getWidth(void) const; - - /** - * @brief Get the window height. - * @return unsigned int, the window height (in pixel). - */ - unsigned int getHeight(void) const; - - /** - * @brief Get the window size. - * @return std::pair, the window size (in pixel). - */ - std::pair getSize(void) const; - - /** - * @brief Set the window size. - * @param[in] newSize New value of window size. - */ - void setSize(std::pair newSize); - - /** - * @brief Set the window size. - * @param[in] newWidth New value of window width. - * @param[in] newHeight New value of window height. - */ - void setSize(unsigned int newWidth, unsigned int newHeight); - - /** - * @brief Say if the window is resizable. - * @return bool, a boolean which say the resizable status. - */ - bool isResizable(void) const; - - /** - * @brief Set the rezisable status. - * @param[in] newResizable New value of rezisable status. - */ - void setResizable(bool newResizable); - - /** - * @brief Say if the window is initialized. - * @return bool, a boolean which say the initialization status. - */ - bool isInitialized(void) const; - - /** - * @brief Initialize the window. - * @post Give a error if the windows is already init. - */ - void initialization(); - - /** - * @brief Launched before the creation of the window, usefull for setting OpenGL attribute. - */ - virtual void preinitialization() = 0; - - /** - * @brief Launched after the creation of the window, usefull for setting others attribute. - */ - virtual void postinitialization() = 0; -}; - -#endif \ No newline at end of file diff --git a/src/Engine/Core/Entity/CEntity.cpp b/src/Engine/Core/Entity/CEntity.cpp index c42a7aa..e59ac82 100644 --- a/src/Engine/Core/Entity/CEntity.cpp +++ b/src/Engine/Core/Entity/CEntity.cpp @@ -6,20 +6,20 @@ namespace CosmicCore { - CEntity::CEntity(ECManager& registry, EntityId handle) : CSerializable(), m_registryReference(registry), m_handle(handle) + CEntity::CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene) : CSerializable(), m_scene(scene), m_registryReference(registry), m_handle(handle) { } - CEntity::CEntity(const CEntity& cop): m_registryReference(cop.m_registryReference), m_handle(cop.m_handle){ + CEntity::CEntity(const CEntity& cop): m_scene(cop.m_scene), m_registryReference(cop.m_registryReference), m_handle(cop.m_handle){ } - std::weak_ptr CEntity::getScene() + CScene* CEntity::getScene() { return m_scene; } - void CEntity::setScene(std::weak_ptr s) + void CEntity::setScene(CScene* s) { m_scene = s; } diff --git a/src/Engine/Core/Entity/CEntity.hpp b/src/Engine/Core/Entity/CEntity.hpp index 31c1d88..3f8429b 100644 --- a/src/Engine/Core/Entity/CEntity.hpp +++ b/src/Engine/Core/Entity/CEntity.hpp @@ -4,24 +4,22 @@ #include #include #include "../Utils/CSerializable.hpp" -#include +#include "../Systems/EntityComponentManager.hpp" namespace CosmicCore { class CScene; class CEntity : public CSerializable { - using ECManager = entt::registry; - using EntityId = entt::entity; private: /** * @brief A pointer to the scene containing the entity. */ - std::weak_ptr m_scene; + CScene* m_scene; - ECManager& m_registryReference; + EntityComponentManager& m_registryReference; EntityId m_handle; @@ -32,7 +30,7 @@ namespace CosmicCore */ CEntity() = delete; - CEntity(ECManager& registry, EntityId handle); + CEntity(EntityComponentManager& registry, EntityId handle, CScene* scene); CEntity(const CEntity& cop); /** @@ -49,26 +47,34 @@ namespace CosmicCore template void addComponent(std::forward_list args) { - m_registryReference.emplace(m_handle, *this, args); + m_registryReference().emplace(m_handle, *this, args); } template void addComponent() { - m_registryReference.emplace(m_handle, *this); + m_registryReference().emplace(m_handle, *this); } + EntityComponentManager& getRegistry(){return m_registryReference;}; + /** * @brief Getter to the entity's scene. * @return The pointer m_scene. */ - std::weak_ptr getScene(); + CScene* getScene(); /** * @brief Setter of the scene. * @param[in, out] e The scene in which the entity will be set. */ - void setScene(std::weak_ptr s); + void setScene(CScene* s); + + EntityId operator*(){ + return m_handle; + } + + //TODO GET COMPONENT VECTOR OF SPECIFIC TYPE ? si utile nlohmann::json to_json(); }; diff --git a/src/Engine/Core/Exception/CException.cpp b/src/Engine/Core/Exception/CException.cpp index 2793a58..929c63b 100644 --- a/src/Engine/Core/Exception/CException.cpp +++ b/src/Engine/Core/Exception/CException.cpp @@ -1,7 +1,7 @@ #include "CException.hpp" void CException::makeFullMessage(void) { - std::stringstream sstring; + /*std::stringstream sstring; sstring << "Error : " << m_code << std::endl << m_message << std::endl; boost::stacktrace::stacktrace stacktrace = boost::stacktrace::stacktrace(); std::size_t frames = stacktrace.size(); @@ -17,7 +17,7 @@ void CException::makeFullMessage(void) { sstring << " (" << stacktrace[i].address() << ')' << std::endl; } - m_fullMessage = sstring.str(); + m_fullMessage = sstring.str();*/ } CException::CException(void) noexcept : diff --git a/src/Engine/Core/Exception/CException.hpp b/src/Engine/Core/Exception/CException.hpp index ac89025..6d77859 100644 --- a/src/Engine/Core/Exception/CException.hpp +++ b/src/Engine/Core/Exception/CException.hpp @@ -3,8 +3,6 @@ #include #include -#include -#include /** * @file CException.hpp diff --git a/src/Engine/Core/Exception/CExceptionManager.cpp b/src/Engine/Core/Exception/CExceptionManager.cpp index b446020..00a7770 100644 --- a/src/Engine/Core/Exception/CExceptionManager.cpp +++ b/src/Engine/Core/Exception/CExceptionManager.cpp @@ -1,6 +1,6 @@ #include "CExceptionManager.hpp" -void HandleException(const CException& e, bool fatal) { +/*void HandleException(const CException& e, bool fatal) { std::string windowMessage(e.getMessage()); windowMessage += "\nException reported in \""; @@ -31,4 +31,4 @@ void HandleException(const CException& e, bool fatal) { // It's fatal, so we quit. exit(EXIT_FAILURE); } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Core/Exception/CExceptionManager.hpp b/src/Engine/Core/Exception/CExceptionManager.hpp index b6306f7..db62298 100644 --- a/src/Engine/Core/Exception/CExceptionManager.hpp +++ b/src/Engine/Core/Exception/CExceptionManager.hpp @@ -2,10 +2,6 @@ #define CEXCEPTIONMANAGER_HPP #include "CException.hpp" -#include "../File/CFileManager.hpp" - -#include -#include /** * @file CExceptionManager.hpp diff --git a/src/Engine/Core/Graphics/API/Constants.hpp b/src/Engine/Core/Graphics/API/Constants.hpp new file mode 100644 index 0000000..085e987 --- /dev/null +++ b/src/Engine/Core/Graphics/API/Constants.hpp @@ -0,0 +1 @@ +#define MAX_FRAMES_IN_FLIGHT 2 \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/DeletionQueue.hpp b/src/Engine/Core/Graphics/API/DeletionQueue.hpp new file mode 100644 index 0000000..4daa1f3 --- /dev/null +++ b/src/Engine/Core/Graphics/API/DeletionQueue.hpp @@ -0,0 +1,54 @@ +#ifndef DELETIONQUEUE_HPP +#define DELETIONQUEUE_HPP + +#include +#include +#include +#include +#include "Constants.hpp" + +class DeletionQueue { +private: + // une queue par frame + une queue immédiate + std::array>, MAX_FRAMES_IN_FLIGHT> m_frameQueues; + std::deque> m_immediateQueue; + +public: + // destruction différée - attendre MAX_FRAMES_IN_FLIGHT frames + void push(uint32_t currentFrame, std::function&& func) { + // on enfile dans la frame "opposée" pour attendre un cycle complet + uint32_t targetFrame = (currentFrame + MAX_FRAMES_IN_FLIGHT - 1) % MAX_FRAMES_IN_FLIGHT; + m_frameQueues[targetFrame].push_back(std::move(func)); + } + + // destruction immédiate - device.waitIdle() doit avoir été appelé avant + void pushImmediate(std::function&& func) { + m_immediateQueue.push_back(std::move(func)); + } + + // appelé au début de chaque frame - détruit les ressources de cette frame + void flush(uint32_t frameIndex) { + auto& queue = m_frameQueues[frameIndex]; + while (!queue.empty()) { + queue.front()(); + queue.pop_front(); + } + } + + // appelé à la fermeture - détruit tout + void flushAll() { + // vider toutes les frame queues + for (auto& queue : m_frameQueues) { + while (!queue.empty()) { + queue.front()(); + queue.pop_front(); + } + } + // vider la queue immédiate + while (!m_immediateQueue.empty()) { + m_immediateQueue.front()(); + m_immediateQueue.pop_front(); + } + } +}; +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/GraphicsAPI.cpp b/src/Engine/Core/Graphics/API/GraphicsAPI.cpp new file mode 100644 index 0000000..00c5e0f --- /dev/null +++ b/src/Engine/Core/Graphics/API/GraphicsAPI.cpp @@ -0,0 +1,10 @@ +#include "GraphicsAPI.hpp" +#include "VulkanImpl.hpp" +#include + +std::unique_ptr GraphicsAPI::impl = nullptr; + +void GraphicsAPI::initAPI(){ + //todo check config for chosen api + impl = std::make_unique(); +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/GraphicsAPI.hpp b/src/Engine/Core/Graphics/API/GraphicsAPI.hpp new file mode 100644 index 0000000..2d7741c --- /dev/null +++ b/src/Engine/Core/Graphics/API/GraphicsAPI.hpp @@ -0,0 +1,33 @@ +#ifndef GRAPHICAPI_HPP +#define GRAPHICAPI_HPP + +#include +#include +#include "../Shader/CShadersManager.hpp" +#include "../Data/CResourceManager.hpp" + +enum class GraphicsBackend{ + Vulkan, + OpenGL, + Metal +}; + +class GraphicsAPI{ + static std::unique_ptr impl; + protected: + CShadersManager shadermanager; + CResourceManager resourceManager; + public: + static void initAPI(); + static std::unique_ptr& getAPI(){return impl;}; + virtual void init(SDL_Window* window) = 0; + virtual void cleanup() = 0; + virtual ~GraphicsAPI(){}; + virtual void* getDevice() = 0; + virtual void drawFrame() = 0; + CShadersManager& getShaderManager(){return shadermanager;}; + CResourceManager& getResourceManager(){return resourceManager;}; + +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/ManagedDescriptorSet.hpp b/src/Engine/Core/Graphics/API/ManagedDescriptorSet.hpp new file mode 100644 index 0000000..ec4ed0b --- /dev/null +++ b/src/Engine/Core/Graphics/API/ManagedDescriptorSet.hpp @@ -0,0 +1,21 @@ +#ifndef MANAGEDDESCRIPTORSET_HPP +#define MANAGEDDESCRIPTORSET_HPP + +#include +#include + +#define MAX_FRAMES_IN_FLIGHT 2 + +struct ManagedDescriptorSet { + vk::raii::DescriptorSet set = nullptr; + VkDescriptorPool ownerPool = VK_NULL_HANDLE; + + ManagedDescriptorSet() = default; + ManagedDescriptorSet(ManagedDescriptorSet&&) = default; + ManagedDescriptorSet& operator=(ManagedDescriptorSet&&) = default; + + ManagedDescriptorSet(const ManagedDescriptorSet&) = delete; + ManagedDescriptorSet& operator=(const ManagedDescriptorSet&) = delete; +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/VMABuffer.hpp b/src/Engine/Core/Graphics/API/VMABuffer.hpp new file mode 100644 index 0000000..6bce8f1 --- /dev/null +++ b/src/Engine/Core/Graphics/API/VMABuffer.hpp @@ -0,0 +1,15 @@ +#ifndef VMABUFFER_HPP +#define VMABUFFER_HPP + +#include "vk_mem_alloc.h" + +typedef struct vmaBufferStruct { + VkBuffer buffer = VK_NULL_HANDLE; + VmaAllocation allocation = VK_NULL_HANDLE; + + void destroy(VmaAllocator allocator) { + vmaDestroyBuffer(allocator, buffer, allocation); + } +}VMABuffer; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/VMAUsage.cpp b/src/Engine/Core/Graphics/API/VMAUsage.cpp new file mode 100644 index 0000000..00317e0 --- /dev/null +++ b/src/Engine/Core/Graphics/API/VMAUsage.cpp @@ -0,0 +1,2 @@ +#define VMA_IMPLEMENTATION +#include "vk_mem_alloc.h" \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/VulkanImpl.cpp b/src/Engine/Core/Graphics/API/VulkanImpl.cpp new file mode 100644 index 0000000..6eb5367 --- /dev/null +++ b/src/Engine/Core/Graphics/API/VulkanImpl.cpp @@ -0,0 +1,789 @@ +#include "VulkanImpl.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../Kernel/CKernel.hpp" +#include "DeletionQueue.hpp" +#include "vulkan/vulkan.hpp" +static uint32_t chooseSwapMinImageCount(vk::SurfaceCapabilitiesKHR const &surfaceCapabilities) +{ + auto minImageCount = std::max(3u, surfaceCapabilities.minImageCount); + if ((0 < surfaceCapabilities.maxImageCount) && (surfaceCapabilities.maxImageCount < minImageCount)) + { + minImageCount = surfaceCapabilities.maxImageCount; + } + return minImageCount; +} + +static vk::SurfaceFormatKHR chooseSwapSurfaceFormat(std::vector const &availableFormats) +{ + assert(!availableFormats.empty()); + const auto formatIt = std::ranges::find_if( + availableFormats, + [](const auto &format) { return format.format == vk::Format::eB8G8R8A8Srgb && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear; }); + return formatIt != availableFormats.end() ? *formatIt : availableFormats[0]; +} + +static vk::PresentModeKHR chooseSwapPresentMode(const std::vector &availablePresentModes) +{ + assert(std::ranges::any_of(availablePresentModes, [](auto presentMode) { return presentMode == vk::PresentModeKHR::eFifo; })); + return std::ranges::any_of(availablePresentModes, + [](const vk::PresentModeKHR value) { return vk::PresentModeKHR::eMailbox == value; }) ? + vk::PresentModeKHR::eMailbox : + vk::PresentModeKHR::eFifo; +} + +vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR &capabilities, SDL_Window* window) +{ + if (capabilities.currentExtent.width != 0xFFFFFFFF) + { + return capabilities.currentExtent; + } + int width, height; + SDL_GetWindowSizeInPixels(window, &width, &height); + + return { + std::clamp(width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width), + std::clamp(height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height)}; +} + +void VulkanImpl::init(SDL_Window* window){ + m_window = window; + createInstance(); + createSurface(); + pickPhysicalDevice(); + createLogicalDevice(); + //getShaders after creating device + shadermanager.create(); + shadermanager.compile(); + createSwapChain(); + createImageViews(); + createDescriptorSetLayouts(); + //createGraphicsPipeline(); + createDepthResources(); + createCommandPool(); + createDescriptorPool(); + createDefaultTexture(); + createCommandBuffer(); + createSyncObjects(); +} + +void VulkanImpl::cleanup(){ + device.waitIdle(); + // 1. détruire les ressources dans le ResourceManager + // (buffers, pipelines, descriptor sets...) + m_deletionQueue.flushAll(); + + CosmicCore::CKernel::m_kernel->cleanup(); + + resourceManager.cleanup(); + shadermanager.cleanup(); + + + m_deletionQueue.flushAll(); + + // 2. sync objects + inFlightFences.clear(); + renderFinishedSemaphores.clear(); + presentCompleteSemaphores.clear(); + + // 3. command buffers puis command pool + commandBuffers.clear(); + commandPool = nullptr; + + // 4. swapchain + cleanupSwapChain(); + + // descriptor set layouts + pipeline layout avant le device + defaultPipelineLayoutInfo = nullptr; + cameraLayout = nullptr; + transformLayout = nullptr; + materialLayout = nullptr; + + VmaTotalStatistics stats; + vmaCalculateStatistics(allocator, &stats); + if (stats.total.statistics.allocationCount > 0) { + std::cout << "VMA: " << stats.total.statistics.allocationCount + << " allocations non libérées !" << std::endl; + std::cout << "VMA: " << stats.total.statistics.allocationBytes + << " bytes non libérés" << std::endl; + } + + //Vulkan memory allocator + vmaDestroyAllocator(allocator); + + // 5. surface + surface = nullptr; + + // 6. device en avant-dernier + device = nullptr; + + // 7. instance en dernier + instance = nullptr; +} + +void VulkanImpl::createInstance(){ + constexpr vk::ApplicationInfo appInfo{ "CosmicEngine", + VK_MAKE_VERSION( 1, 0, 0 ), + "No Engine", + VK_MAKE_VERSION( 1, 0, 0 ), + vk::ApiVersion13}; + + uint32_t sdl_extensions_count = 0; + const char* const* sdl_extensions = SDL_Vulkan_GetInstanceExtensions(&sdl_extensions_count); + + auto extensionProp = context.enumerateInstanceExtensionProperties(); + for (uint32_t i = 0; i < sdl_extensions_count; ++i) + { + if (std::ranges::none_of(extensionProp, + [sdlExtension = sdl_extensions[i]](auto const& extensionProperty) + { return strcmp(extensionProperty.extensionName, sdlExtension) == 0; })) + { + throw std::runtime_error("Required SDL extension not supported: " + std::string(sdl_extensions[i])); + } + } + + // Get the required layers + std::vector requiredLayers; + if (enableValidationLayers) + { + requiredLayers.assign(validationLayers.begin(), validationLayers.end()); + } + + // Check if the required layers are supported by the Vulkan implementation. + auto layerProperties = context.enumerateInstanceLayerProperties(); + auto unsupportedLayerIt = std::ranges::find_if(requiredLayers, + [&layerProperties](auto const &requiredLayer) { + return std::ranges::none_of(layerProperties, + [requiredLayer](auto const &layerProperty) { return strcmp(layerProperty.layerName, requiredLayer) == 0; }); + }); + if (unsupportedLayerIt != requiredLayers.end()) + { + throw std::runtime_error("Required layer not supported: " + std::string(*unsupportedLayerIt)); + } + + vk::InstanceCreateInfo createInfo{{},&appInfo, static_cast(requiredLayers.size()), requiredLayers.data(), sdl_extensions_count, sdl_extensions}; + + + instance = vk::raii::Instance(context, createInfo); +} + +void VulkanImpl::pickPhysicalDevice() +{ + std::vector devices = instance.enumeratePhysicalDevices(); + const auto devIter = std::ranges::find_if( + devices, + [&](auto const &device) { + // Check if the device supports the Vulkan 1.3 API version + bool supportsVulkan1_3 = device.getProperties().apiVersion >= VK_API_VERSION_1_3; + + // Check if any of the queue families support graphics operations + auto queueFamilies = device.getQueueFamilyProperties(); + bool supportsGraphics = + std::ranges::any_of(queueFamilies, [](auto const &qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); }); + + // Check if all required device extensions are available + auto availableDeviceExtensions = device.enumerateDeviceExtensionProperties(); + bool supportsAllRequiredExtensions = + std::ranges::all_of(requiredDeviceExtension, + [&availableDeviceExtensions](auto const &requiredDeviceExtension) { + return std::ranges::any_of(availableDeviceExtensions, + [requiredDeviceExtension](auto const &availableDeviceExtension) { return strcmp(availableDeviceExtension.extensionName, requiredDeviceExtension) == 0; }); + }); + + auto features = device.template getFeatures2(); + bool supportsRequiredFeatures = features.template get().dynamicRendering && + features.template get().extendedDynamicState; + + return supportsVulkan1_3 && supportsGraphics && supportsAllRequiredExtensions && supportsRequiredFeatures; + }); + if (devIter != devices.end()) + { + physicalDevice = *devIter; + } + else + { + throw std::runtime_error("failed to find a suitable GPU!"); + } +} + +void VulkanImpl::createLogicalDevice() +{ + // find the index of the first queue family that supports graphics + std::vector queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); + + // get the first index into queueFamilyProperties which supports graphics + auto graphicsQueueFamilyProperty = std::ranges::find_if(queueFamilyProperties, [](auto const &qfp) { return (qfp.queueFlags & vk::QueueFlagBits::eGraphics) != static_cast(0); }); + assert(graphicsQueueFamilyProperty != queueFamilyProperties.end() && "No graphics queue family found!"); + + auto graphicsIndex = static_cast(std::distance(queueFamilyProperties.begin(), graphicsQueueFamilyProperty)); + + // determine a queueFamilyIndex that supports present + // first check if the graphicsIndex is good enough + auto presentIndex = physicalDevice.getSurfaceSupportKHR( graphicsIndex, *surface ) + ? graphicsIndex + : static_cast( queueFamilyProperties.size() ); + if ( presentIndex == queueFamilyProperties.size() ) + { + // the graphicsIndex doesn't support present -> look for another family index that supports both + // graphics and present + for ( size_t i = 0; i < queueFamilyProperties.size(); i++ ) + { + if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) && + physicalDevice.getSurfaceSupportKHR( static_cast( i ), *surface ) ) + { + graphicsIndex = static_cast( i ); + presentIndex = graphicsIndex; + queueIndex = graphicsIndex; + break; + } + } + if ( presentIndex == queueFamilyProperties.size() ) + { + // there's nothing like a single family index that supports both graphics and present -> look for another + // family index that supports present + for ( size_t i = 0; i < queueFamilyProperties.size(); i++ ) + { + if ( physicalDevice.getSurfaceSupportKHR( static_cast( i ), *surface ) ) + { + presentIndex = static_cast( i ); + break; + } + } + } + } + if ( ( graphicsIndex == queueFamilyProperties.size() ) || ( presentIndex == queueFamilyProperties.size() ) ) + { + throw std::runtime_error( "Could not find a queue for graphics or present -> terminating" ); + } + + queueIndex = graphicsIndex; + + // query for Vulkan 1.3 features + + auto features = physicalDevice.getFeatures2(); + vk::PhysicalDeviceVulkan11Features vulkan11Features; + vulkan11Features.shaderDrawParameters = vk::True; + + vk::PhysicalDeviceVulkan13Features vulkan13Features; + vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT extendedDynamicStateFeatures; + vulkan13Features.dynamicRendering = vk::True; + vulkan13Features.synchronization2 = vk::True; + extendedDynamicStateFeatures.extendedDynamicState = vk::True; + vulkan11Features.pNext = &vulkan13Features; + vulkan13Features.pNext = &extendedDynamicStateFeatures; + features.pNext = &vulkan11Features; + + // create a Device + float queuePriority = 0.5f; + vk::DeviceQueueCreateInfo deviceQueueCreateInfo{{}, + graphicsIndex, + 1, + &queuePriority}; + + vk::DeviceCreateInfo deviceCreateInfo{{}, + 1, + &deviceQueueCreateInfo, + {}, + {}, + static_cast(requiredDeviceExtension.size()), + requiredDeviceExtension.data(), + {}, + &features + }; + + + device = vk::raii::Device(physicalDevice, deviceCreateInfo); + graphicsQueue = vk::raii::Queue(device, graphicsIndex, 0); + presentQueue = vk::raii::Queue( device, presentIndex, 0 ); + + VmaAllocatorCreateInfo allocatorInfo{}; + allocatorInfo.physicalDevice = *physicalDevice; + allocatorInfo.device = *device; + allocatorInfo.instance = *instance; + allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_3; + vmaCreateAllocator(&allocatorInfo, &allocator); +} + +void VulkanImpl::createSurface() +{ + VkSurfaceKHR _surface; + if (!SDL_Vulkan_CreateSurface(m_window, *instance, nullptr, &_surface)) { + throw std::runtime_error("failed to create window surface!"); + } + surface = vk::raii::SurfaceKHR(instance, _surface); +} + +void VulkanImpl::createSwapChain() +{ + auto surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface); + swapChainExtent = chooseSwapExtent(surfaceCapabilities, m_window); + swapChainSurfaceFormat = chooseSwapSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(*surface)); + vk::SwapchainCreateInfoKHR swapChainCreateInfo{ {}, + *surface, + chooseSwapMinImageCount(surfaceCapabilities), + swapChainSurfaceFormat.format, + swapChainSurfaceFormat.colorSpace, + swapChainExtent, + 1, + vk::ImageUsageFlagBits::eColorAttachment, + vk::SharingMode::eExclusive, + {}, + surfaceCapabilities.currentTransform, + vk::CompositeAlphaFlagBitsKHR::eOpaque, + chooseSwapPresentMode(physicalDevice.getSurfacePresentModesKHR(*surface)), + true}; + + swapChain = vk::raii::SwapchainKHR(device, swapChainCreateInfo); + + swapChainImages = swapChain.getImages(); +} + +void VulkanImpl::createImageViews() +{ + vk::ImageViewCreateInfo imageViewCreateInfo{ + {}, + {}, + vk::ImageViewType::e2D, + swapChainSurfaceFormat.format, + {}, + {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1} + }; + for (auto& image : swapChainImages) + { + imageViewCreateInfo.image = image; + swapChainImageViews.emplace_back(device, imageViewCreateInfo); + } +} + +vk::raii::ImageView VulkanImpl::createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags) +{ + vk::ImageViewCreateInfo imageViewCreateInfo{ + {}, + image, + vk::ImageViewType::e2D, + format, + {}, + {aspectFlags, 0, 1, 0, 1} + }; + return vk::raii::ImageView(device, imageViewCreateInfo); +} + +void VulkanImpl::createCommandPool() +{ + vk::CommandPoolCreateInfo poolInfo{vk::CommandPoolCreateFlagBits::eResetCommandBuffer, queueIndex}; + commandPool = vk::raii::CommandPool(device, poolInfo); +} + +void VulkanImpl::createCommandBuffer() +{ + vk::CommandBufferAllocateInfo allocInfo{commandPool, vk::CommandBufferLevel::ePrimary, MAX_FRAMES_IN_FLIGHT}; + commandBuffers = vk::raii::CommandBuffers(device, allocInfo); +} + + +void VulkanImpl::recordCommandBuffer(uint32_t imageIndex) +{ + auto &commandBuffer = commandBuffers[frameIndex]; + commandBuffer.begin({}); + // Before starting rendering, transition the swapchain image to COLOR_ATTACHMENT_OPTIMAL + transitionImageLayout( + swapChainImages[imageIndex], + vk::ImageLayout::eUndefined, + vk::ImageLayout::eColorAttachmentOptimal, + {}, // srcAccessMask (no need to wait for previous operations) + vk::AccessFlagBits2::eColorAttachmentWrite, // dstAccessMask + vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage + vk::PipelineStageFlagBits2::eColorAttachmentOutput, // dstStage + vk::ImageAspectFlagBits::eColor + ); + + // Transition depth image to depth attachment optimal layout + transitionImageLayout( + depthImage, + vk::ImageLayout::eUndefined, + vk::ImageLayout::eDepthAttachmentOptimal, + vk::AccessFlagBits2::eDepthStencilAttachmentWrite, + vk::AccessFlagBits2::eDepthStencilAttachmentWrite, + vk::PipelineStageFlagBits2::eEarlyFragmentTests | vk::PipelineStageFlagBits2::eLateFragmentTests, + vk::PipelineStageFlagBits2::eEarlyFragmentTests | vk::PipelineStageFlagBits2::eLateFragmentTests, + vk::ImageAspectFlagBits::eDepth); + + vk::ClearValue clearColor = vk::ClearColorValue(0.0f, 0.0f, 0.0f, 1.0f); + vk::ClearValue clearDepth = vk::ClearDepthStencilValue(1.0f, 0); + //color + vk::RenderingAttachmentInfo attachmentInfo = { + swapChainImageViews[imageIndex], + vk::ImageLayout::eColorAttachmentOptimal, + {}, + {}, + {}, + vk::AttachmentLoadOp::eClear, + vk::AttachmentStoreOp::eStore, + clearColor + }; + //depth + vk::RenderingAttachmentInfo depthAttachmentInfo = { + depthImageView, + vk::ImageLayout::eDepthAttachmentOptimal, + {}, + {}, + {}, + vk::AttachmentLoadOp::eClear, + vk::AttachmentStoreOp::eDontCare, + clearDepth}; + + vk::RenderingInfo renderingInfo = {{},{{0, 0}, swapChainExtent}, + 1, + {}, + 1, + &attachmentInfo, + &depthAttachmentInfo}; + + commandBuffer.beginRendering(renderingInfo); + + commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast(swapChainExtent.width), static_cast(swapChainExtent.height), 0.0f, 1.0f)); + commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent)); + + CosmicCore::CKernel::m_kernel->getActiveScene()->render(commandBuffer, frameIndex); + + commandBuffer.endRendering(); + // After rendering, transition the swapchain image to PRESENT_SRC + transitionImageLayout( + swapChainImages[imageIndex], + vk::ImageLayout::eColorAttachmentOptimal, + vk::ImageLayout::ePresentSrcKHR, + vk::AccessFlagBits2::eColorAttachmentWrite, // srcAccessMask + {}, // dstAccessMask + vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage + vk::PipelineStageFlagBits2::eBottomOfPipe, // dstStage + vk::ImageAspectFlagBits::eColor + ); + commandBuffer.end(); +} + +void VulkanImpl::transitionImageLayout( + vk::Image image, + vk::ImageLayout old_layout, + vk::ImageLayout new_layout, + vk::AccessFlags2 src_access_mask, + vk::AccessFlags2 dst_access_mask, + vk::PipelineStageFlags2 src_stage_mask, + vk::PipelineStageFlags2 dst_stage_mask, vk::ImageAspectFlags image_aspect_flags) +{ + + vk::ImageMemoryBarrier2 barrier = {src_stage_mask, src_access_mask, dst_stage_mask, dst_access_mask, old_layout, new_layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, image, {image_aspect_flags,0,1,0,1}}; + vk::DependencyInfo dependency_info = {{},{},{},{}, {}, 1,&barrier}; + commandBuffers[frameIndex].pipelineBarrier2(dependency_info); +} + +void VulkanImpl::createSyncObjects() +{ + for (size_t i = 0; i < swapChainImages.size(); i++) + { + renderFinishedSemaphores.emplace_back(device, vk::SemaphoreCreateInfo()); + } + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + presentCompleteSemaphores.emplace_back(device, vk::SemaphoreCreateInfo()); + inFlightFences.emplace_back(device, vk::FenceCreateInfo{vk::FenceCreateFlagBits::eSignaled}); + } +} + +void VulkanImpl::drawFrame() +{ + auto fenceResult = device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX); + m_deletionQueue.flush(frameIndex); // détruit les ressources de cette frame + if (fenceResult != vk::Result::eSuccess) + { + throw std::runtime_error("failed to wait for fence!"); + } + device.resetFences(*inFlightFences[frameIndex]); + + auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr); + commandBuffers[frameIndex].reset(); + recordCommandBuffer(imageIndex); + + vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); + const vk::SubmitInfo submitInfo{1, &*presentCompleteSemaphores[frameIndex], &waitDestinationStageMask, 1, &*commandBuffers[frameIndex], 1, &*renderFinishedSemaphores[imageIndex]}; + presentQueue.submit(submitInfo, *inFlightFences[frameIndex]); + + const vk::PresentInfoKHR presentInfoKHR{1, &*renderFinishedSemaphores[imageIndex], 1, &*swapChain, &imageIndex}; + result = presentQueue.presentKHR(presentInfoKHR); + // Due to VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS being defined, eErrorOutOfDateKHR can be checked as a result + // here and does not need to be caught by an exception. + if ((result == vk::Result::eSuboptimalKHR) || (result == vk::Result::eErrorOutOfDateKHR) || framebufferResized) + { + framebufferResized = false; + recreateSwapChain(); + } + else + { + // There are no other success codes than eSuccess; on any error code, presentKHR already threw an exception. + assert(result == vk::Result::eSuccess); + } + frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT; +} + +void VulkanImpl::cleanupSwapChain() +{ + depthImageView = nullptr; + depthImage = nullptr; + depthImageMemory = nullptr; + + swapChainImageViews.clear(); + swapChain = nullptr; + swapChainImages.clear(); +} + +void VulkanImpl::recreateSwapChain() +{ + int width = 0, height = 0; + SDL_GetWindowSizeInPixels(m_window, &width, &height); + while (width == 0 || height == 0) { + SDL_GetWindowSizeInPixels(m_window, &width, &height); + SDL_WaitEvent(nullptr); + } + + device.waitIdle(); + + cleanupSwapChain(); + createSwapChain(); + createImageViews(); + createDepthResources(); +} + +uint32_t VulkanImpl::findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties) +{ + vk::PhysicalDeviceMemoryProperties memProperties = physicalDevice.getMemoryProperties(); + + for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) + { + if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) + { + return i; + } + } + + throw std::runtime_error("failed to find suitable memory type!"); +} + +void VulkanImpl::copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size) { + vk::raii::CommandBuffer commandCopyBuffer = beginSingleTimeCommands(); + commandCopyBuffer.copyBuffer(vk::Buffer(src), vk::Buffer(dst), vk::BufferCopy(0, 0, size)); + endSingleTimeCommands(commandCopyBuffer); +} + +void VulkanImpl::createDescriptorSetLayouts() +{ + // set 0 - Camera : un UBO en vertex shader + vk::DescriptorSetLayoutBinding cameraBinding{ + 0, // binding + vk::DescriptorType::eUniformBuffer, // type + 1, // count + vk::ShaderStageFlagBits::eVertex, // stage + nullptr + }; + cameraLayout = vk::raii::DescriptorSetLayout( + device, + vk::DescriptorSetLayoutCreateInfo{{}, 1, &cameraBinding} + ); + + // set 1 - Transform : un UBO en vertex shader + vk::DescriptorSetLayoutBinding transformBinding{ + 0, + vk::DescriptorType::eUniformBuffer, + 1, + vk::ShaderStageFlagBits::eVertex, + nullptr + }; + transformLayout = vk::raii::DescriptorSetLayout( + device, + vk::DescriptorSetLayoutCreateInfo{{}, 1, &transformBinding} + ); + + // set 2 - Material : un UBO + deux samplers en fragment shader + std::array materialBindings{{ + {0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eFragment, nullptr}, + {1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, nullptr}, + {2, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, nullptr}, + }}; + materialLayout = vk::raii::DescriptorSetLayout( + device, + vk::DescriptorSetLayoutCreateInfo{{}, + static_cast(materialBindings.size()), + materialBindings.data()} + ); + + std::array layouts{ + *cameraLayout, + *transformLayout, + *materialLayout + }; + vk::PipelineLayoutCreateInfo layoutInfo{{}, + static_cast(layouts.size()), + layouts.data() + }; + defaultPipelineLayoutInfo = vk::raii::PipelineLayout(device, layoutInfo); +} + +//Fonction d'ajout de descriptor set qui regarde la taille de la pool, si la pool est dépassée, on ajoute une pool 2x plus grande +void VulkanImpl::createDescriptorPool() +{ + descriptorPoolManager.init(device); +} + +void VulkanImpl::createDepthResources() +{ + vk::Format depthFormat = findDepthFormat(); + createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::MemoryPropertyFlagBits::eDeviceLocal, depthImage, depthImageMemory); + depthImageView = createImageView(depthImage, depthFormat, vk::ImageAspectFlagBits::eDepth); +} + +vk::Format VulkanImpl::findSupportedFormat(const std::vector& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features) +{ + for (const auto format : candidates) { + vk::FormatProperties props = physicalDevice.getFormatProperties(format); + + if (tiling == vk::ImageTiling::eLinear && (props.linearTilingFeatures & features) == features) { + return format; + } + if (tiling == vk::ImageTiling::eOptimal && (props.optimalTilingFeatures & features) == features) { + return format; + } + } + + throw std::runtime_error("failed to find supported format!"); +} + +vk::Format VulkanImpl::findDepthFormat() { + return findSupportedFormat( + {vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint}, + vk::ImageTiling::eOptimal, + vk::FormatFeatureFlagBits::eDepthStencilAttachment + ); + } + +bool VulkanImpl::hasStencilComponent(vk::Format format) { + return format == vk::Format::eD32SfloatS8Uint || format == vk::Format::eD24UnormS8Uint; +} + +void VulkanImpl::createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory) +{ + vk::ImageCreateInfo imageInfo{{},vk::ImageType::e2D, format, {width, height, 1}, 1, 1, vk::SampleCountFlagBits::e1, tiling, usage, vk::SharingMode::eExclusive}; + + image = vk::raii::Image(device, imageInfo); + + vk::MemoryRequirements memRequirements = image.getMemoryRequirements(); + vk::MemoryAllocateInfo allocInfo{memRequirements.size, + findMemoryType(memRequirements.memoryTypeBits, properties)}; + imageMemory = vk::raii::DeviceMemory(device, allocInfo); + image.bindMemory(imageMemory, 0); +} + +vk::raii::CommandBuffer VulkanImpl::beginSingleTimeCommands() { + vk::CommandBufferAllocateInfo allocInfo{ commandPool, vk::CommandBufferLevel::ePrimary, 1 }; + vk::raii::CommandBuffer commandBuffer = std::move(device.allocateCommandBuffers(allocInfo).front()); + + vk::CommandBufferBeginInfo beginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit }; + commandBuffer.begin(beginInfo); + + return commandBuffer; +} + +void VulkanImpl::endSingleTimeCommands(vk::raii::CommandBuffer& commandBuffer) { + commandBuffer.end(); + + vk::SubmitInfo submitInfo{{},{},{},1, &*commandBuffer }; + graphicsQueue.submit(submitInfo, nullptr); + graphicsQueue.waitIdle(); +} + + +void VulkanImpl::transitionImageLayout(vk::Image image, vk::ImageLayout oldLayout, vk::ImageLayout newLayout) +{ + auto commandBuffer = beginSingleTimeCommands(); + + vk::ImageMemoryBarrier barrier{{},{},oldLayout, newLayout,{}, {}, image, {vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}}; + + vk::PipelineStageFlags sourceStage; + vk::PipelineStageFlags destinationStage; + + if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) + { + barrier.srcAccessMask = {}; + barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; + + sourceStage = vk::PipelineStageFlagBits::eTopOfPipe; + destinationStage = vk::PipelineStageFlagBits::eTransfer; + } + else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) + { + barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + + sourceStage = vk::PipelineStageFlagBits::eTransfer; + destinationStage = vk::PipelineStageFlagBits::eFragmentShader; + } + else + { + throw std::invalid_argument("unsupported layout transition!"); + } + commandBuffer.pipelineBarrier(sourceStage, destinationStage, {}, {}, nullptr, barrier); + endSingleTimeCommands(commandBuffer); +} + +void VulkanImpl::copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height) +{ + auto commandBuffer = beginSingleTimeCommands(); + vk::BufferImageCopy region{0, 0, 0, {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, {0, 0, 0}, {width, height, 1}}; + commandBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, {region}); + endSingleTimeCommands(commandBuffer); +} + +void VulkanImpl::destroyBuffer(VMABuffer& buffer, uint32_t frame) { + VmaAllocator& alloc = allocator; + VkBuffer& buf = buffer.buffer; + VmaAllocation& mem = buffer.allocation; + + m_deletionQueue.push(frame, [alloc, buf, mem]() { + vmaDestroyBuffer(alloc, buf, mem); + }); + + buffer.buffer = VK_NULL_HANDLE; + buffer.allocation = VK_NULL_HANDLE; +} + +// destruction d'un descriptor set +void VulkanImpl::destroyDescriptorSet(ManagedDescriptorSet& set, uint32_t frame) { + auto s = std::make_shared(std::move(set)); + m_deletionQueue.push(frame, [&dpm = descriptorPoolManager, s]() mutable { + dpm.free(*s); + }); +} + +void VulkanImpl::destroyPipeline(vk::raii::Pipeline& pipeline, vk::raii::PipelineLayout& layout) +{ + auto p = std::make_shared(std::move(pipeline)); + auto pl = std::make_shared(std::move(layout)); + + m_deletionQueue.push(frameIndex, [p, pl]() mutable { + p = nullptr; + pl = nullptr; + }); +} + +void VulkanImpl::createDefaultTexture() +{ + auto def = std::make_unique(""); + def.get()->initDefaultTexture(); + m_defaultTexture = def.get(); + getResourceManager().getTextureManager().addTexture("default", std::move(def)); +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/API/VulkanImpl.hpp b/src/Engine/Core/Graphics/API/VulkanImpl.hpp new file mode 100644 index 0000000..0b88da9 --- /dev/null +++ b/src/Engine/Core/Graphics/API/VulkanImpl.hpp @@ -0,0 +1,226 @@ +#ifndef VULKANIMPL_HPP +#define VULKANIMPL_HPP + +#include "GraphicsAPI.hpp" +#include "DeletionQueue.hpp" +#include +#include +#include + +#include "vk_mem_alloc.h" +#include "vulkan/vulkan.hpp" +#include "ManagedDescriptorSet.hpp" +const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation" +}; + +#ifdef NDEBUG +constexpr bool enableValidationLayers = false; +#else +constexpr bool enableValidationLayers = true; +#endif + +class DescriptorAllocator { + struct Pool { + vk::raii::DescriptorPool pool = nullptr; + uint32_t capacity = 0; + uint32_t allocated = 0; + + bool isFull() const { return allocated >= capacity; } + bool isEmpty() const { return allocated == 0; } + }; + + vk::raii::Device* m_device = nullptr; + uint32_t m_baseSize = 64; + std::vector m_pools; + + Pool createPool(uint32_t size) { + std::vector sizes = { + {vk::DescriptorType::eUniformBuffer, size * 2}, + {vk::DescriptorType::eCombinedImageSampler, size * 2}, + }; + Pool p; + p.capacity = size; + p.pool = vk::raii::DescriptorPool(*m_device, + vk::DescriptorPoolCreateInfo{ + vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, + size, + static_cast(sizes.size()), + sizes.data() + } + ); + return p; + } + + Pool& getAvailablePool() { + // cherche une pool non pleine + for (auto& p : m_pools) + if (!p.isFull()) return p; + + //nouvelle pool x2 + uint32_t newSize = m_pools.empty() + ? m_baseSize + : m_pools.back().capacity * 2; + + return m_pools.emplace_back(createPool(newSize)); + } + +public: + void init(vk::raii::Device& device) { m_device = &device; } + + ManagedDescriptorSet allocate(vk::DescriptorSetLayout layout) { + auto& p = getAvailablePool(); + + vk::DescriptorSetAllocateInfo allocInfo{*p.pool, 1, &layout}; + auto sets = m_device->allocateDescriptorSets(allocInfo); + p.allocated++; + ManagedDescriptorSet mds; + mds.set = std::move(sets[0]); + mds.ownerPool = *p.pool; + return mds; + } + + void free(ManagedDescriptorSet& man) { + // retrouve la pool du set pour décrémenter + VkDescriptorPool rawPool = man.ownerPool; // handle de la pool parente + man.set = nullptr; // libère vk::raii free + + for (auto it = m_pools.begin(); it != m_pools.end(); ++it) { + if (*it->pool == rawPool) { + it->allocated--; + if (it->isEmpty()) + m_pools.erase(it); + return; + } + } + } +}; + + +class VulkanImpl: public GraphicsAPI{ + private: + vk::raii::Context context; + vk::raii::Instance instance = nullptr; + vk::raii::PhysicalDevice physicalDevice = nullptr; + std::vector requiredDeviceExtension = { + vk::KHRSwapchainExtensionName}; + + vk::raii::Device device = nullptr; + vk::raii::Queue graphicsQueue = nullptr; + vk::raii::Queue presentQueue = nullptr; + uint32_t queueIndex = ~0; + vk::raii::SurfaceKHR surface = nullptr; + + vk::raii::SwapchainKHR swapChain = nullptr; + std::vector swapChainImages; + vk::SurfaceFormatKHR swapChainSurfaceFormat; + vk::Extent2D swapChainExtent; + std::vector swapChainImageViews; + + vk::raii::CommandPool commandPool = nullptr; + std::vector commandBuffers; + + std::vector presentCompleteSemaphores; + std::vector renderFinishedSemaphores; + std::vector inFlightFences; + uint32_t frameIndex = 0; + SDL_Window* m_window; + + bool framebufferResized = false; + + VmaAllocator allocator = nullptr; + + vk::raii::DescriptorSetLayout cameraLayout = nullptr; // set 0 + vk::raii::DescriptorSetLayout transformLayout = nullptr; // set 1 + vk::raii::DescriptorSetLayout materialLayout = nullptr; // set 2 + + DescriptorAllocator descriptorPoolManager; + vk::raii::PipelineLayout defaultPipelineLayoutInfo = nullptr; + + vk::raii::Image depthImage = nullptr; + vk::raii::DeviceMemory depthImageMemory = nullptr; + vk::raii::ImageView depthImageView = nullptr; + + DeletionQueue m_deletionQueue; + + CTexture* m_defaultTexture = nullptr; + public: + virtual ~VulkanImpl(){}; + void init(SDL_Window* window) override; + void cleanup()override; + void createInstance(); + void pickPhysicalDevice(); + void createLogicalDevice(); + void createSurface(); + void createSwapChain(); + void createImageViews(); + //void createGraphicsPipeline(); + void createCommandPool(); + void createCommandBuffer(); + void createSyncObjects(); + void drawFrame() override; + void recreateSwapChain(); + void createDescriptorSetLayouts(); + void cleanupSwapChain(); + void createDepthResources(); + + void transitionImageLayout(vk::Image image, vk::ImageLayout old_layout, vk::ImageLayout new_layout, vk::AccessFlags2 src_access_mask, vk::AccessFlags2 dst_access_mask, vk::PipelineStageFlags2 src_stage_mask, vk::PipelineStageFlags2 dst_stage_mask, vk::ImageAspectFlags image_aspect_flags); + void transitionImageLayout(vk::Image image, vk::ImageLayout oldLayout, vk::ImageLayout newLayout); + void recordCommandBuffer(uint32_t imageIndex); + void* getDevice()override {return &device;}; + uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties); + vk::SurfaceFormatKHR& getSwapChainFormat(){return swapChainSurfaceFormat;}; + uint32_t getGraphicsQueueIndex() const { return queueIndex; } + vk::Extent2D getSwapChainExtent() const { return swapChainExtent; } + + // accès au command buffer courant pour que le Renderer puisse enregistrer + vk::raii::CommandBuffer& getCurrentCommandBuffer(); + + // accès à l'image view courante pour le color attachment + vk::raii::ImageView& getCurrentSwapChainImageView(); + + // pour que le Renderer sache quelle frame est en cours + uint32_t getCurrentFrameIndex() const { return frameIndex; } + + VmaAllocator getAllocator() { return allocator; } + vk::raii::PhysicalDevice& getPhysicalDevice() { return physicalDevice; } + vk::raii::DescriptorSetLayout& getCameraLayout() { return cameraLayout; } + vk::raii::DescriptorSetLayout& getTransformLayout() { return transformLayout; } + vk::raii::DescriptorSetLayout& getMaterialLayout() { return materialLayout; } + + void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize size); + + vk::Format findSupportedFormat(const std::vector& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features); + vk::Format findDepthFormat(); + + bool hasStencilComponent(vk::Format format); + void createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags properties, vk::raii::Image &image, vk::raii::DeviceMemory &imageMemory); + + DescriptorAllocator& getDescriptorPoolManager(){return descriptorPoolManager;}; + + void createDescriptorPool(); + + vk::raii::CommandBuffer beginSingleTimeCommands(); + + void endSingleTimeCommands(vk::raii::CommandBuffer& commandBuffer); + + vk::raii::ImageView createImageView(vk::raii::Image& image, vk::Format format, vk::ImageAspectFlags aspectFlags); + + + void copyBufferToImage(const vk::raii::Buffer &buffer, vk::raii::Image &image, uint32_t width, uint32_t height); + + void destroyBuffer(VMABuffer& buffer, uint32_t frameIndex); + + void destroyDescriptorSet(ManagedDescriptorSet& set, uint32_t frameIndex); + + void destroyPipeline(vk::raii::Pipeline& pipeline, vk::raii::PipelineLayout& layout); + + vk::raii::PipelineLayout& getDefaultPipelineLayout(){return defaultPipelineLayoutInfo;}; + + DeletionQueue& getDeletionQueue(){return m_deletionQueue;}; + + CTexture* getDefaultTexture() { return m_defaultTexture; } + + void createDefaultTexture(); + }; +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/CContext.cpp b/src/Engine/Core/Graphics/CContext.cpp new file mode 100644 index 0000000..a29b8e2 --- /dev/null +++ b/src/Engine/Core/Graphics/CContext.cpp @@ -0,0 +1,42 @@ +#include "CContext.hpp" +#include "API/GraphicsAPI.hpp" +#include +#include + +bool CContext::m_screenSaver = false; + +void CContext::init(SDL_InitFlags sdlFlags) { + // Log initialisation. + initLog(); + + + // SDL Initialization. + if (SDL_Init(sdlFlags)) { + SDL_Quit(); + //HandleException(CLibException(std::string("Unable to initialize SDL: ") + SDL_GetError()), true); + } + + GraphicsAPI::initAPI(); +} + +bool CContext::isScreenSaverEnable(void) { + return m_screenSaver; +} + +void CContext::setScreenSaverEnable(bool newScreenSaver) { + m_screenSaver = newScreenSaver; + if (m_screenSaver) { + SDL_EnableScreenSaver(); + } + else { + SDL_DisableScreenSaver(); + } +} + +void CContext::quit(void) { + SDL_Quit(); +} + +void CContext::initLog(void) { + //todo +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/CContext.hpp b/src/Engine/Core/Graphics/CContext.hpp new file mode 100644 index 0000000..fc5ff25 --- /dev/null +++ b/src/Engine/Core/Graphics/CContext.hpp @@ -0,0 +1,34 @@ +#ifndef CCONTEXT_HPP +#define CCONTEXT_HPP + +#include +#include +#include + +#define LOG_FILE "CosmicEngine_%3N.log" +#define LOG_ROTATION_SIZE 1 * 1024 * 1024 +#define LOG_MAX_SIZE 50 * 1024 * 1024 + +class CContext { +private: + // Say if the screenSaver is enabled. + static bool m_screenSaver; + +public: + CContext(void) = delete; + + static void init(SDL_InitFlags sdlFlags); + + static void quit(void); + + static bool isScreenSaverEnable(void); + + + static void setScreenSaverEnable(bool newScreenSaver); + +private: + + static void initLog(void); +}; + +#endif diff --git a/src/Engine/Core/Component/Graphics/CModel.cpp b/src/Engine/Core/Graphics/Data/CModel.cpp similarity index 76% rename from src/Engine/Core/Component/Graphics/CModel.cpp rename to src/Engine/Core/Graphics/Data/CModel.cpp index 76ee607..a099342 100644 --- a/src/Engine/Core/Component/Graphics/CModel.cpp +++ b/src/Engine/Core/Graphics/Data/CModel.cpp @@ -6,10 +6,6 @@ CModel::CModel(std::vector meshes) : } CModel::~CModel(void) { - for (unsigned int i = 0; i < m_meshes.size(); i++) - { - delete m_meshes[i]; - } } void CModel::load(void) { @@ -21,12 +17,12 @@ void CModel::load(void) { m_loaded = true; } -void CModel::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) { +/*void CModel::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) { // For each meshes of the model. for (unsigned int i = 0; i < m_meshes.size(); i++) { m_meshes[i]->draw(model, view, projection, lightPos, intensity); } -} +}*/ std::vector& CModel::getMeshes() { diff --git a/src/Engine/Core/Graphics/Data/CModel.hpp b/src/Engine/Core/Graphics/Data/CModel.hpp new file mode 100644 index 0000000..e355ee2 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/CModel.hpp @@ -0,0 +1,34 @@ +#ifndef CMODEL_HPP +#define CMODEL_HPP + +#include "Mesh/CMesh.hpp" +#include + +class CModel { +private: + + std::vector m_meshes; + + bool m_loaded; + +public: + + CModel(void) = delete; + + CModel(std::vector meshes); + + ~CModel(void); + + void load(void); + + //void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity); + + std::vector& getMeshes(void); + + void setMeshes(std::vector meshes); + + bool isLoaded(void); + +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/CModelLoader.cpp b/src/Engine/Core/Graphics/Data/CModelLoader.cpp new file mode 100644 index 0000000..0e685f7 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/CModelLoader.cpp @@ -0,0 +1,151 @@ +#include "CModelLoader.hpp" +#include "../API/GraphicsAPI.hpp" +#include + +CModel* CModelLoader::loadModel(std::string fileName, CResourceManager& rm) +{ + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(fileName, + aiProcess_Triangulate | + aiProcess_FlipUVs | + aiProcess_CalcTangentSpace | + aiProcess_GenNormals + ); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + throw std::runtime_error("Assimp: " + std::string(importer.GetErrorString())); + + // dossier de base pour les textures relatives + std::vector meshes; + processNode(scene->mRootNode, scene, fileName, rm, meshes); + + // crée et enregistre le model + auto model = std::make_unique(meshes); + auto* ptr = model.get(); + rm.getModelManager().addModel(fileName,std::move(model)); + + return ptr; +} + +void CModelLoader::processNode(aiNode* node, const aiScene* scene, const std::string& directory, CResourceManager& rm, std::vector& meshes) +{ + // process all the node's meshes (if any) + for (uint32_t i = 0; i < node->mNumMeshes; i++) { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(processMesh(mesh, scene, directory, rm)); + } + // then do the same for each of its children + for (uint32_t i = 0; i < node->mNumChildren; i++) { + processNode(node->mChildren[i], scene, directory, rm, meshes); + } +} + +CMesh* CModelLoader::processMesh(aiMesh* mesh, const aiScene* scene, const std::string& directory, CResourceManager& rm) +{ + std::vector vertices; + std::vector indices; + + // vertices + for (uint32_t i = 0; i < mesh->mNumVertices; i++) { + SVertex vertex{}; + vertex.m_position = { + mesh->mVertices[i].x, + mesh->mVertices[i].y, + mesh->mVertices[i].z + }; + vertex.m_normal = mesh->HasNormals() ? + glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z) : + glm::vec3(0.0f); + + vertex.m_texCoords = mesh->mTextureCoords[0] ? + glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y) : + glm::vec2(0.0f); + + vertex.m_tangent = mesh->HasTangentsAndBitangents() ? + glm::vec3(mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z) : + glm::vec3(0.0f); + + vertex.m_bitangent = mesh->HasTangentsAndBitangents() ? + glm::vec3(mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z) : + glm::vec3(0.0f); + + vertices.push_back(vertex); + } + + // indices + for (uint32_t i = 0; i < mesh->mNumFaces; i++) { + aiFace face = mesh->mFaces[i]; + for (uint32_t j = 0; j < face.mNumIndices; j++) + indices.push_back(face.mIndices[j]); + } + + // material + CMaterial* material = nullptr; + if (mesh->mMaterialIndex >= 0) { + material = processMaterial( + scene->mMaterials[mesh->mMaterialIndex], + directory, + rm + ); + } + + // crée et enregistre le mesh + auto newMesh = std::make_unique(); + newMesh->setVertices(vertices); + newMesh->setIndexes(indices); + if (material) newMesh->setMaterial(material); + newMesh->load(); + + auto* ptr = newMesh.get(); + rm.getMeshManager().addMesh(directory, std::move(newMesh)); + return ptr; +} + +CMaterial* CModelLoader::processMaterial(aiMaterial* mat, const std::string& directory, CResourceManager& rm) +{ + auto newMat = std::make_unique(); + + // albedo + if (mat->GetTextureCount(aiTextureType_DIFFUSE) > 0) { + aiString path; + mat->GetTexture(aiTextureType_DIFFUSE, 0, &path); + newMat->textureAlbedo = loadTexture( + directory + "/" + path.C_Str(), rm + ); + } + + // normal + if (mat->GetTextureCount(aiTextureType_NORMALS) > 0) { + aiString path; + mat->GetTexture(aiTextureType_NORMALS, 0, &path); + newMat->textureNormal = loadTexture( + directory + "/" + path.C_Str(), rm + ); + } + + auto shader = GraphicsAPI::getAPI()->getShaderManager().get("triangle"); + newMat->shader = static_cast(shader); + newMat->build(); + + auto* ptr = newMat.get(); + rm.getMaterialManager().addMaterial(directory, std::move(newMat)); + return ptr; +} + + +CTexture* CModelLoader::loadTexture(const std::string& directory, CResourceManager& rm) +{ + auto text = rm.getTextureManager().get(directory); + if(rm.getTextureManager().get(directory)) + { + return text.value(); + } + else { + auto tex = std::make_unique(directory); + tex->init(); + + auto* ptr = tex.get(); + rm.getTextureManager().addTexture(directory, std::move(tex)); + return ptr; + } +} \ No newline at end of file diff --git a/src/Engine/Core/Utils/File/CModelLoader.hpp b/src/Engine/Core/Graphics/Data/CModelLoader.hpp similarity index 64% rename from src/Engine/Core/Utils/File/CModelLoader.hpp rename to src/Engine/Core/Graphics/Data/CModelLoader.hpp index 36fd861..33af82a 100644 --- a/src/Engine/Core/Utils/File/CModelLoader.hpp +++ b/src/Engine/Core/Graphics/Data/CModelLoader.hpp @@ -5,18 +5,15 @@ #include #include #include -#include "../../Model/Graphic/Texture/CImageTexture.hpp" -#include -#include -#include "../../Model/Graphic/Mesh/CMesh.hpp" -#include "../../Model/Graphic/CModel.hpp" -#include "../../Model/Node/CScene.hpp" -#include "../../Controller/CKernel.hpp" -#include "../../Context/CContext.hpp" + +#include "CResourceManager.hpp" +#include "Mesh/CMesh.hpp" +#include "Texture/CTexture.hpp" /** * @brief Class allowing to load models from obj files. */ +#include class CModelLoader { private: /** @@ -26,7 +23,7 @@ private: * @param[in] meshes The mesh list. * @param[in] material A pointer to a material. It's optionnal and override the obj's material. */ - static void processNode(aiNode* node, const aiScene* scene, std::vector* meshes, SMaterial* material); + static void processNode(aiNode* node, const aiScene* scene, const std::string& directory, CResourceManager& rm, std::vector& meshes); /** * @brief Compute every meshes. @@ -35,7 +32,7 @@ private: * @param[in] meshes The list of meshes. * @param[in] material A pointer to a material. It's optionnal and override the obj's material. */ - static void processMesh(aiMesh* mesh, const aiScene* scene, std::vector* meshes, SMaterial* material); + static CMesh* processMesh(aiMesh* mesh, const aiScene* scene, const std::string& directory, CResourceManager& rm); /** * @brief Load Textures from the obj file. @@ -43,7 +40,9 @@ private: * @param[in] type The assimp's texture type. * @param[in] typeName The texture's type. */ - static std::vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, ETextureType typeName); + static CTexture* loadTexture(const std::string& directory, CResourceManager& rm); + + static CMaterial* processMaterial(aiMaterial* mat, const std::string& directory, CResourceManager& rm); public: /** @@ -52,7 +51,7 @@ public: * @param[in] material Pointer to a material. It's optionnal and override the obj's material. * @return A dynamically allocated CModel. */ - static CModel* loadModel(std::string fileName, SMaterial* material); + static CModel* loadModel(std::string filename, CResourceManager& rm); }; diff --git a/src/Engine/Core/Graphics/Data/CModelManager.hpp b/src/Engine/Core/Graphics/Data/CModelManager.hpp new file mode 100644 index 0000000..0dcc3f6 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/CModelManager.hpp @@ -0,0 +1,32 @@ +#ifndef CMODELMANAGER_HPP +#define CMODELMANAGER_HPP + +#include "CModel.hpp" +#include +#include +class CModelManager +{ + public: + std::list> loadedModel; + std::unordered_map modelsMap; + + void addModel(std::string name, std::unique_ptr&& model) + { + loadedModel.push_back(std::move(model)); + modelsMap[name] = loadedModel.back().get(); + } + std::optional get(std::string name) + { + auto find = modelsMap.find(name); + if(find != modelsMap.end()) + { + return find->second; + } + else { + return nullptr; + } + } + +}; + + #endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/CResourceManager.hpp b/src/Engine/Core/Graphics/Data/CResourceManager.hpp new file mode 100644 index 0000000..83523f9 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/CResourceManager.hpp @@ -0,0 +1,28 @@ +#ifndef CRESOURCEMANAGER_HPP +#define CRESOURCEMANAGER_HPP + +#include "CModelManager.hpp" +#include "Mesh/CMeshManager.hpp" +#include "Material/CMaterialManager.hpp" +#include "Texture/CTextureManager.hpp" + +class CResourceManager{ + private: + CModelManager modelManager; + CMeshManager meshManager; + CMaterialManager materialManager; + CTextureManager textureManager; + public: + CModelManager& getModelManager() { return modelManager; } + CMeshManager& getMeshManager() { return meshManager; } + CMaterialManager& getMaterialManager() { return materialManager; } + CTextureManager& getTextureManager() {return textureManager;} + void cleanup(){ + materialManager.loadedMaterials.clear(); + meshManager.loadedMeshes.clear(); + modelManager.loadedModel.clear(); + textureManager.loadedTextures.clear(); + }; +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CTextTexture.cpp b/src/Engine/Core/Graphics/Data/Font/CTextTexture.cpp similarity index 98% rename from src/Engine/Core/Component/Graphics/Texture/CTextTexture.cpp rename to src/Engine/Core/Graphics/Data/Font/CTextTexture.cpp index 9a23365..ea11151 100644 --- a/src/Engine/Core/Component/Graphics/Texture/CTextTexture.cpp +++ b/src/Engine/Core/Graphics/Data/Font/CTextTexture.cpp @@ -1,4 +1,4 @@ -#include "CTextTexture.hpp" +/*#include "CTextTexture.hpp" CTextTexture::CTextTexture(ETextureType type, std::string filePath, std::string text, unsigned int fontSize, glm::vec3 fontColor, glm::bvec4 fontStyle) : CAbstractTexture(type), @@ -108,4 +108,4 @@ void CTextTexture::init(void) { // Free the surface. SDL_FreeSurface(sdlSurface); -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Texture/CTextTexture.hpp b/src/Engine/Core/Graphics/Data/Font/CTextTexture.hpp similarity index 97% rename from src/Engine/Core/Component/Graphics/Texture/CTextTexture.hpp rename to src/Engine/Core/Graphics/Data/Font/CTextTexture.hpp index f5172b8..26b9b40 100644 --- a/src/Engine/Core/Component/Graphics/Texture/CTextTexture.hpp +++ b/src/Engine/Core/Graphics/Data/Font/CTextTexture.hpp @@ -1,4 +1,4 @@ -#ifndef CTEXTTEXTURE_HPP +/*#ifndef CTEXTTEXTURE_HPP #define CTEXTTEXTURE_HPP #include "../../../Controller/Exception/CLibException.hpp" @@ -44,4 +44,4 @@ public: virtual void init(void); }; -#endif \ No newline at end of file +#endif*/ \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Material/CMaterial.cpp b/src/Engine/Core/Graphics/Data/Material/CMaterial.cpp new file mode 100644 index 0000000..bcb3079 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Material/CMaterial.cpp @@ -0,0 +1,137 @@ +#include "CMaterial.hpp" +#include "../Mesh/SVertex.hpp" +#include "../../API/VulkanImpl.hpp" +#include + +void CMaterial::build() +{ + if(isInit) + { + destroy(); + } + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + auto* device= static_cast(api->getDevice()); + auto shaderStages = shader->getShaderStages(0, vk::ShaderStageFlagBits::eVertex, vk::ShaderStageFlagBits::eFragment); + + auto bindingDescription = Vertex::getBindingDescription(); + auto attributeDescriptions = Vertex::getAttributeDescriptions(); + vk::PipelineVertexInputStateCreateInfo vertexInputInfo{{}, 1, &bindingDescription, static_cast(attributeDescriptions.size()), attributeDescriptions.data()}; + + vk::PipelineInputAssemblyStateCreateInfo inputAssembly{{},vk::PrimitiveTopology::eTriangleList}; + vk::PipelineViewportStateCreateInfo viewportState{{},1, {},1}; + + vk::PipelineRasterizationStateCreateInfo rasterizer{{},vk::False, vk::False, vk::PolygonMode::eFill,vk::CullModeFlagBits::eBack, vk::FrontFace::eCounterClockwise, vk::False, {}, {}, 1.0f, 1.0f}; + + vk::PipelineMultisampleStateCreateInfo multisampling{{}, vk::SampleCountFlagBits::e1, vk::False}; + + vk::PipelineColorBlendAttachmentState colorBlendAttachment{vk::False, {}, {}, {}, {}, {}, {}, vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA}; + + vk::PipelineColorBlendStateCreateInfo colorBlending{{},vk::False, vk::LogicOp::eCopy, 1, &colorBlendAttachment}; + + vk::PipelineDepthStencilStateCreateInfo depthStencil{{}, + vk::True, + vk::True, + vk::CompareOp::eLess, + vk::False, + vk::False}; + + std::vector dynamicStates = { + vk::DynamicState::eViewport, + vk::DynamicState::eScissor}; + vk::PipelineDynamicStateCreateInfo dynamicState{{}, static_cast(dynamicStates.size()), dynamicStates.data()}; + + std::array layouts{ + *api->getCameraLayout(), // set 0 + *api->getTransformLayout(), // set 1 + *api->getMaterialLayout() // set 2 + }; + + vk::PipelineLayoutCreateInfo pipelineLayoutInfo{{},3,layouts.data(), 0}; + + pipelineLayout = vk::raii::PipelineLayout(*static_cast(api->getDevice()), pipelineLayoutInfo); + + vk::StructureChain pipelineCreateInfoChain = { + {{}, + 2, + shaderStages.data(), + &vertexInputInfo, + &inputAssembly, + {}, + &viewportState, + &rasterizer, + &multisampling, + &depthStencil, + &colorBlending, + &dynamicState, + pipelineLayout, + nullptr + }, + {{}, + 1, + &api->getSwapChainFormat().format, + api->findDepthFormat() + } + }; + + pipeline = vk::raii::Pipeline(*static_cast(api->getDevice()), nullptr, pipelineCreateInfoChain.get()); + + // descriptor sets du material (set 2) + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + m_descriptorSets[i] = api->getDescriptorPoolManager().allocate( + *api->getMaterialLayout() + ); + + std::vector writes; + + // binding 1 : albedo (si présent) + vk::DescriptorImageInfo albedoInfo; + if (textureAlbedo) { + albedoInfo = { + *textureAlbedo->getSampler(), + *textureAlbedo->getImageView(), + vk::ImageLayout::eShaderReadOnlyOptimal + }; + writes.push_back({ + *m_descriptorSets[i].set, + 1, 0, 1, + vk::DescriptorType::eCombinedImageSampler, + &albedoInfo + }); + } + else { + albedoInfo = { + api->getDefaultTexture()->getSampler(), + api->getDefaultTexture()->getImageView(), + vk::ImageLayout::eShaderReadOnlyOptimal + }; + writes.push_back({ + *m_descriptorSets[i].set, + 1, 0, 1, + vk::DescriptorType::eCombinedImageSampler, + &albedoInfo + }); + } + + if (!writes.empty()) + device->updateDescriptorSets(writes, {}); + } + isInit = true; +} + +CMaterial::~CMaterial() +{ + destroy(); +} + +void CMaterial::destroy() +{ + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + uint32_t currentFrame = api->getCurrentFrameIndex(); + + api->destroyPipeline(pipeline, pipelineLayout); + + // descriptor sets + for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + api->destroyDescriptorSet(m_descriptorSets[i], i); + } +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Material/CMaterial.hpp b/src/Engine/Core/Graphics/Data/Material/CMaterial.hpp new file mode 100644 index 0000000..f741bdd --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Material/CMaterial.hpp @@ -0,0 +1,30 @@ +#ifndef SMATERIAL_HPP +#define SMATERIAL_HPP + +#include "../../Shader/Implementations/CShaderImplVulkan.hpp" +#include "../../API/ManagedDescriptorSet.hpp" +#include "SColor.hpp" +#include "../Texture/CTexture.hpp" + +class CMaterial { + public: + + ~CMaterial(); + void destroy(); + bool isInit = false; + SColor m_color; + CTexture* textureAlbedo = nullptr; + CTexture* textureNormal = nullptr; + CShaderImplVulkan* shader; + vk::raii::PipelineLayout pipelineLayout = nullptr; + vk::raii::Pipeline pipeline = nullptr; + std::array m_descriptorSets; + void build(); + vk::raii::Pipeline& getPipeline(){return pipeline;}; + vk::raii::PipelineLayout& getPipelineLayout(){return pipelineLayout;}; + vk::raii::DescriptorSet& getDescriptorSet(uint32_t frameIndex) { + return m_descriptorSets[frameIndex].set; + } +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Material/CMaterialManager.hpp b/src/Engine/Core/Graphics/Data/Material/CMaterialManager.hpp new file mode 100644 index 0000000..6831326 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Material/CMaterialManager.hpp @@ -0,0 +1,31 @@ +#ifndef CMATERIALMANAGER_HPP +#define CMATERIALMANAGER_HPP + +#include "CMaterial.hpp" +#include +#include +#include +class CMaterialManager +{ + public: + std::list> loadedMaterials; + std::unordered_map materialsMap; + void addMaterial(std::string name, std::unique_ptr&& mat) + { + loadedMaterials.push_back(std::move(mat)); + materialsMap[name] = loadedMaterials.back().get(); + } + std::optional get(std::string name) + { + auto find = materialsMap.find(name); + if(find != materialsMap.end()) + { + return find->second; + } + else { + return nullptr; + } + } +}; + + #endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Material/SColor.hpp b/src/Engine/Core/Graphics/Data/Material/SColor.hpp similarity index 100% rename from src/Engine/Core/Component/Graphics/Material/SColor.hpp rename to src/Engine/Core/Graphics/Data/Material/SColor.hpp diff --git a/src/Engine/Core/Graphics/Data/Mesh/CMesh.cpp b/src/Engine/Core/Graphics/Data/Mesh/CMesh.cpp new file mode 100644 index 0000000..7daff22 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Mesh/CMesh.cpp @@ -0,0 +1,107 @@ +#include "CMesh.hpp" +#include "../../API/VulkanImpl.hpp" +#include +#include +CMesh::CMesh(void) : + m_vertexes() { +} + +CMesh::~CMesh(void) { + destroy(); +} + +void CMesh::destroy() +{ + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + api->destroyBuffer(vertexIndexBuffer, api->getCurrentFrameIndex()); + /*if (api && vertexIndexBuffer.buffer != VK_NULL_HANDLE) + vmaDestroyBuffer(api->getAllocator(), vertexIndexBuffer.buffer, vertexIndexBuffer.allocation);*/ +} +std::vector& CMesh::getVertices(void) { + return m_vertexes; +} + + +void CMesh::setVertices(std::vector vertices) +{ + m_vertexes = vertices; +} +void CMesh::setIndexes(std::vector indexes){ + m_indexes = indexes; +} + +std::vector& CMesh::getIndexes(void){ + return m_indexes; +} + +/*void CMesh::load(void) { + vk::BufferCreateInfo bufferInfo{{},sizeof(m_vertexes[0]) * m_vertexes.size(), vk::BufferUsageFlagBits::eVertexBuffer, vk::SharingMode::eExclusive}; + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + vertexBuffer = vk::raii::Buffer(*static_cast(api->getDevice()), bufferInfo); + + vk::MemoryRequirements memRequirements = vertexBuffer.getMemoryRequirements(); + vk::MemoryAllocateInfo memoryAllocateInfo{memRequirements.size, api->findMemoryType(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)}; + vertexBufferMemory = vk::raii::DeviceMemory(*static_cast(api->getDevice()), memoryAllocateInfo); + + vertexBuffer.bindMemory(*vertexBufferMemory, 0); + + void *data = vertexBufferMemory.mapMemory(0, bufferInfo.size); + memcpy(data, m_vertexes.data(), bufferInfo.size); + vertexBufferMemory.unmapMemory(); +}*/ + +void CMesh::load(void) { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + VmaAllocator allocator = api->getAllocator(); + + VkDeviceSize vertexSize = sizeof(m_vertexes[0]) * m_vertexes.size(); + VkDeviceSize indexSize = sizeof(m_indexes[0]) * m_indexes.size(); + VkDeviceSize totalSize = vertexSize + indexSize; + + // 1. staging buffer - CPU visible, temporaire + VkBufferCreateInfo stagingBufferInfo{}; + stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + stagingBufferInfo.size = totalSize; + stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + VmaAllocationCreateInfo stagingAllocInfo{}; + stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; + stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VMABuffer stagingBuffer; + VmaAllocationInfo stagingInfo{}; + vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo, + &stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo); + + // 2. copie des données CPU → staging + memcpy(stagingInfo.pMappedData, m_vertexes.data(), vertexSize); + memcpy((char*)stagingInfo.pMappedData + vertexSize, m_indexes.data(), indexSize); + vmaFlushAllocation(allocator, stagingBuffer.allocation, 0, VK_WHOLE_SIZE); + + // 3. vertex buffer final - DEVICE_LOCAL, rapide + VkBufferCreateInfo vertexBufferInfo{}; + vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + vertexBufferInfo.size = totalSize; + vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + VmaAllocationCreateInfo vertexAllocInfo{}; + vertexAllocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; + + vmaCreateBuffer(allocator, &vertexBufferInfo, &vertexAllocInfo, + &vertexIndexBuffer.buffer, &vertexIndexBuffer.allocation, nullptr); + + // 4. copie GPU staging → vertex buffer via command buffer + api->copyBuffer(stagingBuffer.buffer, vertexIndexBuffer.buffer, totalSize); + + m_vertexOffset = 0; + m_indexOffset = vertexSize; + m_indexCount = m_indexes.size(); + // 5. détruire le staging buffer + vmaDestroyBuffer(allocator, stagingBuffer.buffer, stagingBuffer.allocation); +} + +/*void CMesh::draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity) { + +}*/ diff --git a/src/Engine/Core/Graphics/Data/Mesh/CMesh.hpp b/src/Engine/Core/Graphics/Data/Mesh/CMesh.hpp new file mode 100644 index 0000000..190bece --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Mesh/CMesh.hpp @@ -0,0 +1,53 @@ +#ifndef CMESH_HPP +#define CMESH_HPP + +#include "SVertex.hpp" +#include "../Material/CMaterial.hpp" + +#include +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include "../../API/VMABuffer.hpp" + +class CMesh { +private: + + std::vector m_vertexes; + std::vector m_indexes; + + VMABuffer vertexIndexBuffer; + VkDeviceSize m_vertexOffset = 0; + VkDeviceSize m_indexOffset = 0; + uint32_t m_indexCount = 0; + + CMaterial* m_material; + +public: + + CMesh(void); + + ~CMesh(void); + + std::vector& getVertices(void); + std::vector& getIndexes(void); + + void setVertices(std::vector vertices); + void setIndexes(std::vector indexes); + + void setMaterial(CMaterial* mat){m_material = mat;}; + + void load(void); + + //void draw(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 lightPos, float intensity); + + CMaterial* getMaterial(){return m_material;}; + VMABuffer& getVertexIndexBuffer(){return vertexIndexBuffer;}; + VkDeviceSize getVertexOffset(){return m_vertexOffset;} + VkDeviceSize getIndexOffset(){return m_indexOffset;}; + uint32_t getIndexCount(){return m_indexCount;}; + void destroy(); +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Mesh/CMeshManager.hpp b/src/Engine/Core/Graphics/Data/Mesh/CMeshManager.hpp new file mode 100644 index 0000000..cebfb3b --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Mesh/CMeshManager.hpp @@ -0,0 +1,31 @@ +#ifndef CMESHMANAGER_HPP +#define CMESHMANAGER_HPP + +#include "CMesh.hpp" +#include +#include +class CMeshManager +{ + public: + std::list> loadedMeshes; + std::unordered_map meshesMap; + void addMesh(std::string name, std::unique_ptr&& mesh) + { + loadedMeshes.push_back(std::move(mesh)); + meshesMap[name] = loadedMeshes.back().get(); + } + + std::optional get(std::string name) + { + auto find = meshesMap.find(name); + if(find != meshesMap.end()) + { + return find->second; + } + else { + return nullptr; + } + } +}; + + #endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Mesh/SVertex.hpp b/src/Engine/Core/Graphics/Data/Mesh/SVertex.hpp new file mode 100644 index 0000000..ba759e3 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Mesh/SVertex.hpp @@ -0,0 +1,70 @@ +#ifndef SVERTEX_HPP +#define SVERTEX_HPP + +#include "vulkan/vulkan.hpp" +#include + +/** + * @file SVertex.hpp + * @brief File for the vertex struct. + */ + +/** + * @brief the struct Vertex, use to represent vertex and vertex attribute. + */ +typedef struct SVertex{ + /** + * @brief Position attribute. + * 3D vector. + */ + glm::vec3 m_position; + + /** + * @brief Position attribute. + * 3D vector. + */ + glm::vec4 m_color; + /** + * @brief Normal attribute. + * 3D vector. + */ + glm::vec3 m_normal; + + /** + * @brief Texture coordinates attribute. + * 2D vector. + */ + glm::vec2 m_texCoords; + + /** + * @brief Tangent attribute. + * 3D vector. + */ + glm::vec3 m_tangent; + + /** + * @brief Bitangent attribute. + * 3D vector (perpendicular to m_tangent vector). + */ + glm::vec3 m_bitangent; + + // m_normal, m_tangent, m_bitangent are supposed to create a vector base to compute normal map. + + static vk::VertexInputBindingDescription getBindingDescription() { + return { 0, sizeof(SVertex), vk::VertexInputRate::eVertex }; + } + + static std::array getAttributeDescriptions() { + return { + vk::VertexInputAttributeDescription( 0, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_position) ), + vk::VertexInputAttributeDescription( 1, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(SVertex, m_color) ), + vk::VertexInputAttributeDescription( 2, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_normal) ), + vk::VertexInputAttributeDescription( 3, 0, vk::Format::eR32G32Sfloat, offsetof(SVertex, m_texCoords) ), + vk::VertexInputAttributeDescription( 4, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_tangent) ), + vk::VertexInputAttributeDescription( 5, 0, vk::Format::eR32G32B32Sfloat, offsetof(SVertex, m_bitangent) ) + }; + } + +} Vertex; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Texture/CTexture.cpp b/src/Engine/Core/Graphics/Data/Texture/CTexture.cpp new file mode 100644 index 0000000..cc9325a --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Texture/CTexture.cpp @@ -0,0 +1,219 @@ +#include "CTexture.hpp" + +#include "../../API/VulkanImpl.hpp" + +CTexture::CTexture(std::string filePath) : + m_filePath(filePath) { +} + +std::string CTexture::getFilePath(void) { + return m_filePath; +} + +void CTexture::setFilePath(std::string filePath) { + m_filePath = filePath; +} + +void CTexture::init(void) { + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + auto* device= static_cast(api->getDevice()); + // Read the image file. + SDL_Surface* sdlSurface = IMG_Load(m_filePath.c_str()); + + if(sdlSurface == nullptr) + { + //error here + } + + SDL_PixelFormat sdlFormat = sdlSurface->format; + SDL_Surface* converted = nullptr; + + if (sdlFormat == SDL_PIXELFORMAT_RGBA32) { + // déjà RGBA, pas de conversion + converted = sdlSurface; + m_format = vk::Format::eR8G8B8A8Srgb; + } else if (sdlFormat == SDL_PIXELFORMAT_BGRA32) { + // déjà BGRA, pas de conversion mais format différent + converted = sdlSurface; + m_format = vk::Format::eB8G8R8A8Srgb; + } else { + // tout autre format → on force RGBA32 + converted = SDL_ConvertSurface(sdlSurface, SDL_PIXELFORMAT_RGBA32); + if (!converted) + throw std::runtime_error("Failed to convert surface: " + m_filePath); + SDL_DestroySurface(sdlSurface); + m_format = vk::Format::eR8G8B8A8Srgb; + } + + + m_width = converted->w; + m_height = converted->h; + VkDeviceSize imageSize = m_width * m_height * 4; + + // 2. staging buffer + VkBufferCreateInfo stagingBufferInfo{}; + stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + stagingBufferInfo.size = imageSize; + stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + VmaAllocationCreateInfo stagingAllocInfo{}; + stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; + stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VMABuffer stagingBuffer; + VmaAllocationInfo stagingInfo{}; + vmaCreateBuffer(api->getAllocator(), &stagingBufferInfo, &stagingAllocInfo, + &stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo); + + memcpy(stagingInfo.pMappedData, converted->pixels, imageSize); + // Free the surface. + SDL_DestroySurface(converted); + + // 3. crée l'image GPU + api->createImage( + m_width, m_height, + m_format, + vk::ImageTiling::eOptimal, + vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, + vk::MemoryPropertyFlagBits::eDeviceLocal, + m_textureImage, + m_textureImageMemory + ); + + // 4. transitions et copie + api->transitionImageLayout(m_textureImage, + vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferDstOptimal); + + { + auto cmd = api->beginSingleTimeCommands(); + vk::BufferImageCopy region{ + 0, 0, 0, + {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, + {0, 0, 0}, + {static_cast(m_width), static_cast(m_height), 1} + }; + cmd.copyBufferToImage( + vk::Buffer(stagingBuffer.buffer), + m_textureImage, + vk::ImageLayout::eTransferDstOptimal, + region + ); + api->endSingleTimeCommands(cmd); + } + + api->transitionImageLayout(m_textureImage, + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal); + + vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation); + + // 5. image view + m_imageView = api->createImageView(m_textureImage, m_format, vk::ImageAspectFlagBits::eColor); + + // 6. sampler + vk::SamplerCreateInfo samplerInfo{}; + samplerInfo.magFilter = vk::Filter::eLinear; + samplerInfo.minFilter = vk::Filter::eLinear; + samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat; + samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat; + samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat; + samplerInfo.anisotropyEnable = vk::True; + samplerInfo.maxAnisotropy = api->getPhysicalDevice().getProperties().limits.maxSamplerAnisotropy; + samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack; + samplerInfo.unnormalizedCoordinates = vk::False; + samplerInfo.compareEnable = vk::False; + samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear; + + m_sampler = vk::raii::Sampler(*device, samplerInfo); + +} + +void CTexture::initDefaultTexture() +{ + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + auto* device= static_cast(api->getDevice()); + + // pixel blanc 1x1 RGBA + uint32_t whitePixel = 0x00000ff0; + uint32_t width = 1; + uint32_t height = 1; + VkDeviceSize imageSize = sizeof(uint32_t); + + // staging buffer + VkBufferCreateInfo stagingBufferInfo{}; + stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + stagingBufferInfo.size = imageSize; + stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + + VmaAllocationCreateInfo stagingAllocInfo{}; + stagingAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; + stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + VMABuffer stagingBuffer; + VmaAllocationInfo stagingInfo{}; + vmaCreateBuffer(api->getAllocator(), &stagingBufferInfo, &stagingAllocInfo, + &stagingBuffer.buffer, &stagingBuffer.allocation, &stagingInfo); + + memcpy(stagingInfo.pMappedData, &whitePixel, imageSize); + + // image GPU + api->createImage(width, height, + vk::Format::eR8G8B8A8Srgb, + vk::ImageTiling::eOptimal, + vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, + vk::MemoryPropertyFlagBits::eDeviceLocal, + m_textureImage, + m_textureImageMemory + ); + + api->transitionImageLayout(m_textureImage, + vk::ImageLayout::eUndefined, + vk::ImageLayout::eTransferDstOptimal); + + { + auto cmd = api->beginSingleTimeCommands(); + vk::BufferImageCopy region{ + 0, 0, 0, + {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, + {0, 0, 0}, + {width, height, 1} + }; + cmd.copyBufferToImage( + vk::Buffer(stagingBuffer.buffer), + m_textureImage, + vk::ImageLayout::eTransferDstOptimal, + region + ); + api->endSingleTimeCommands(cmd); + } + + api->transitionImageLayout(m_textureImage, + vk::ImageLayout::eTransferDstOptimal, + vk::ImageLayout::eShaderReadOnlyOptimal); + + vmaDestroyBuffer(api->getAllocator(), stagingBuffer.buffer, stagingBuffer.allocation); + + // image view + m_imageView = api->createImageView( + m_textureImage, + vk::Format::eR8G8B8A8Srgb, + vk::ImageAspectFlagBits::eColor + ); + + // sampler + vk::SamplerCreateInfo samplerInfo{}; + samplerInfo.magFilter = vk::Filter::eLinear; + samplerInfo.minFilter = vk::Filter::eLinear; + samplerInfo.addressModeU = vk::SamplerAddressMode::eRepeat; + samplerInfo.addressModeV = vk::SamplerAddressMode::eRepeat; + samplerInfo.addressModeW = vk::SamplerAddressMode::eRepeat; + samplerInfo.anisotropyEnable = vk::False; + samplerInfo.maxAnisotropy = 1.0f; + samplerInfo.borderColor = vk::BorderColor::eIntOpaqueBlack; + samplerInfo.unnormalizedCoordinates = vk::False; + samplerInfo.compareEnable = vk::False; + samplerInfo.mipmapMode = vk::SamplerMipmapMode::eLinear; + + m_sampler = vk::raii::Sampler(*device, samplerInfo); +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Texture/CTexture.hpp b/src/Engine/Core/Graphics/Data/Texture/CTexture.hpp new file mode 100644 index 0000000..1287856 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Texture/CTexture.hpp @@ -0,0 +1,45 @@ +#ifndef CTEXTURE_HPP +#define CTEXTURE_HPP + +#include +#include +#include +#include + + +class CTexture{ +private: + // Path of the file. + std::string m_filePath; + vk::raii::Image m_textureImage = nullptr; + vk::raii::DeviceMemory m_textureImageMemory = nullptr; + vk::raii::ImageView m_imageView = nullptr; + vk::raii::Sampler m_sampler = nullptr; + + uint32_t m_width = 0; + uint32_t m_height = 0; + vk::Format m_format = vk::Format::eR8G8B8A8Srgb; + +public: + CTexture(void) = delete; + CTexture(const CTexture&) = delete; + CTexture& operator=(const CTexture&) = delete; + ~CTexture(void) { + m_sampler = nullptr; + m_imageView = nullptr; + m_textureImage = nullptr; + m_textureImageMemory = nullptr; + }; + CTexture(std::string filePath); + std::string getFilePath(void); + void setFilePath(std::string filePath); + void init(void); + void initDefaultTexture(); + + vk::raii::ImageView& getImageView() { return m_imageView; } + vk::raii::Sampler& getSampler() { return m_sampler; } + uint32_t getWidth() const { return m_width; } + uint32_t getHeight() const { return m_height; } +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Data/Texture/CTextureManager.hpp b/src/Engine/Core/Graphics/Data/Texture/CTextureManager.hpp new file mode 100644 index 0000000..f659059 --- /dev/null +++ b/src/Engine/Core/Graphics/Data/Texture/CTextureManager.hpp @@ -0,0 +1,32 @@ +#ifndef CTEXTUREMANAGER_HPP +#define CTEXTUREMANAGER_HPP + +#include "CTexture.hpp" +#include +#include +#include +#include +class CTextureManager +{ + public: + std::list> loadedTextures; + std::unordered_map texturesMap; + void addTexture(std::string name, std::unique_ptr&& text) + { + loadedTextures.push_back(std::move(text)); + texturesMap[name] = loadedTextures.back().get(); + } + std::optional get(std::string name) + { + auto find = texturesMap.find(name); + if(find != texturesMap.end()) + { + return find->second; + } + else { + return nullptr; + } + } +}; + + #endif \ No newline at end of file diff --git a/src/Engine/Core/Component/Graphics/Shader/CShader.cpp b/src/Engine/Core/Graphics/Shader/CShader.cpp similarity index 100% rename from src/Engine/Core/Component/Graphics/Shader/CShader.cpp rename to src/Engine/Core/Graphics/Shader/CShader.cpp diff --git a/src/Engine/Core/Component/Graphics/Shader/CShader.hpp b/src/Engine/Core/Graphics/Shader/CShader.hpp similarity index 100% rename from src/Engine/Core/Component/Graphics/Shader/CShader.hpp rename to src/Engine/Core/Graphics/Shader/CShader.hpp diff --git a/src/Engine/Core/Graphics/Shader/CShadersManager.cpp b/src/Engine/Core/Graphics/Shader/CShadersManager.cpp index 227626e..fe2dbf9 100644 --- a/src/Engine/Core/Graphics/Shader/CShadersManager.cpp +++ b/src/Engine/Core/Graphics/Shader/CShadersManager.cpp @@ -1,24 +1,17 @@ #include "CShadersManager.hpp" - -#include "CShaderFactory.hpp" -#include "../CKernel.hpp" - -#include - -CShadersManager::CShadersManager(void) :m_shadersMap(), m_shaderList(nullptr) { +#include +#include +#include +#include "../../../Utils/Factory/CShaderFactory.hpp" +CShadersManager::CShadersManager(void) :m_shadersMap() { } CShadersManager::~CShadersManager(void) { - for (std::pair& it : m_shadersMap) - { - delete it.second; - } - free(m_shaderList); } CShader* CShadersManager::get(std::string name) const { - std::map::const_iterator it = m_shadersMap.find(name); + std::unordered_map::const_iterator it = m_shadersMap.find(name); if (it == m_shadersMap.end()) { return nullptr; } @@ -28,60 +21,33 @@ CShader* CShadersManager::get(std::string name) const { } void CShadersManager::create(void) { - if (std::filesystem::is_directory(CEngineConfiguration::configuration->getGlobalShadersPath())) { - for (std::filesystem::directory_iterator itr(CEngineConfiguration::configuration->getGlobalShadersPath()); itr != std::filesystem::directory_iterator(); ++itr) { + std::filesystem::path shaderDir = std::filesystem::absolute(SHADERS_FOLDER); + if (std::filesystem::is_directory(shaderDir)) { + for (std::filesystem::directory_iterator itr(shaderDir); itr != std::filesystem::directory_iterator(); ++itr) { if (std::filesystem::is_regular_file(itr->status())) { - DEBUG_LOG(trace, "Kernel", "ShadersManager", "Shader : " + itr->path().string() + " found.") - CFileManager jsonfm(itr->path().string()); - std::string json = jsonfm.read(); + std::ifstream jsonfm(itr->path().string()); try { - nlohmann::json shaderJson = nlohmann::json::parse(json); - std::string name = shaderJson["name"]; - std::string vert = shaderJson["vert"]; - std::string frag = shaderJson["frag"]; - CShader* newShader = CShaderFactory::createShader(CKernel::m_kernel ,name, CEngineConfiguration::configuration->getGlobalShadersPath().string() + std::string("/") + vert, CEngineConfiguration::configuration->getGlobalShadersPath().string() + std::string("/") + frag); - - m_shadersMap.insert(std::pair(name, newShader)); + auto shader = CosmicUtils::CShaderFactory::create(itr->path().stem(), itr->path()); + shaders.push_back(std::move(shader)); + m_shadersMap.insert(std::make_pair(itr->path().stem(), shaders.back().get())); } catch (std::exception& e) { - throw CJsonException(std::string("Failed to parse and retrieve data from the json file ") + itr->path().string() + ": " + e.what()); + //throw CJsonException(std::string("Failed to parse and retrieve data from the json file ") + itr->path().string() + ": " + e.what()); } - - DEBUG_LOG(trace, "Kernel", "ShadersManager", "Shader : " + itr->path().string() + " successfully retrieved.") } } - - m_shaderList = (CShader**)malloc(sizeof(CShader*) * m_shadersMap.size()); - - if (m_shaderList == NULL) { - throw CRuntimeException("unable to alloc shaders list"); - } - - unsigned int i = 0; - - for (std::pair it : m_shadersMap) - { - m_shaderList[i] = it.second; - i++; - } - } else { - throw CFileException(std::string("Failed to find the shaders folder : ") + CKernel::m_kernel->getEngineConfig()->getGlobalShadersPath().string()); + //throw CFileException(std::string("Failed to find the shaders folder : ") + CKernel::m_kernel->getEngineConfig()->getGlobalShadersPath().string()); } } void CShadersManager::compile(void) { - DEBUG_LOG(trace, "Kernel", "ShadersManager", "Starting compiling shaders files."); - unsigned int nbShader = m_shadersMap.size(); - - for (unsigned int i = 0; i < nbShader; i++) + for (auto& el: shaders) { - m_shaderList[i]->init(); + el->init(); } - - DEBUG_LOG(trace, "Kernel", "ShadersManager", "All shaders are ready to use.") } \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Shader/CShadersManager.hpp b/src/Engine/Core/Graphics/Shader/CShadersManager.hpp index 6a4655a..cdcc762 100644 --- a/src/Engine/Core/Graphics/Shader/CShadersManager.hpp +++ b/src/Engine/Core/Graphics/Shader/CShadersManager.hpp @@ -1,68 +1,45 @@ #ifndef CSHADERSMANAGER_HPP #define CSHADERSMANAGER_HPP +#include #include -#include #include #include +#include -#include "../../Model/Graphic/Shader/CShader.hpp" -#include "../../Context/CContext.hpp" +#include "CShader.hpp" -#include "../Exception/CJsonException.hpp" -#include "../Exception/CFileException.hpp" -#include "../Exception/CRuntimeException.hpp" +#define SHADERS_FOLDER "assets/shaders/slang/spv" -/*#ifdef WIN32 - #define SHADERS_FOLDER "../assets/shaders" -#else - #define SHADERS_FOLDER "../../assets/shaders" -#endif*/ -/** - * @brief Class to manage shaders. - */ class CShadersManager { private: - /** - * @brief map to store in a proper way the shaders. - */ - std::map m_shadersMap; + std::list> shaders; + std::unordered_map m_shadersMap; - CShader** m_shaderList; public: - /** - * @brief constructor. - */ + CShadersManager(void); CShadersManager(const CShadersManager& param) = delete; - /** - * @brief destructor, destroy the shaders of the list. - */ ~CShadersManager(void); CShadersManager& operator=(const CShadersManager& param) = delete; - /** - * @brief get a shader by its name. - * @param[in] name shader name. - * @return the shader. - */ CShader* get(std::string name) const; - /** - * @brief compile and link all the shaders to make them ready to use. - */ + std::list>::const_iterator beginShaders(){return shaders.cbegin();}; + std::list>::const_iterator endShaders(){return shaders.cend();}; + void compile(void); - /** - * @brief search the folder assets/shaders and create the shaders specifieds by a json file. - * @post throw an FileException if the shaders folder is not found. - */ void create(void); + + void cleanup(){ + shaders.clear(); + } }; #endif \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.cpp b/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.cpp new file mode 100644 index 0000000..5802f6f --- /dev/null +++ b/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.cpp @@ -0,0 +1,106 @@ +#include "CShaderImplVulkan.hpp" +#include "vulkan/vulkan.hpp" +#include "../../API/GraphicsAPI.hpp" +#include +#include +#include +#include +#include + + +CShaderImplVulkan::CShaderImplVulkan(std::string name, std::filesystem::path spvPath): m_name(name), spirvPath(spvPath) +{ + +} + +std::string CShaderImplVulkan::getName(void) const { + return m_name; +} + +void CShaderImplVulkan::setName(std::string name) { + m_name = name; +} + +void CShaderImplVulkan::init() +{ + std::ifstream fileShader(spirvPath, std::ios::binary | std::ios::ate); + size_t fileSize = fileShader.tellg(); + fileShader.seekg(0); + + std::vector spirv(fileSize / sizeof(uint32_t)); + fileShader.read(reinterpret_cast(spirv.data()), fileSize); + //spirv.push_back('\0'); + //fileSize++; + fileShader.close(); + + vk::ShaderModuleCreateInfo createInfo{ {},fileSize,spirv.data() }; + shaderModule = vk::raii::ShaderModule(*static_cast(GraphicsAPI::getAPI()->getDevice()), createInfo); + + SpvReflectShaderModule module; + SpvReflectResult result = spvReflectCreateShaderModule( + spirv.size() * sizeof(uint32_t), + spirv.data(), + &module + ); + assert(result == SPV_REFLECT_RESULT_SUCCESS); + + uint32_t entryPointCount = module.entry_point_count; + for (uint32_t i = 0; i < entryPointCount; i++) { + const SpvReflectEntryPoint& entry = module.entry_points[i]; + + switch (entry.shader_stage) { + case SPV_REFLECT_SHADER_STAGE_VERTEX_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eVertex].push_back(entry.name); + break; + case SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eFragment].push_back(entry.name); + break; + case SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eGeometry].push_back(entry.name); + break; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eTessellationControl].push_back(entry.name); + break; + case SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eTessellationEvaluation].push_back(entry.name); + break; + case SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT: + stageEntryPoints[vk::ShaderStageFlagBits::eCompute].push_back(entry.name); + break; + default: + continue; + } + } + + spvReflectDestroyShaderModule(&module); +} + +void CShaderImplVulkan::setBool(const std::string& name, bool value) const +{ +} + +void CShaderImplVulkan::setInt(const std::string& name, int value) const +{ +} + +void CShaderImplVulkan::setFloat(const std::string& name, float value) const +{ +} + +void CShaderImplVulkan::setMat2(const std::string& name, glm::mat2 value) const { +} + +void CShaderImplVulkan::setMat3(const std::string& name, glm::mat3 value) const { +} + +void CShaderImplVulkan::setMat4(const std::string& name, glm::mat4 value) const { +} + +void CShaderImplVulkan::setVec2(const std::string& name, glm::vec2 value) const { +} + +void CShaderImplVulkan::setVec3(const std::string& name, glm::vec3 value) const { +} + +void CShaderImplVulkan::setVec4(const std::string& name, glm::vec4 value) const { +} \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.hpp b/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.hpp new file mode 100644 index 0000000..1cda4f7 --- /dev/null +++ b/src/Engine/Core/Graphics/Shader/Implementations/CShaderImplVulkan.hpp @@ -0,0 +1,99 @@ +#ifndef CSHADEROPENGLIMPLHPP +#define CSHADEROPENGLIMPLHPP + +#include "../CShader.hpp" +#include "vulkan/vulkan.hpp" + +#include +#include +#include +#include + +/** + * @file CShaderImplVulkan.hpp + * @brief File of CShaderImplVulkan, a Vulkan impl. of CShader to manage shader program. + */ + + /** + * @brief a Vulkan impl. of CShader to manage shader program. + */ +class CShaderImplVulkan : public CShader { +private: + + std::string m_name; + std::filesystem::path spirvPath; + vk::raii::ShaderModule shaderModule = nullptr; + vk::raii::Device* device = nullptr; + std::unordered_map> stageEntryPoints; + +public: + + CShaderImplVulkan() = delete; + + CShaderImplVulkan(std::string name, std::string vertexPath, std::string fragmentPath) = delete; + + CShaderImplVulkan(std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath) = delete; + + CShaderImplVulkan(std::string name, std::filesystem::path spvPath); + + virtual unsigned int getId(void) const {return 0;}; + + virtual std::string getName(void) const; + + virtual std::string getVertexPath(void) const {return "";}; + + virtual std::string getGeomPath(void) const{return "";}; + + virtual std::string getFragmentPath(void) const {return "";}; + + virtual void setName(std::string name); + + virtual void setVertexPath(std::string vp) {}; + + virtual void setGeomPath(std::string gp) {}; + + virtual void setFragmentPath(std::string fp) {}; + + virtual bool isReady(void) const {return true;}; + + virtual bool hasGeom(void) const {return true;}; + + virtual void use(void) {}; + + virtual void init(void); + + template + std::vector getShaderStages(unsigned int offset = 0, Flags... flagBits) + { + std::vector pipe; + for(auto el : std::initializer_list{ flagBits... }) + { + //todo assert exists + std::string& entry = stageEntryPoints[el][offset]; + vk::PipelineShaderStageCreateInfo info{{}, el, shaderModule, entry.c_str() };//todo check specialized info ? + pipe.push_back(info); + } + return pipe; + } + + virtual void setBool(const std::string& name, bool value) const; + + virtual void setInt(const std::string& name, int value) const; + + virtual void setFloat(const std::string& name, float value) const; + + virtual void setMat2(const std::string& name, glm::mat2 value) const; + + virtual void setMat3(const std::string& name, glm::mat3 value) const; + + virtual void setMat4(const std::string& name, glm::mat4 value) const; + + virtual void setVec2(const std::string& name, glm::vec2 value) const; + + virtual void setVec3(const std::string& name, glm::vec3 value) const; + + virtual void setVec4(const std::string& name, glm::vec4 value) const; +}; + + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CGameWindow.cpp b/src/Engine/Core/Graphics/Window/CGameWindow.cpp similarity index 69% rename from src/Engine/Core/Context/Window/CGameWindow.cpp rename to src/Engine/Core/Graphics/Window/CGameWindow.cpp index f1e5c78..db568ba 100644 --- a/src/Engine/Core/Context/Window/CGameWindow.cpp +++ b/src/Engine/Core/Graphics/Window/CGameWindow.cpp @@ -1,14 +1,16 @@ #include "CGameWindow.hpp" +#include +#include CGameWindow::CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen) : - CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_OPENGL), + CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_VULKAN), m_grabCursor(false), m_relativeCursor(false), m_msaa(0) { } CGameWindow::CGameWindow(std::string title, SDL_Window* window) : - CWindow(title, window, SDL_WINDOW_OPENGL, 0), + CWindow(title, window, SDL_WINDOW_VULKAN), m_grabCursor(false), m_relativeCursor(false), m_msaa(0) { @@ -17,18 +19,18 @@ CGameWindow::CGameWindow(std::string title, SDL_Window* window) : CGameWindow::~CGameWindow(void) { } -SDL_GLContext CGameWindow::getOpenGLContext(void) { +/*SDL_GLContext CGameWindow::getOpenGLContext(void) { if (getWindow() == nullptr) { - throw CLogicException("The window must be initialized before using this method !"); + //throw CLogicException("The window must be initialized before using this method !"); } else { SDL_GLContext out = SDL_GL_CreateContext(getWindow()); if (out == nullptr) { - throw CLibException(std::string("Unable to create OpenGL context: ") + SDL_GetError()); + //throw CLibException(std::string("Unable to create OpenGL context: ") + SDL_GetError()); } return out; } -} +}*/ bool CGameWindow::isCursorGrabbed(void) const { return m_grabCursor; @@ -43,10 +45,10 @@ void CGameWindow::setCursorGrabbed(bool newMouseGrab) { if (getWindow() != nullptr) { if (m_grabCursor) { - SDL_SetWindowGrab(getWindow(), SDL_TRUE); + SDL_SetWindowMouseGrab(getWindow(), true); } else { - SDL_SetWindowGrab(getWindow(), SDL_FALSE); + SDL_SetWindowMouseGrab(getWindow(), false); } } } @@ -64,10 +66,10 @@ void CGameWindow::setCursorRelative(bool newMouseRelative) { if (getWindow() != nullptr) { if (m_relativeCursor) { - SDL_SetRelativeMouseMode(SDL_TRUE); + SDL_SetWindowRelativeMouseMode(getWindow(), true); } else { - SDL_SetRelativeMouseMode(SDL_FALSE); + SDL_SetWindowRelativeMouseMode(getWindow(), false); } } } @@ -78,7 +80,7 @@ unsigned char CGameWindow::getAntiAliasing(void) const { void CGameWindow::setAntiAliasing(unsigned char newMsaa) { if (getWindow() != nullptr) { - throw CLogicException("The window must be uninitialized before using this method !"); + //throw CLogicException("The window must be uninitialized before using this method !"); } else { if (newMsaa == 2 || newMsaa == 4 || newMsaa == 8 || newMsaa == 16) { @@ -92,7 +94,7 @@ void CGameWindow::setAntiAliasing(unsigned char newMsaa) { void CGameWindow::preinitialization(void) { // We want OpenGL version 3.3. - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + /*SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); // Anti-aliasing Configuration. @@ -108,7 +110,8 @@ void CGameWindow::preinitialization(void) { SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Depht Buffer. - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);*/ + //TODO init graphic generic (opengl vulkan etc.... commence par vulkan ?) } @@ -116,17 +119,17 @@ void CGameWindow::postinitialization(void) { // Set the cursorGrab property. if (m_grabCursor) { - SDL_SetWindowGrab(getWindow(), SDL_TRUE); + SDL_SetWindowMouseGrab(getWindow(), true); } else { - SDL_SetWindowGrab(getWindow(), SDL_FALSE); + SDL_SetWindowMouseGrab(getWindow(), false); } // Set the cursorRelative property. if (m_relativeCursor) { - SDL_SetRelativeMouseMode(SDL_TRUE); + SDL_SetWindowRelativeMouseMode(getWindow(), true); } else { - SDL_SetRelativeMouseMode(SDL_FALSE); + SDL_SetWindowRelativeMouseMode(getWindow(), false); } } \ No newline at end of file diff --git a/src/Engine/Core/Graphics/Window/CGameWindow.hpp b/src/Engine/Core/Graphics/Window/CGameWindow.hpp new file mode 100644 index 0000000..734124e --- /dev/null +++ b/src/Engine/Core/Graphics/Window/CGameWindow.hpp @@ -0,0 +1,49 @@ +#ifndef CGAMEWINDOW_HPP +#define CGAMEWINDOW_HPP + +#include "CWindow.hpp" + +#include + +class CGameWindow : public CWindow { +private: + // Say if the mouse is grabbed. + bool m_grabCursor; + + // Say if the mouse is in relative mode. + bool m_relativeCursor; + + // The anti-aliasing. + unsigned char m_msaa; + +public: + CGameWindow(void) = delete; + CGameWindow(const CGameWindow& param) = delete; + CGameWindow& operator=(const CGameWindow& param) = delete; + + CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen); + + CGameWindow(std::string title, SDL_Window* window); + + ~CGameWindow(void); + + bool isCursorGrabbed(void) const; + + void setCursorGrabbed(bool newMouseGrab); + + bool isCursorRelative(void) const; + + void setCursorRelative(bool newMouseRelative); + + unsigned char getAntiAliasing(void) const; + + void setAntiAliasing(unsigned char newMsaa); + + virtual void preinitialization(); + + virtual void postinitialization(); + + //SDL_GLContext getOpenGLContext(void); +}; + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CLoadingWindow.cpp b/src/Engine/Core/Graphics/Window/CLoadingWindow.cpp similarity index 97% rename from src/Engine/Core/Context/Window/CLoadingWindow.cpp rename to src/Engine/Core/Graphics/Window/CLoadingWindow.cpp index f9607ff..8e75aa8 100644 --- a/src/Engine/Core/Context/Window/CLoadingWindow.cpp +++ b/src/Engine/Core/Graphics/Window/CLoadingWindow.cpp @@ -1,4 +1,4 @@ -#include "CLoadingWindow.hpp" +/*#include "CLoadingWindow.hpp" CLoadingWindow::CLoadingWindow(std::string title, std::string iconPath, std::string splashPath, unsigned int width, unsigned int height) : CWindow(title, iconPath, width, height, false, false, SDL_WINDOW_BORDERLESS | SDL_WINDOW_ALWAYS_ON_TOP), @@ -37,4 +37,4 @@ void CLoadingWindow::postinitialization(void) { SDL_RenderCopy(renderer, tex, NULL, NULL); SDL_RenderPresent(renderer); } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CLoadingWindow.hpp b/src/Engine/Core/Graphics/Window/CLoadingWindow.hpp similarity index 52% rename from src/Engine/Core/Context/Window/CLoadingWindow.hpp rename to src/Engine/Core/Graphics/Window/CLoadingWindow.hpp index 05b7130..957fc66 100644 --- a/src/Engine/Core/Context/Window/CLoadingWindow.hpp +++ b/src/Engine/Core/Graphics/Window/CLoadingWindow.hpp @@ -1,4 +1,4 @@ -#ifndef CLOADINGWINDOW_HPP +/*#ifndef CLOADINGWINDOW_HPP #define CLOADINGWINDOW_HPP #include "CWindow.hpp" @@ -17,14 +17,6 @@ #include #endif -/** - * @file CLoadingWindow.hpp - * @brief File of CWindow, a class reprensenting a loading Window, using SDL2 lib. - */ - -/** - * @brief Class reprensenting a loading Window, using SDL2 lib. - */ class CLoadingWindow : public CWindow { private: // The path to the splash image. @@ -38,30 +30,13 @@ public: CLoadingWindow(const CLoadingWindow& param) = delete; CLoadingWindow& operator=(const CLoadingWindow& param) = delete; - /** - * @brief The default constructor, build a non visible window with size of widthxheight. - * @param[in] title The title of the window. - * @param[in] iconPath The iconPath of the window. - * @param[in] splashPath The splashPath of the window. - * @param[in] width The width of the window. - * @param[in] height The height of the window. - */ CLoadingWindow(std::string title, std::string iconPath, std::string splashPath, unsigned int width, unsigned int height); - /** - * @brief The destructor. - */ ~CLoadingWindow(void); - /** - * @brief Launched before the creation of the window, usefull for setting OpenGL attribute. - */ virtual void preinitialization(); - /** - * @brief Launched after the creation of the window, usefull for setting others attribute. - */ virtual void postinitialization(); }; -#endif \ No newline at end of file +#endif*/ \ No newline at end of file diff --git a/src/Engine/Core/Context/Window/CWindow.cpp b/src/Engine/Core/Graphics/Window/CWindow.cpp similarity index 81% rename from src/Engine/Core/Context/Window/CWindow.cpp rename to src/Engine/Core/Graphics/Window/CWindow.cpp index e729a23..faf644e 100644 --- a/src/Engine/Core/Context/Window/CWindow.cpp +++ b/src/Engine/Core/Graphics/Window/CWindow.cpp @@ -1,20 +1,21 @@ #include "CWindow.hpp" - -CWindow::CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, unsigned int sdlFlags) : +#include +#include +#include "../API/GraphicsAPI.hpp" +CWindow::CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, SDL_WindowFlags sdlFlags) : m_title(title), m_iconPath(iconPath), m_size(width, height), - m_visible(false), m_fullscreen(fullscreen), + m_visible(false), m_resizable(resizable), m_sdlFlags(sdlFlags) { m_pwindow = nullptr; } -CWindow::CWindow(std::string title, SDL_Window* window, unsigned int sdlFlags, unsigned int imageFlags): m_sdlFlags(sdlFlags), m_size(600,400) +CWindow::CWindow(std::string title, SDL_Window* window, SDL_WindowFlags sdlFlags): m_title(title), m_size(600,400), m_sdlFlags(sdlFlags), m_pwindow(window) { - m_title = title; - m_pwindow = window; + } CWindow::~CWindow(void) { @@ -65,7 +66,7 @@ void CWindow::setIconPath(std::string newIconPath) { image = IMG_Load(m_iconPath.c_str()); if (image != nullptr) { SDL_SetWindowIcon(m_pwindow, image); - SDL_FreeSurface(image); + SDL_DestroySurface(image); } } } @@ -105,10 +106,10 @@ void CWindow::setResizable(bool newResizable) { m_resizable = newResizable; if (m_pwindow != nullptr) { if (m_resizable) { - SDL_SetWindowResizable(m_pwindow, SDL_TRUE); + SDL_SetWindowResizable(m_pwindow, true); } else { - SDL_SetWindowResizable(m_pwindow, SDL_FALSE); + SDL_SetWindowResizable(m_pwindow, true); } } } @@ -139,11 +140,11 @@ void CWindow::initialization(void) { preinitialization(); // Création de la fenetre. - m_pwindow = SDL_CreateWindow(m_title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_size.first, m_size.second, SDL_WINDOW_HIDDEN | m_sdlFlags); + m_pwindow = SDL_CreateWindow(m_title.c_str(), m_size.first, m_size.second, SDL_WINDOW_HIDDEN | m_sdlFlags); // Handle error. if (m_pwindow == nullptr) { - throw CLibException(std::string("Unable to create window: ") + SDL_GetError()); + //throw CLibException(std::string("Unable to create window: ") + SDL_GetError());//todo exceptions } // Set the icon. @@ -151,15 +152,18 @@ void CWindow::initialization(void) { image = IMG_Load(m_iconPath.c_str()); if (image != nullptr) { SDL_SetWindowIcon(m_pwindow, image); - SDL_FreeSurface(image); + SDL_DestroySurface(image); } + GraphicsAPI::getAPI()->init(m_pwindow); + + // Set the rezisable property. if (m_resizable) { - SDL_SetWindowResizable(m_pwindow, SDL_TRUE); + SDL_SetWindowResizable(m_pwindow, true); } else { - SDL_SetWindowResizable(m_pwindow, SDL_FALSE); + SDL_SetWindowResizable(m_pwindow, false); } // Set the fullscreen property. diff --git a/src/Engine/Core/Graphics/Window/CWindow.hpp b/src/Engine/Core/Graphics/Window/CWindow.hpp new file mode 100644 index 0000000..518be44 --- /dev/null +++ b/src/Engine/Core/Graphics/Window/CWindow.hpp @@ -0,0 +1,95 @@ +#ifndef CWINDOW_HPP +#define CWINDOW_HPP + +#include +#define SDL_MAIN_USE_CALLBACKS // This is necessary for the new callbacks API. To use the legacy API, don't define this. + +#include +#include +#include +#include +#include + +class CWindow { +private: + // The title of the window. + std::string m_title; + + // The path to the icon. + std::string m_iconPath; + + // First is the width, second is the height. + std::pair m_size; + + // Say if the window is fullscreen. + bool m_fullscreen; + + // Say if the window is visible. + bool m_visible; + + // Say if the window is resizable. + bool m_resizable; + + // SDL flags for creating the window. + SDL_WindowFlags m_sdlFlags; + + // The pointer to the window. + SDL_Window* m_pwindow; + +public: + CWindow(void) = delete; + CWindow(const CWindow& param) = delete; + CWindow& operator=(const CWindow& param) = delete; + + CWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen, SDL_WindowFlags sdlFlags); + + CWindow(std::string title, SDL_Window* window, SDL_WindowFlags sdlFlags); + + + ~CWindow(void); + + + SDL_Window* getWindow(void); + + void setWindow(SDL_Window* window){m_pwindow = window; }; + + bool isFullscreen(void) const; + + void setFullscreen(bool newFullscreen); + + bool isVisible(void) const; + + void setVisible(bool newVisible); + + std::string getIconPath(void) const; + + std::string getTitle(void) const; + + void setTitle(std::string newTitle); + + void setIconPath(std::string newIconPath); + + unsigned int getWidth(void) const; + + unsigned int getHeight(void) const; + + std::pair getSize(void) const; + + void setSize(std::pair newSize); + + void setSize(unsigned int newWidth, unsigned int newHeight); + + bool isResizable(void) const; + + void setResizable(bool newResizable); + + bool isInitialized(void) const; + + void initialization(); + + virtual void preinitialization() = 0; + + virtual void postinitialization() = 0; +}; + +#endif diff --git a/src/Engine/Core/Input/CInput.cpp b/src/Engine/Core/Input/CInput.cpp index 68d49be..d4d60a5 100644 --- a/src/Engine/Core/Input/CInput.cpp +++ b/src/Engine/Core/Input/CInput.cpp @@ -1,5 +1,5 @@ #include "CInput.hpp" - +/* #include "../CKernel.hpp" #include @@ -162,4 +162,4 @@ void CInput::onKKeyDown(unsigned int which) { void CInput::onKKeyUp(unsigned int which) { (void)which; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Core/Input/CInput.hpp b/src/Engine/Core/Input/CInput.hpp index b8ad516..54d8d0f 100644 --- a/src/Engine/Core/Input/CInput.hpp +++ b/src/Engine/Core/Input/CInput.hpp @@ -1,17 +1,17 @@ #ifndef CINPUT_HPP #define CINPUT_HPP -#include "../../Model/Input/CMouse.hpp" +/*#include "../../Model/Input/CMouse.hpp" #include "../../Model/Input/CKeyboard.hpp" #include "../../Model/Input/CController.hpp" #include "../Exception/CException.hpp" #include "../../Model/Observer/CKeyObserver.hpp" #include "../Exception/CExceptionManager.hpp" -#include "../CKernel.fwd.hpp" +#include "../CKernel.fwd.hpp"*/ -#include +/*#include #include -#include +#include */ /** * @file CInput.hpp @@ -21,38 +21,38 @@ /** * @brief Class to handle all input event. */ -class CInput : public CKeyObserver { -private: +/*class CInput : public CKeyObserver { +private:*/ // A pointer to the game. - CKernel* m_kernel; + //CKernel* m_kernel; // The event handler. - SDL_Event m_event; + //SDL_Event m_event; // The mouse model. - CMouse m_mouse; + //CMouse m_mouse; // The keyboard model. - CKeyboard m_keyboard; + //CKeyboard m_keyboard; // The controllers model, sorted by id. - std::map m_controllers; + //std::map m_controllers; -public: +/*public: CInput(void) = delete; CInput(const CInput& param) = delete; - CInput& operator=(const CInput& param) = delete; + CInput& operator=(const CInput& param) = delete;*/ /** * @brief The usage constructor. * @param[in] game A pointer to the game object, to handle specific event, like quit. */ - CInput(CKernel* game); + //CInput(CKernel* game); /** * @brief The destructor. */ - ~CInput(void); + //~CInput(void); /** * @brief Function to handle all event of the game, SDL and CGame must be initialized. This function is call once per game frame. @@ -63,38 +63,38 @@ public: * @brief The keyboard getter. * @return CKeyboard*, The keyboard. */ - CKeyboard* getKeyboard(void); + //CKeyboard* getKeyboard(void); /** * @brief The mouse getter. * @return CMouse*, The mouse. */ - CMouse* getMouse(void); + //CMouse* getMouse(void); /** * @brief The controller getter. * @param[in] id The id of the wanted controller. * @return CController*, The controller. */ - CController* getController(unsigned int id); + //CController* getController(unsigned int id); /** * @brief The controllers getter. * @return std::map, All the controllers, ordered by id. */ - std::map getControllers(void); + //std::map getControllers(void); /** * @brief Handle key down event. * @param[in] which The code of the key. */ - virtual void onKKeyDown(unsigned int which); + /*virtual void onKKeyDown(unsigned int which);*/ /** * @brief Handle key down event. * @param[in] which The code of the key. */ - virtual void onKKeyUp(unsigned int which); -}; + //virtual void onKKeyUp(unsigned int which); +//}; #endif \ No newline at end of file diff --git a/src/Engine/Core/Kernel/CKernel.cpp b/src/Engine/Core/Kernel/CKernel.cpp index e6e580a..66e26b9 100644 --- a/src/Engine/Core/Kernel/CKernel.cpp +++ b/src/Engine/Core/Kernel/CKernel.cpp @@ -1,16 +1,23 @@ #include "CKernel.hpp" -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "../../Configurations/Configuration/CConfiguration.hpp" -#include "../../Modules/Module/CModuleLoader.hpp" -#include "../Component/Graphics/CTestRenderer.hpp" -//CKernel* CKernel::m_kernel; +#include "../Graphics/CContext.hpp" +#include "../Graphics/API/GraphicsAPI.hpp" +#include "../Scene/CScene.hpp" +#include "../Entity/CEntity.hpp" +#include "../Component/Camera/CCamera.hpp" //CShader* CKernel::m_mainShader; // #define NAME "Cosmic Engine" -// #define LOGO "../assets/spaceEngineIcon.png" +#define LOGO "assets/spaceEngineIcon.png" // #define SPLASH "../assets/shrekt.png" // #define SPLASH_HEIGHT 512 // #define SPLASH_WIDTH 512 @@ -18,21 +25,19 @@ // #define GAME_WIDTH 640 namespace CosmicCore { + + CKernel* CKernel::m_kernel; CKernel::CKernel(std::string name, std::string gameName) : - m_gameName(gameName) + m_gameName(gameName), m_window(gameName, LOGO, 1270, 720, true, false) { - //m_kernel = this; - //CContext::init(SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC,IMG_INIT_PNG | IMG_INIT_JPG); - m_activeScene = std::make_unique("Scene1"); + m_kernel = this; + + CContext::init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC); } CKernel::~CKernel() { - /*for(std::pair& scenePair : m_sceneList) - { - delete scenePair.second; - }*/ } /*void CKernel::setContext(SDL_GLContext context) @@ -40,10 +45,10 @@ namespace CosmicCore { m_GLcontext = context; }*/ - /*CScene* CKernel::getActiveScene() + CScene* CKernel::getActiveScene() { return m_activeScene; - }*/ + } /*void CKernel::initGL() { @@ -59,11 +64,16 @@ namespace CosmicCore { void CKernel::start(bool isPreview) { //DEBUG_LOG(trace, "Kernel", "Context", "Starting " + m_gameName + "...") - CConfiguration::init(); + //CosmicConfig::CConfiguration::init(); //CComponentFactory::registerStandardProvidedAbstractComponents(); - std::cout << CModuleLoader::loadAll() << std::endl; + //std::cout << CModuleLoader::loadAll() << std::endl; if(!isPreview) { + m_window.initialization(); + + m_sceneMap["TestScene"] = std::make_unique("Scene1"); + m_activeScene = m_sceneMap["TestScene"].get(); + m_activeScene->addEntity("TestEntity", "Description"); // Open the splash window. //DEBUG_LOG(trace, "Kernel", "Context", "Loading splash window...") //m_loadingWindow.setVisible(true); @@ -131,88 +141,92 @@ namespace CosmicCore { } void CKernel::loop() { - while(1) - { - int addOrNot = 0; - std::cout << "Create test renderer to add to the scene via an entity ?" << std::endl; - std::cin >> addOrNot; - if(addOrNot == 1) - { - auto entity = m_activeScene->addEntity("test1", "testDesc"); - entity.addComponent(); - std::cout << "nb Entities : " << m_activeScene->getNumEntity() << std::endl; - } - else if(addOrNot == 2) - { - //m_activeScene.get()->getEntityComponentManager().getEntities().clear(); - //m_activeScene.get()->getEntityComponentManager().addComponent(m_activeScene.get()->getEntityComponentManager().getEntities().size()-1, EComponentType::COMPONENT_RENDERER); - } - m_activeScene->render(); - } - /*unsigned int frameRate(1000 / m_config.getTargetedFramerate()); + + unsigned int frameRate(1000 / 144); unsigned int beginIterationTime(0); unsigned int endIterationTime(0); unsigned int spendedIterationTime(0); unsigned int lastFrame = 0; - - // Activation du Depth Buffer - glEnable(GL_DEPTH_TEST); - - //lancement des scripts - unsigned int numEntities = m_activeScene->getNumEntity(); - for (unsigned int i = 0; i < numEntities; i++) - { - unsigned int numComponents = m_activeScene->getEntity(i)->getComponents(EComponentType::COMPONENT_SCRIPT).size(); - for (unsigned int j = 0; j < numComponents; j++) - { - ((CAbstractScript*)(m_activeScene->getEntity(i)->getComponents(EComponentType::COMPONENT_SCRIPT)[j]))->start(); - } - - } + m_window.setVisible(true); + m_window.setResizable(true); while (!m_finished) { // Define the starting time. beginIterationTime = SDL_GetTicks(); - + // Compute the delta time. unsigned int currentFrame = beginIterationTime; m_deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - + // Update event system. - m_inputHandler.updateEvent(); + //m_inputHandler.updateEvent(); // ####### start render ####### + + SDL_Event event; + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_EVENT_QUIT) + m_finished = true; + if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(m_window.getWindow())) + m_finished = true; + if (event.type == SDL_EVENT_KEY_DOWN) { + // Handle key press + SDL_Keycode keyPressed = event.key.key; + auto entities = m_activeScene->getECManager().registry.view(); + auto& ent = m_activeScene->getECManager().registry.get(entities.front()); + switch (keyPressed) { + case SDLK_Z: + ent.forward({0.0f, 0.0f, -0.05f}); + break; + case SDLK_Q: + ent.forward({-0.05f, 0.0f, 0.0f}); + break; + case SDLK_S: + ent.forward({0.0f, 0.0f, 0.05f}); + break; + case SDLK_D: + ent.forward({0.05f, 0.0f, 0.0f}); + break; + case SDLK_LCTRL: + ent.forward({0.0f, -0.05f, 0.0f}); + break; + case SDLK_LSHIFT: + ent.forward({0.0f, 0.05f, 0.0f}); + break; + default: + break; + } - // Nettoyage de l'�cran. - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Update des scripts. - m_activeScene->updateScript(); - - // Actualisation du monde physique. - //todo fonction wrap => pour rendre valide même si c'est pas ODE - dSpaceCollide(m_activeScene->getTangibleWorld()->getSpace(), m_activeScene->getTangibleWorld(), &(m_activeScene->getTangibleWorld())->callback); - m_activeScene->getTangibleWorld()->updateWorld(0.12f); - - - // Rendu. - m_activeScene->render(); - - // Actualisation de la fen�tre. - SDL_GL_SwapWindow(m_window.getWindow()); + // Process the key pressed + } + if(event.type == SDL_EVENT_MOUSE_MOTION) + { + auto entities = m_activeScene->getECManager().registry.view(); + auto& ent = m_activeScene->getECManager().registry.get(entities.front()); + static const float sensitivity = 0.1f; + // yaw : rotation autour de Y global (axe monde) + ent.rotate(glm::vec3(0.0f, 1.0f, 0.0f), glm::radians(-event.motion.xrel * sensitivity)); + + // pitch : rotation autour de X local (axe de la caméra) + ent.rotate(glm::vec3(1.0f, 0.0f, 0.0f), glm::radians(-event.motion.yrel * sensitivity)); + } + } + if(m_activeScene) + GraphicsAPI::getAPI()->drawFrame(); // ####### end render ####### // Compute the end and spended time . endIterationTime = SDL_GetTicks(); - spendedIterationTime = endIterationTime - beginIterationTime; + spendedIterationTime = endIterationTime - beginIterationTime; // If need, we pause the programm to have the right fps amount. if (spendedIterationTime < frameRate) { SDL_Delay(frameRate - spendedIterationTime); } } - if(m_isOriginOfContext) - CContext::quit();*/ + GraphicsAPI::getAPI()->cleanup(); + CContext::quit(); } void CKernel::quit() { diff --git a/src/Engine/Core/Kernel/CKernel.hpp b/src/Engine/Core/Kernel/CKernel.hpp index 62da794..f52b75e 100644 --- a/src/Engine/Core/Kernel/CKernel.hpp +++ b/src/Engine/Core/Kernel/CKernel.hpp @@ -8,7 +8,7 @@ #include //#include "../Context/CContext.hpp" -//#include "../Context/Window/CGameWindow.hpp" +#include "../Graphics/Window/CGameWindow.hpp" //#include "../Context/Window/CLoadingWindow.hpp" //#include "../Controller/Configuration/CGameConfiguration.hpp" @@ -46,15 +46,15 @@ namespace CosmicCore { // The windows. //CLoadingWindow m_loadingWindow; - //CGameWindow m_window; - + CGameWindow m_window; + // Global game var. bool m_finished; unsigned int m_deltaTime; // The Scenes. - std::unique_ptr m_activeScene; - //std::map m_sceneList; + CScene* m_activeScene; + std::map> m_sceneMap; //CInput m_inputHandler; //SDL_GLContext m_GLcontext; @@ -66,7 +66,7 @@ namespace CosmicCore { /** * @brief A pointer to the simulation which is accessible from anywhere. */ - //static CKernel* m_kernel; + static CKernel* m_kernel; /** * @brief A pointer to the shader used, accessible from anywhere. @@ -86,7 +86,8 @@ namespace CosmicCore { //void addScene(std::shared_ptr& scene); //void setActiveScene(std::string scene); //void setContext(SDL_GLContext context); - //CScene* getActiveScene(); + CScene* getActiveScene(); + void cleanup(){m_sceneMap.clear();}; //unsigned int getNbScene() { return m_sceneList.size(); }; //std::map& getScenes() { return m_sceneList; }; diff --git a/src/Engine/Core/Scene/CScene.cpp b/src/Engine/Core/Scene/CScene.cpp index 7fdc0bf..84eca9a 100644 --- a/src/Engine/Core/Scene/CScene.cpp +++ b/src/Engine/Core/Scene/CScene.cpp @@ -1,9 +1,15 @@ #include "CScene.hpp" -#include "nlohmann/json_fwd.hpp" -#include "../Component/Graphics/CTestRenderer.hpp" -//#include "../../Controller/Exception/CRuntimeException.hpp" -//#include "Components/CAbstractScript.hpp" +#include "../Entity/CEntity.hpp" +#include "../Component/Graphics/CRenderer.hpp" +#include "../Component/Meta/CMetaData.hpp" +#include "../Component/Geometry/CTransform.hpp" +#include "../Component/Camera/CCamera.hpp" +#include "../Component/Relationships/CRelationship.hpp" +#include "../Graphics/API/GraphicsAPI.hpp" +#include "../Graphics/Data/CModelLoader.hpp" +#include +#include namespace CosmicCore { CScene::CScene(std::string name) : CSerializable(), @@ -15,8 +21,52 @@ namespace CosmicCore { return m_name; } + CEntity CScene::addEntity(std::string name, std::string description){ + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + + auto handle = m_ecManager.registry.create(); + CEntity handler(m_ecManager, handle, this); + m_ecManager().emplace(handle, handler); + m_ecManager().emplace(handle, handler, std::move(name), std::move(description)); + + auto& rM = GraphicsAPI::getAPI()->getResourceManager(); + + auto model = CModelLoader::loadModel("assets/models/cube.glb", rM); + + rM.getTextureManager().loadedTextures.push_back(std::make_unique("assets/shrekt.png")); + auto texture = rM.getTextureManager().loadedTextures.back().get(); + texture->init(); + for(auto& mesh : model->getMeshes()) + { + mesh->getMaterial()->textureAlbedo = texture; + mesh->getMaterial()->build(); + } + + m_ecManager().emplace(handle, handler, model); + auto& tr = m_ecManager.registry.get(handle); + tr.initUniformBuffer(dynamic_cast(GraphicsAPI::getAPI().get())->getAllocator()); + tr.updateUniformBuffer(0); + tr.updateUniformBuffer(1); + + auto camHandle = m_ecManager.registry.create(); + CEntity handlerCam(m_ecManager, camHandle, this); + + auto& transform = m_ecManager().emplace(camHandle, handlerCam); + auto& cam = m_ecManager.registry.emplace(camHandle, handlerCam); + + m_ecManager.registry.emplace(camHandle, handlerCam, std::vector{handle}); + m_ecManager.registry.emplace(handle, handler, camHandle); + + transform.setCenter({0.0f, 0.9f, 3.0f}); + cam.setAspect((float)api->getSwapChainExtent().width / api->getSwapChainExtent().height); + cam.initUniformBuffer(api->getAllocator()); + cam.updateUniformBuffer(0, transform); + cam.updateUniformBuffer(1, transform); + return handler; + } + unsigned int CScene::getNumEntity(void) const { - return this->m_ecManager.view()->size(); + return m_ecManager().view()->size(); } void CScene::removeEntity(unsigned int index, bool destroy) @@ -24,24 +74,57 @@ namespace CosmicCore { } - void CScene::render(){ - auto renderers = m_ecManager.view(); - for(auto beg = renderers->begin(); beg != renderers->end(); ++beg) - { - beg->render(); - } - //std::chrono::steady_clock::time_point begin1 = std::chrono::steady_clock::now(); - //auto eh = m_ecManager.create(); - //m_ecManager.emplace(eh, nullptr); - //std::chrono::steady_clock::time_point end1 = std::chrono::steady_clock::now(); - //std::cout << "added entity and comptest : " <(end1 - begin1).count() << std::endl; - //static unsigned int entitynb = 0; - //entitynb++; - //std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - //m_ecManager.view().each([](auto e, CTestRenderer& comp){comp.render();}); - //std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - //std::cout << "render func : " << std::chrono::duration_cast(end - begin).count() << std::endl; - //std::cout << "nb : " << entitynb << std::endl; + void CScene::render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex){ + auto entities = m_ecManager.registry.view(); + VulkanImpl* api = dynamic_cast(GraphicsAPI::getAPI().get()); + auto cam = m_ecManager.registry.view(); + auto& camera = m_ecManager.registry.get(cam.front()); + auto& transform = m_ecManager.registry.get(cam.front()); + + camera.updateUniformBuffer(frameIndex, transform); + + cmd.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + api->getDefaultPipelineLayout(), // layout du pipeline + 0, + *camera.getDescriptorSet(frameIndex), + {} + ); + + for (auto& entity : entities) { + auto model = m_ecManager.registry.get(entity).getModel(); + auto& transform = m_ecManager.registry.get(entity); + + transform.updateUniformBuffer(frameIndex); + //trier meshes par matérial ? + + // bind transform UBO (set = 1) + cmd.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + api->getDefaultPipelineLayout(), // layout du pipeline + 1, // set = 1 + *transform.getDescriptorSet(frameIndex), + {} + ); + + for (auto& mesh : model->getMeshes()) { + // ne rebind le pipeline que si le material change + //if (mesh.getMaterial() != boundMaterial) { + //boundMaterial = mesh.getMaterial(); + cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, + *mesh->getMaterial()->getPipeline()); + cmd.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, + *mesh->getMaterial()->getPipelineLayout(), + 2, + *mesh->getMaterial()->getDescriptorSet(frameIndex), + {}); + //} + + cmd.bindVertexBuffers(0, vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getVertexOffset()); + cmd.bindIndexBuffer(vk::Buffer(mesh->getVertexIndexBuffer().buffer), mesh->getIndexOffset(), vk::IndexType::eUint32); + cmd.drawIndexed(mesh->getIndexCount(), 1, 0, 0, 0); + } + } } // void CScene::setMask(unsigned int mask) diff --git a/src/Engine/Core/Scene/CScene.hpp b/src/Engine/Core/Scene/CScene.hpp index b40c7ef..95ce703 100644 --- a/src/Engine/Core/Scene/CScene.hpp +++ b/src/Engine/Core/Scene/CScene.hpp @@ -1,37 +1,32 @@ #ifndef CSCENE_HPP #define CSCENE_HPP -#include "../Component/Geometry/CTransform.hpp" -#include "../Component/Meta/CMetaData.hpp" - -#include +#include "../Systems/EntityComponentManager.hpp" +#include "../Utils/CSerializable.hpp" #include +#include -namespace CosmicCore {; +namespace CosmicCore { + class CEntity; class CScene : public CSerializable { - using ECManager = entt::registry; private: // The name of the scene. std::string m_name; - ECManager m_ecManager; - + EntityComponentManager m_ecManager; + public: CScene() = delete; CScene(std::string name); - ~CScene() = default; + virtual ~CScene() = default; unsigned int getNumEntity() const; - CEntity addEntity(std::string name, std::string description){ - auto handle = m_ecManager.create(); - CEntity handler(m_ecManager, handle); - m_ecManager.emplace(handle, handler); - m_ecManager.emplace(handle, handler, std::move(name), std::move(description)); - return handler; - } + CEntity addEntity(std::string name, std::string description); std::string getName() const; + EntityComponentManager& getECManager(){return m_ecManager;}; + void removeEntity(unsigned int index, bool destroy = true); //CEntity* getActiveCamera(); @@ -73,7 +68,7 @@ namespace CosmicCore {; */ //unsigned int getMask(); - void render(); + void render(vk::raii::CommandBuffer& cmd, uint32_t frameIndex); //void updateScript(); nlohmann::json to_json(); diff --git a/src/Engine/Core/Systems/EntityComponentManager.hpp b/src/Engine/Core/Systems/EntityComponentManager.hpp new file mode 100644 index 0000000..ebb1679 --- /dev/null +++ b/src/Engine/Core/Systems/EntityComponentManager.hpp @@ -0,0 +1,26 @@ +#ifndef ENTITYCOMPONENTMANAGER_HPP +#define ENTITYCOMPONENTMANAGER_HPP + +#include + +namespace CosmicCore { + + using ECManager = entt::registry; + using EntityId = entt::entity; + + class EntityComponentManager{ + public: + ECManager registry; + ECManager& operator()(){ + return registry; + } + + const ECManager& operator()() const { + return registry; + } + }; +}; + + + +#endif \ No newline at end of file diff --git a/src/Engine/Core/Utils/File/CFileManager.cpp b/src/Engine/Core/Utils/File/CFileManager.cpp index f061721..a88c2f5 100644 --- a/src/Engine/Core/Utils/File/CFileManager.cpp +++ b/src/Engine/Core/Utils/File/CFileManager.cpp @@ -1,6 +1,6 @@ #include "CFileManager.hpp" -void CFileManager::open(const char mode) { +/*void CFileManager::open(const char mode) { DEBUG_LOG(trace, "Kernel", "FileManager", "file " + m_filePath + " opened.") switch (mode) { @@ -59,4 +59,4 @@ std::string CFileManager::read(void) { close(); return out; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Core/Utils/File/CFileManager.hpp b/src/Engine/Core/Utils/File/CFileManager.hpp index 6ecd846..f451c6a 100644 --- a/src/Engine/Core/Utils/File/CFileManager.hpp +++ b/src/Engine/Core/Utils/File/CFileManager.hpp @@ -1,14 +1,8 @@ #ifndef CFILEMANAGER_HPP #define CFILEMANAGER_HPP -#include "../Exception/CFileException.hpp" -#include "../../Context/CContext.hpp" - #include #include -#include - - /** * @file CFileManager.hpp diff --git a/src/Engine/Core/Utils/File/CModelLoader.cpp b/src/Engine/Core/Utils/File/CModelLoader.cpp deleted file mode 100644 index 270ca1e..0000000 --- a/src/Engine/Core/Utils/File/CModelLoader.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "CModelLoader.hpp" -#include - -CModel* CModelLoader::loadModel(std::string fileName, SMaterial* material) -{ - Assimp::Importer import; - const aiScene* scene = import.ReadFile(fileName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_JoinIdenticalVertices); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - std::cout << std::string(import.GetErrorString()) << std::endl; - DEBUG_LOG(trace, "Kernel", "ModelLoader", std::string("Assimp error : ") + std::string(import.GetErrorString())) - return nullptr; - } - - std::vector meshes; - processNode(scene->mRootNode, scene, &meshes, material); - - CModel* model = new CModel(meshes); - model->load(); - return model; -} - -void CModelLoader::processNode(aiNode* node, const aiScene* scene, std::vector* meshes, SMaterial* material) -{ - // process all the node's meshes (if any) - for (unsigned int i = 0; i < node->mNumMeshes; i++) - { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - processMesh(mesh, scene, meshes, material); - } - // then do the same for each of its children - for (unsigned int i = 0; i < node->mNumChildren; i++) - { - processNode(node->mChildren[i], scene, meshes, material); - } -} - -void CModelLoader::processMesh(aiMesh* mesh, const aiScene* scene, std::vector* meshes, SMaterial* material) -{ - std::vector vertices; - std::vector indices; - SVertex vertex; - for (unsigned int i = 0; i < mesh->mNumVertices; i++) - { - vertex.m_position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); - vertex.m_normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); - - if (mesh->mTextureCoords[0]) // if the mesh contains texture coordinates - { - vertex.m_texCoords.x = mesh->mTextureCoords[0][i].x; - vertex.m_texCoords.y = mesh->mTextureCoords[0][i].y; - } - else - { - vertex.m_texCoords = glm::vec2(0.0f, 0.0f); - } - - if (mesh->mBitangents)// if the mesh contains bitangent coordinates - { - vertex.m_bitangent.x = mesh->mBitangents->x; - vertex.m_bitangent.y = mesh->mBitangents->y; - vertex.m_bitangent.z = mesh->mBitangents->z; - } - else - { - vertex.m_bitangent = glm::vec3(0.0f, 0.0f, 0.0f); - } - - if (mesh->mTangents)// if the mesh contains tangent coordinates - { - vertex.m_tangent.x = mesh->mTangents->x; - vertex.m_tangent.y = mesh->mTangents->y; - vertex.m_tangent.z = mesh->mTangents->z; - } - else - { - vertex.m_tangent = glm::vec3(0.0f, 0.0f, 0.0f); - } - - vertices.push_back(vertex); - } - // process indices - - for (unsigned int i = 0; i < mesh->mNumFaces; i++) - { - aiFace face = mesh->mFaces[i]; - for (unsigned int j = 0; j < face.mNumIndices; j++) - indices.push_back(face.mIndices[j]); - } - // process material - std::vector diffuseMaps; - std::vector specularMaps; - std::vector textures; - SMaterial* mat = new SMaterial; - if (mesh->mMaterialIndex >= 0 && material == nullptr) - { - aiMaterial* amaterial = scene->mMaterials[mesh->mMaterialIndex]; - diffuseMaps = loadMaterialTextures(amaterial, - aiTextureType_DIFFUSE, ETextureType::TEXTURE_DIFFUSE); - specularMaps = loadMaterialTextures(amaterial, - aiTextureType_SPECULAR, ETextureType::TEXTURE_SPECULAR); - - for (size_t i = 0; i < diffuseMaps.size(); i++) - { - textures.push_back((CAbstractTexture*)diffuseMaps[i]); - } - for (size_t j = 0; j < specularMaps.size(); j++) - { - textures.push_back((CAbstractTexture*)specularMaps[j]); - } - std::vector colorsC; //= { {glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), EColorType::COLOR_DIFFUSE} }; - aiColor4D color(0.0f, 0.0f, 0.0f, 0.0f); - amaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color); - SColor diffuseColor = { glm::vec4(color.r, color.g, color.b, color.a), EColorType::COLOR_DIFFUSE }; - colorsC.push_back(diffuseColor); - - *mat = { textures, colorsC, CKernel::m_mainShader }; - } - else// if the material is given, override the material of the wavefront obj file - { - delete mat; - mat = material; - } - - - CMesh* m = new CMesh(); - - m->setMaterial(mat); - - m->setIndexes(indices); - m->setVertices(vertices); - - meshes->push_back(m); - -} - -std::vector CModelLoader::loadMaterialTextures(aiMaterial* mat, aiTextureType type, ETextureType typeName) -{ - std::vector textures; - for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) - { - aiString str; - mat->GetTexture(type, i, &str); - CImageTexture* text = new CImageTexture(typeName, str.C_Str()); - text->init();//Load the texture in GPU before adding it the texture list - textures.push_back(text); - } - return textures; -} \ No newline at end of file diff --git a/src/Engine/Modules/Module/CModuleLoader.cpp b/src/Engine/Modules/Module/CModuleLoader.cpp index 257f20f..8faa366 100644 --- a/src/Engine/Modules/Module/CModuleLoader.cpp +++ b/src/Engine/Modules/Module/CModuleLoader.cpp @@ -1,5 +1,5 @@ #include "CModuleLoader.hpp" -namespace CosmicCore { +/*namespace CosmicCore { std::vector CModuleLoader::handles; -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/src/Engine/Modules/Module/CModuleLoader.hpp b/src/Engine/Modules/Module/CModuleLoader.hpp index 4f25037..f0214c7 100644 --- a/src/Engine/Modules/Module/CModuleLoader.hpp +++ b/src/Engine/Modules/Module/CModuleLoader.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "../Configuration/CConfiguration.hpp" +/*#include "../../../Configurations/Configuration/CConfiguration.hpp" namespace CosmicCore { class CModuleLoader { @@ -62,5 +62,5 @@ namespace CosmicCore return 0; } }; -} +}*/ #endif diff --git a/src/Engine/Utils/Factory/CShaderFactory.cpp b/src/Engine/Utils/Factory/CShaderFactory.cpp index 92ebbb9..3acd272 100644 --- a/src/Engine/Utils/Factory/CShaderFactory.cpp +++ b/src/Engine/Utils/Factory/CShaderFactory.cpp @@ -1,36 +1,5 @@ #include "CShaderFactory.hpp" -#include "../CKernel.hpp" -#include "../../Specific/Graphic/OpenGLImpl/CShaderOpenGLImpl.hpp" -CShader* CShaderFactory::createShader(CKernel* e, std::string name, std::string vertexPath, std::string fragmentPath) { - if (e == nullptr) { - throw CLogicException("CKernel is null"); - } - return createShader(e->getEngineConfig()->getGraphicImplementation(), name, vertexPath, fragmentPath); -} - -CShader* CShaderFactory::createShader(CKernel* e, std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath) { - if (e == nullptr) { - throw CLogicException("CKernel is null"); - } - return createShader(e->getEngineConfig()->getGraphicImplementation(), name, vertexPath, fragmentPath, geomPath); -} - -CShader* CShaderFactory::createShader(EGraphicImplementation e, std::string name, std::string vertexPath, std::string fragmentPath) { - switch (e) { - case EGraphicImplementation::GRAPHIC_OPENGL: - return new CShaderOpenGLImpl(name, vertexPath, fragmentPath); - break; - } - throw CLogicException("Unexpected error while creating shader"); - -} - -CShader* CShaderFactory::createShader(EGraphicImplementation e, std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath) { - switch (e) { - case EGraphicImplementation::GRAPHIC_OPENGL: - return new CShaderOpenGLImpl(name, vertexPath, fragmentPath, geomPath); - break; - } - throw CLogicException("Unexpected error while creating shader"); +namespace CosmicUtils { + GraphicsBackend CShaderFactory::m_backend = GraphicsBackend::Vulkan; } \ No newline at end of file diff --git a/src/Engine/Utils/Factory/CShaderFactory.hpp b/src/Engine/Utils/Factory/CShaderFactory.hpp index b7444f0..21427c8 100644 --- a/src/Engine/Utils/Factory/CShaderFactory.hpp +++ b/src/Engine/Utils/Factory/CShaderFactory.hpp @@ -1,18 +1,27 @@ #ifndef CSHADERFACTORY_HPP #define CSHADERFACTORY_HPP -#include "../Configuration/EImplementations.hpp" -#include "../../Model/Graphic/Shader/CShader.hpp" -#include "../CKernel.fwd.hpp" +#include "../../Core/Graphics/Shader/CShader.hpp" +#include "../../Core/Graphics/API/GraphicsAPI.hpp" +#include "../../Core/Graphics/Shader/Implementations/CShaderImplVulkan.hpp" -namespace CShaderFactory { - CShader* createShader(CKernel* e, std::string name, std::string vertexPath, std::string fragmentPath); +#include +#include +#include +namespace CosmicUtils { - CShader* createShader(EGraphicImplementation e, std::string name, std::string vertexPath, std::string fragmentPath); - - CShader* createShader(CKernel* e, std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath); - - CShader* createShader(EGraphicImplementation e, std::string name, std::string vertexPath, std::string fragmentPath, std::string geomPath); + class CShaderFactory{ + static GraphicsBackend m_backend; + public: + static std::unique_ptr create(std::string name, std::filesystem::path path) { + switch (m_backend) { + case GraphicsBackend::Vulkan: return std::make_unique(name, path); + case GraphicsBackend::OpenGL: return nullptr; + case GraphicsBackend::Metal: return nullptr; + break; + } + } + }; } #endif \ No newline at end of file diff --git a/src/Engine/Utils/Factory/ComponentFactory.cpp b/src/Engine/Utils/Factory/ComponentFactory.cpp index ef378f4..91889d0 100644 --- a/src/Engine/Utils/Factory/ComponentFactory.cpp +++ b/src/Engine/Utils/Factory/ComponentFactory.cpp @@ -1,6 +1,6 @@ #include "ComponentFactory.hpp" -namespace CosmicCore { +/*namespace CosmicCore { CComponentFactory& globalComponentFactory = CComponentFactory::instance(); CComponentFactory& CComponentFactory::instance() { @@ -8,4 +8,4 @@ namespace CosmicCore { return factory; } } - +*/ diff --git a/src/Engine/Utils/Factory/ComponentFactory.hpp b/src/Engine/Utils/Factory/ComponentFactory.hpp index 3d3b743..b5c6244 100644 --- a/src/Engine/Utils/Factory/ComponentFactory.hpp +++ b/src/Engine/Utils/Factory/ComponentFactory.hpp @@ -6,10 +6,10 @@ #include #include #include -#include "../Component/CAbstractComponent.hpp" +//#include "../Component/CAbstractComponent.hpp" //TODO modifier pour la scène soit obligatoire, sans scène pas d'entité, sans entité pas de composants -namespace CosmicCore +/*namespace CosmicCore { class CEntity; class CComponentFactory { @@ -91,5 +91,5 @@ namespace CosmicCore extern CComponentFactory& globalComponentFactory; } - +*/ #endif diff --git a/src/main.cpp b/src/main.cpp index 0ad2f95..d398020 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,6 @@ int main(int argc, char** argv) { // test(); using namespace CosmicCore; CKernel g("Mon jeu", "Jeu"); - //CScene s("Scene1"); g.start(); g.loop(); diff --git a/test/main.cpp b/test/main.cpp index 6429b75..70c5714 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -27,12 +27,12 @@ TEST_CASE("Entity component manager", "[ECManager]") { //scene.addEntity(entity2); //REQUIRE(!scene.getEntity(0).expired()); - CosmicCore::CEntityComponentManager eM; + /*CosmicCore::CEntityComponentManager eM; eM.getEntities().emplace_back("name"); REQUIRE(!eM.getEntities().empty()); REQUIRE(eM.getEntities()[0].value().get().getName() == "name"); eM.getEntities().erase(0); REQUIRE(eM.getEntities().empty()); - REQUIRE(!eM.getEntities()[0].has_value()); + REQUIRE(!eM.getEntities()[0].has_value());*/ }