├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── ShaderClockHeatmap.jpg ├── cmake ├── compilers_minimal.cmake ├── download_glew.cmake ├── download_glfw.cmake ├── download_glslang.cmake ├── download_spirvcross.cmake ├── download_vk.cmake ├── main.cpp └── project_template.cmake ├── shader_trace ├── CMakeLists.txt ├── include │ └── ShaderTrace.h └── source │ ├── Common.h │ ├── InsertFunctionProfiler.cpp │ ├── InsertShaderClockHeatmap.cpp │ ├── InsertTraceRecording.cpp │ ├── ParseShaderTrace.cpp │ ├── ShaderTrace.cpp │ └── Utils.cpp └── tests ├── opengl ├── CMakeLists.txt ├── ShaderCompiler.cpp ├── ShaderCompiler.h ├── ShaderPerf_Test1.cpp ├── ShaderTrace_Test1.cpp └── main.cpp ├── ref ├── ShaderTrace_Test1.txt ├── ShaderTrace_Test10.txt ├── ShaderTrace_Test11.txt ├── ShaderTrace_Test12.txt ├── ShaderTrace_Test13.txt ├── ShaderTrace_Test14.txt ├── ShaderTrace_Test2.txt ├── ShaderTrace_Test4.txt ├── ShaderTrace_Test5.txt ├── ShaderTrace_Test6.txt ├── ShaderTrace_Test7.txt ├── ShaderTrace_Test8.txt └── ShaderTrace_Test9.txt ├── utils ├── Utils.cpp └── Utils.h └── vulkan ├── CMakeLists.txt ├── ClockMap_Test1.cpp ├── ClockMap_Test2.cpp ├── Device.cpp ├── Device.h ├── ShaderPerf_Test1.cpp ├── ShaderTrace_Test1.cpp ├── ShaderTrace_Test10.cpp ├── ShaderTrace_Test11.cpp ├── ShaderTrace_Test12.cpp ├── ShaderTrace_Test13.cpp ├── ShaderTrace_Test14.cpp ├── ShaderTrace_Test2.cpp ├── ShaderTrace_Test3.cpp ├── ShaderTrace_Test4.cpp ├── ShaderTrace_Test5.cpp ├── ShaderTrace_Test6.cpp ├── ShaderTrace_Test7.cpp ├── ShaderTrace_Test8.cpp ├── ShaderTrace_Test9.cpp ├── VulkanLoader.cpp ├── VulkanLoader.h ├── fn_vulkan_dev.h ├── fn_vulkan_inst.h ├── fn_vulkan_lib.h └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.glsl_dbg 3 | /build 4 | glslang 5 | SPIRV-Cross 6 | GLFW 7 | GLEW 8 | Vulkan-Headers 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | matrix: 3 | include: 4 | # Linux GCC x64 5 | - os: linux 6 | name: linux64 GCC 8 7 | dist: xenial 8 | addons: 9 | apt: 10 | sources: 11 | - ubuntu-toolchain-r-test 12 | packages: 13 | - xorg-dev 14 | - g++-8 15 | before_install: 16 | - eval "CC=gcc-8 && CXX=g++-8" 17 | # Download and install cmake 18 | - mkdir $HOME/cmake; 19 | - export PATH="$HOME/cmake/bin:$PATH"; 20 | - travis_retry wget -q https://cmake.org/files/v3.15/cmake-3.15.1-Linux-x86_64.sh; 21 | - sh cmake-3.15.1-Linux-x86_64.sh --prefix=$HOME/cmake --exclude-subdir --skip-license; 22 | script: 23 | - mkdir -p build 24 | - cd build 25 | - cmake -DCMAKE_BUILD_TYPE=Release -DCI_BUILD=ON .. 26 | - cmake --build . --config Release 27 | 28 | # Windows MSVC x86 29 | - os: windows 30 | name: win32 31 | language: shell 32 | before_install: 33 | - choco install python --version 3.7.0 34 | - python -m pip install --upgrade pip 35 | env: PATH=/c/Python37:/c/Python37/Scripts:$PATH 36 | install: pip3 install --upgrade pip 37 | script: 38 | - mkdir -p build 39 | - cd build 40 | - cmake -G "Visual Studio 15 2017" -DCI_BUILD=ON .. 41 | - cmake --build . --config Release 42 | 43 | # Windows MSVC x64 44 | - os: windows 45 | name: win64 46 | language: shell 47 | before_install: 48 | - choco install python --version 3.7.0 49 | - python -m pip install --upgrade pip 50 | env: PATH=/c/Python37:/c/Python37/Scripts:$PATH 51 | install: pip3 install --upgrade pip 52 | script: 53 | - mkdir -p build 54 | - cd build 55 | - cmake -G "Visual Studio 15 2017 Win64" -DCI_BUILD=ON .. 56 | - cmake --build . --config Release 57 | 58 | # Windows MSVC x64 Debug 59 | - os: windows 60 | name: win64 debug 61 | language: shell 62 | before_install: 63 | - choco install python --version 3.7.0 64 | - python -m pip install --upgrade pip 65 | env: PATH=/c/Python37:/c/Python37/Scripts:$PATH 66 | install: pip3 install --upgrade pip 67 | script: 68 | - mkdir -p build 69 | - cd build 70 | - cmake -G "Visual Studio 15 2017 Win64" -DCI_BUILD=ON .. 71 | - cmake --build . --config Debug 72 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.10 FATAL_ERROR ) 2 | 3 | message( STATUS "==========================================================================\n" ) 4 | message( STATUS "project 'GLSL-Trace' generation started" ) 5 | 6 | project( "GLSL-Trace" LANGUAGES C CXX ) 7 | set_property( GLOBAL PROPERTY USE_FOLDERS ON ) 8 | message( STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER_VERSION})" ) 9 | message( STATUS "target system: ${CMAKE_SYSTEM_NAME} (${CMAKE_SYSTEM_VERSION})" ) 10 | message( STATUS "host system: ${CMAKE_HOST_SYSTEM_NAME} (${CMAKE_HOST_SYSTEM_VERSION})" ) 11 | 12 | set( EXTERNALS_USE_STABLE_VERSIONS ON CACHE BOOL "use last stable version instead of master branch" ) 13 | set( ENABLE_TESTS ON CACHE BOOL "tests" ) 14 | 15 | set( CMAKE_DEBUG_POSTFIX "d" ) 16 | set( CMAKE_RELEASE_POSTFIX "" ) 17 | set( CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "installation directory" FORCE ) 18 | set( MAIN_BINARY_DIR "${CMAKE_BINARY_DIR}/bin" CACHE INTERNAL "" FORCE ) 19 | set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${MAIN_BINARY_DIR}" ) 20 | set( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${MAIN_BINARY_DIR}" ) 21 | set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${MAIN_BINARY_DIR}" ) 22 | set( EXTERNALS_PATH "${CMAKE_CURRENT_SOURCE_DIR}" CACHE PATH "Path to external projects sources" ) 23 | set( EXTERNALS_INSTALL_PATH "${CMAKE_BINARY_DIR}/external_libs" CACHE PATH "Path to install external projects libraries" ) 24 | 25 | include( "cmake/compilers_minimal.cmake" ) 26 | 27 | # prepare for external projects 28 | if (TRUE) 29 | include( ExternalProject ) 30 | 31 | set( LIST_SEPARATOR "|" ) 32 | string( REPLACE ";" "${LIST_SEPARATOR}" EXTERNAL_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" ) 33 | set( BUILD_TARGET_FLAGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}" 34 | "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}" 35 | "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}" 36 | "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" 37 | "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}" 38 | "-DCMAKE_STATIC_LINKER_FLAGS=${CMAKE_STATIC_LINKER_FLAGS}" 39 | "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}" ) 40 | 41 | foreach ( CONFIG ${CMAKE_CONFIGURATION_TYPES} ) 42 | string( TOUPPER ${CONFIG} OUT_CONFIG ) 43 | 44 | set( BUILD_TARGET_FLAGS 45 | "${BUILD_TARGET_FLAGS}" 46 | "-DCMAKE_C_FLAGS_${OUT_CONFIG}=${CMAKE_C_FLAGS_${OUT_CONFIG}}" 47 | "-DCMAKE_CXX_FLAGS_${OUT_CONFIG}=${CMAKE_CXX_FLAGS_${OUT_CONFIG}}" 48 | "-DCMAKE_EXE_LINKER_FLAGS_${OUT_CONFIG}=${CMAKE_EXE_LINKER_FLAGS_${OUT_CONFIG}}" 49 | "-DCMAKE_STATIC_LINKER_FLAGS_${OUT_CONFIG}=${CMAKE_STATIC_LINKER_FLAGS_${OUT_CONFIG}}" 50 | "-DCMAKE_SHARED_LINKER_FLAGS_${OUT_CONFIG}=${CMAKE_SHARED_LINKER_FLAGS_${OUT_CONFIG}}" ) 51 | endforeach () 52 | endif () 53 | 54 | include( "cmake/download_glslang.cmake" ) 55 | include( "cmake/project_template.cmake" ) 56 | add_subdirectory( "shader_trace" ) 57 | 58 | if (DEFINED CI_BUILD) 59 | include( "cmake/download_vk.cmake" ) 60 | add_subdirectory( "tests/vulkan" ) 61 | 62 | elseif (${ENABLE_TESTS}) 63 | enable_testing() 64 | include( "cmake/download_vk.cmake" ) 65 | include( "cmake/download_glfw.cmake" ) 66 | include( "cmake/download_glew.cmake" ) 67 | include( "cmake/download_spirvcross.cmake" ) 68 | add_subdirectory( "tests/opengl" ) 69 | add_subdirectory( "tests/vulkan" ) 70 | endif () 71 | 72 | message( STATUS "project 'GLSL-Trace' generation ended" ) 73 | message( STATUS "\n==========================================================================" ) 74 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2020 Zhirnov Andrey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ShaderClockHeatmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azhirnov/glsl_trace/d6499dda98640d38cc7a918fae2209808bd6db24/ShaderClockHeatmap.jpg -------------------------------------------------------------------------------- /cmake/download_glew.cmake: -------------------------------------------------------------------------------- 1 | # find or download GLEW 2 | 3 | if (TRUE) 4 | set( EXTERNAL_GLEW_PATH "" CACHE PATH "path to GLEW source" ) 5 | mark_as_advanced( EXTERNAL_GLEW_PATH ) 6 | set( GLEW_INSTALL_DIR "${EXTERNALS_INSTALL_PATH}/glew" ) 7 | 8 | # select version 9 | if (${EXTERNALS_USE_STABLE_VERSIONS}) 10 | set( GLEW_TAG "glew-2.1.0" ) 11 | else () 12 | set( GLEW_TAG "master" ) 13 | endif () 14 | 15 | # reset to default 16 | if (NOT EXISTS "${EXTERNAL_GLEW_PATH}/build/cmake/CMakeLists.txt") 17 | message( STATUS "GLEW is not found in \"${EXTERNAL_GLEW_PATH}\"" ) 18 | set( EXTERNAL_GLEW_PATH "${EXTERNALS_PATH}/GLEW" CACHE PATH "" FORCE ) 19 | else () 20 | message( STATUS "GLEW found in \"${EXTERNAL_GLEW_PATH}\"" ) 21 | endif () 22 | 23 | if (NOT EXISTS "${EXTERNAL_GLEW_PATH}/CMakeLists.txt") 24 | set( GLEW_URL "https://sourceforge.net/projects/glew/files/glew/2.1.0/glew-2.1.0.zip/download" ) 25 | else () 26 | set( GLEW_URL "" ) 27 | endif () 28 | 29 | ExternalProject_Add( "External.GLEW" 30 | LIST_SEPARATOR "${LIST_SEPARATOR}" 31 | LOG_OUTPUT_ON_FAILURE 1 32 | # download 33 | URL "${GLEW_URL}" 34 | DOWNLOAD_DIR "${EXTERNAL_GLEW_PATH}" 35 | LOG_DOWNLOAD 1 36 | # update 37 | PATCH_COMMAND "" 38 | UPDATE_DISCONNECTED 1 39 | # configure 40 | SOURCE_DIR "${EXTERNAL_GLEW_PATH}" 41 | SOURCE_SUBDIR "build/cmake" 42 | CMAKE_GENERATOR "${CMAKE_GENERATOR}" 43 | CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}" 44 | CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" 45 | CMAKE_ARGS "-DCMAKE_CONFIGURATION_TYPES=${EXTERNAL_CONFIGURATION_TYPES}" 46 | "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}" 47 | "-DCMAKE_INSTALL_PREFIX=${GLEW_INSTALL_DIR}" 48 | ${BUILD_TARGET_FLAGS} 49 | LOG_CONFIGURE 1 50 | # build 51 | BINARY_DIR "${CMAKE_BINARY_DIR}/build-glew" 52 | BUILD_COMMAND ${CMAKE_COMMAND} 53 | --build . 54 | --config $ 55 | --target ALL_BUILD 56 | LOG_BUILD 1 57 | # install 58 | INSTALL_DIR "${GLEW_INSTALL_DIR}" 59 | INSTALL_COMMAND ${CMAKE_COMMAND} 60 | --build . 61 | --config $ 62 | --target install 63 | LOG_INSTALL 1 64 | # test 65 | LOG_TEST 1 66 | ) 67 | set_property( TARGET "External.GLEW" PROPERTY FOLDER "External" ) 68 | 69 | add_library( "GLEW-lib" INTERFACE ) 70 | 71 | set_property( TARGET "GLEW-lib" PROPERTY INTERFACE_LINK_LIBRARIES 72 | "$<$:${GLEW_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}libglew32d${CMAKE_STATIC_LIBRARY_SUFFIX}>" 73 | "$<$:${GLEW_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}libglew32${CMAKE_STATIC_LIBRARY_SUFFIX}>" 74 | "$<$:${GLEW_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}libglew32${CMAKE_STATIC_LIBRARY_SUFFIX}>" ) 75 | 76 | target_compile_definitions( "GLEW-lib" INTERFACE GLEW_STATIC ) 77 | target_include_directories( "GLEW-lib" INTERFACE "${GLEW_INSTALL_DIR}/include" ) 78 | add_dependencies( "GLEW-lib" "External.GLEW" ) 79 | endif () 80 | -------------------------------------------------------------------------------- /cmake/download_glfw.cmake: -------------------------------------------------------------------------------- 1 | # find or download GLFW 2 | 3 | if (TRUE) 4 | set( EXTERNAL_GLFW_PATH "" CACHE PATH "path to GLFW source" ) 5 | mark_as_advanced( EXTERNAL_GLFW_PATH ) 6 | set( GLFW_INSTALL_DIR "${EXTERNALS_INSTALL_PATH}/glfw" ) 7 | 8 | # select version 9 | if (${EXTERNALS_USE_STABLE_VERSIONS}) 10 | set( GLFW_TAG "3.3" ) 11 | else () 12 | set( GLFW_TAG "master" ) 13 | endif () 14 | 15 | # reset to default 16 | if (NOT EXISTS "${EXTERNAL_GLFW_PATH}/CMakeLists.txt") 17 | message( STATUS "GLFW is not found in \"${EXTERNAL_GLFW_PATH}\"" ) 18 | set( EXTERNAL_GLFW_PATH "${EXTERNALS_PATH}/GLFW" CACHE PATH "" FORCE ) 19 | else () 20 | message( STATUS "GLFW found in \"${EXTERNAL_GLFW_PATH}\"" ) 21 | endif () 22 | 23 | if (NOT EXISTS "${EXTERNAL_GLFW_PATH}/CMakeLists.txt") 24 | set( GLFW_REPOSITORY "https://github.com/glfw/glfw.git" ) 25 | else () 26 | set( GLFW_REPOSITORY "" ) 27 | endif () 28 | 29 | ExternalProject_Add( "External.GLFW" 30 | LIST_SEPARATOR "${LIST_SEPARATOR}" 31 | LOG_OUTPUT_ON_FAILURE 1 32 | # download 33 | GIT_REPOSITORY ${GLFW_REPOSITORY} 34 | GIT_TAG ${GLFW_TAG} 35 | GIT_PROGRESS 1 36 | # update 37 | PATCH_COMMAND "" 38 | UPDATE_DISCONNECTED 1 39 | # configure 40 | SOURCE_DIR "${EXTERNAL_GLFW_PATH}" 41 | CMAKE_GENERATOR "${CMAKE_GENERATOR}" 42 | CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}" 43 | CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" 44 | CMAKE_ARGS "-DCMAKE_CONFIGURATION_TYPES=${EXTERNAL_CONFIGURATION_TYPES}" 45 | "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}" 46 | "-DCMAKE_INSTALL_PREFIX=${GLFW_INSTALL_DIR}" 47 | ${BUILD_TARGET_FLAGS} 48 | LOG_CONFIGURE 1 49 | # build 50 | BINARY_DIR "${CMAKE_BINARY_DIR}/build-glfw" 51 | BUILD_COMMAND ${CMAKE_COMMAND} 52 | --build . 53 | --config $ 54 | --target glfw 55 | LOG_BUILD 1 56 | # install 57 | INSTALL_DIR "${GLFW_INSTALL_DIR}" 58 | INSTALL_COMMAND ${CMAKE_COMMAND} 59 | --build . 60 | --config $ 61 | --target install 62 | LOG_INSTALL 1 63 | # test 64 | LOG_TEST 1 65 | ) 66 | set_property( TARGET "External.GLFW" PROPERTY FOLDER "External" ) 67 | 68 | add_library( "GLFW-lib" INTERFACE ) 69 | set_property( TARGET "GLFW-lib" PROPERTY INTERFACE_LINK_LIBRARIES "${GLFW_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}glfw3${CMAKE_STATIC_LIBRARY_SUFFIX}" ) 70 | target_include_directories( "GLFW-lib" INTERFACE "${GLFW_INSTALL_DIR}/include" ) 71 | add_dependencies( "GLFW-lib" "External.GLFW" ) 72 | endif () 73 | -------------------------------------------------------------------------------- /cmake/download_glslang.cmake: -------------------------------------------------------------------------------- 1 | # find or download GLSLANG 2 | 3 | if (TRUE) 4 | set( EXTERNAL_GLSLANG_PATH "" CACHE PATH "path to glslang source" ) 5 | mark_as_advanced( EXTERNAL_GLSLANG_PATH ) 6 | 7 | # reset to default 8 | if (NOT EXISTS "${EXTERNAL_GLSLANG_PATH}/CMakeLists.txt") 9 | message( STATUS "glslang is not found in \"${EXTERNAL_GLSLANG_PATH}\"" ) 10 | set( EXTERNAL_GLSLANG_PATH "${EXTERNALS_PATH}/glslang" CACHE PATH "" FORCE ) 11 | else () 12 | message( STATUS "glslang found in \"${EXTERNAL_GLSLANG_PATH}\"" ) 13 | endif () 14 | 15 | if (FALSE) 16 | find_package( Vulkan ) 17 | if (Vulkan_FOUND) 18 | message( STATUS "used glslang from VulkanSDK" ) 19 | set( EXTERNAL_GLSLANG_PATH "${Vulkan_INCLUDE_DIR}/../glslang" CACHE PATH "" FORCE ) 20 | endif () 21 | endif () 22 | 23 | if (NOT EXISTS "${EXTERNAL_GLSLANG_PATH}/CMakeLists.txt") 24 | set( GLSLANG_REPOSITORY "https://github.com/KhronosGroup/glslang.git" ) 25 | else () 26 | set( GLSLANG_REPOSITORY "" ) 27 | endif () 28 | 29 | if (NOT EXISTS "${EXTERNAL_GLSLANG_PATH}/External/SPIRV-Tools/include") 30 | set( SPIRVTOOLS_REPOSITORY "https://github.com/KhronosGroup/SPIRV-Tools.git" ) 31 | else () 32 | set( SPIRVTOOLS_REPOSITORY "" ) 33 | endif () 34 | 35 | if (NOT EXISTS "${EXTERNAL_GLSLANG_PATH}/External/SPIRV-Tools/external/SPIRV-Headers/include") 36 | set( SPIRVHEADERS_REPOSITORY "https://github.com/KhronosGroup/SPIRV-Headers.git" ) 37 | else () 38 | set( SPIRVHEADERS_REPOSITORY "" ) 39 | endif () 40 | 41 | set( ENABLE_HLSL OFF CACHE BOOL "glslang option" ) 42 | set( ENABLE_OPT OFF CACHE BOOL "glslang option" ) 43 | mark_as_advanced( ENABLE_HLSL ENABLE_OPT ) 44 | 45 | # SPIRV-Tools require Python 3 for building 46 | if (${ENABLE_OPT}) 47 | find_package( PythonInterp 3.7 REQUIRED ) 48 | find_package( PythonLibs 3.7 REQUIRED ) 49 | endif () 50 | 51 | #if (${EXTERNALS_USE_STABLE_VERSIONS}) 52 | # set( GLSLANG_TAG "10-11.0.0" ) 53 | # set( SPIRV_TOOLS_TAG "v2020.4" ) 54 | # set( SPIRV_HEADERS_TAG "1.5.4" ) 55 | #else () 56 | set( GLSLANG_TAG "master" ) 57 | set( SPIRV_TOOLS_TAG "master" ) 58 | set( SPIRV_HEADERS_TAG "master" ) 59 | #endif () 60 | 61 | set( GLSLANG_DEPS "External.glslang" ) 62 | 63 | ExternalProject_Add( "External.glslang" 64 | LOG_OUTPUT_ON_FAILURE 1 65 | # download 66 | GIT_REPOSITORY ${GLSLANG_REPOSITORY} 67 | GIT_TAG ${GLSLANG_TAG} 68 | GIT_PROGRESS 1 69 | # update 70 | PATCH_COMMAND "" 71 | UPDATE_DISCONNECTED 1 72 | LOG_UPDATE 1 73 | # configure 74 | SOURCE_DIR "${EXTERNAL_GLSLANG_PATH}" 75 | CONFIGURE_COMMAND "" 76 | # build 77 | BINARY_DIR "" 78 | BUILD_COMMAND "" 79 | INSTALL_COMMAND "" 80 | TEST_COMMAND "" 81 | ) 82 | 83 | if (${ENABLE_OPT}) 84 | ExternalProject_Add( "External.SPIRV-Tools" 85 | LOG_OUTPUT_ON_FAILURE 1 86 | DEPENDS "External.glslang" 87 | # download 88 | GIT_REPOSITORY ${SPIRVTOOLS_REPOSITORY} 89 | GIT_TAG ${SPIRV_TOOLS_TAG} 90 | GIT_PROGRESS 1 91 | # update 92 | PATCH_COMMAND "" 93 | UPDATE_DISCONNECTED 1 94 | LOG_UPDATE 1 95 | # configure 96 | SOURCE_DIR "${EXTERNAL_GLSLANG_PATH}/External/SPIRV-Tools" 97 | CONFIGURE_COMMAND "" 98 | # build 99 | BINARY_DIR "" 100 | BUILD_COMMAND "" 101 | INSTALL_COMMAND "" 102 | TEST_COMMAND "" 103 | ) 104 | 105 | ExternalProject_Add( "External.SPIRV-Headers" 106 | LOG_OUTPUT_ON_FAILURE 1 107 | DEPENDS "External.glslang" 108 | "External.SPIRV-Tools" 109 | # download 110 | GIT_REPOSITORY ${SPIRVHEADERS_REPOSITORY} 111 | GIT_TAG ${SPIRV_HEADERS_TAG} 112 | GIT_PROGRESS 1 113 | # update 114 | PATCH_COMMAND "" 115 | UPDATE_DISCONNECTED 1 116 | LOG_UPDATE 1 117 | # configure 118 | SOURCE_DIR "${EXTERNAL_GLSLANG_PATH}/External/SPIRV-Tools/external/SPIRV-Headers" 119 | CONFIGURE_COMMAND "" 120 | # build 121 | BINARY_DIR "" 122 | BUILD_COMMAND "" 123 | INSTALL_COMMAND "" 124 | TEST_COMMAND "" 125 | ) 126 | 127 | set( GLSLANG_DEPS "${GLSLANG_DEPS}" "External.SPIRV-Tools" "External.SPIRV-Headers" ) 128 | set_property( TARGET "External.SPIRV-Headers" PROPERTY FOLDER "External" ) 129 | set_property( TARGET "External.SPIRV-Tools" PROPERTY FOLDER "External" ) 130 | endif () 131 | 132 | set( GLSLANG_INSTALL_DIR "${EXTERNALS_INSTALL_PATH}/glslang" ) 133 | 134 | ExternalProject_Add( "External.glslang-main" 135 | LIST_SEPARATOR "${LIST_SEPARATOR}" 136 | LOG_OUTPUT_ON_FAILURE 1 137 | DEPENDS ${GLSLANG_DEPS} 138 | DOWNLOAD_COMMAND "" 139 | # configure 140 | SOURCE_DIR "${EXTERNAL_GLSLANG_PATH}" 141 | CMAKE_GENERATOR "${CMAKE_GENERATOR}" 142 | CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}" 143 | CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" 144 | CMAKE_ARGS "-DCMAKE_CONFIGURATION_TYPES=${EXTERNAL_CONFIGURATION_TYPES}" 145 | "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}" 146 | "-DCMAKE_INSTALL_PREFIX=${GLSLANG_INSTALL_DIR}" 147 | "-DENABLE_HLSL=${ENABLE_HLSL}" 148 | "-DENABLE_OPT=${ENABLE_OPT}" 149 | "-DENABLE_SPVREMAPPER=ON" 150 | "-DENABLE_GLSLANG_BINARIES=OFF" 151 | "-DSKIP_GLSLANG_INSTALL=OFF" 152 | "-DSKIP_SPIRV_TOOLS_INSTALL=OFF" 153 | "-DSPIRV_SKIP_EXECUTABLES=OFF" 154 | "-DSPIRV_SKIP_TESTS=ON" 155 | "-DBUILD_TESTING=OFF" 156 | ${BUILD_TARGET_FLAGS} 157 | LOG_CONFIGURE 1 158 | # build 159 | BINARY_DIR "${CMAKE_BINARY_DIR}/build-glslang" 160 | BUILD_COMMAND ${CMAKE_COMMAND} 161 | --build . 162 | --config $ 163 | --target glslang 164 | LOG_BUILD 1 165 | # install 166 | INSTALL_DIR "${GLSLANG_INSTALL_DIR}" 167 | INSTALL_COMMAND ${CMAKE_COMMAND} 168 | --build . 169 | --config $ 170 | --target glslang 171 | install 172 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 173 | "${EXTERNAL_GLSLANG_PATH}/StandAlone/ResourceLimits.h" 174 | "${GLSLANG_INSTALL_DIR}/include/StandAlone/ResourceLimits.h" 175 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 176 | "${EXTERNAL_GLSLANG_PATH}/StandAlone/ResourceLimits.cpp" 177 | "${GLSLANG_INSTALL_DIR}/include/StandAlone/ResourceLimits.cpp" 178 | LOG_INSTALL 1 179 | # test 180 | TEST_COMMAND "" 181 | ) 182 | 183 | set_property( TARGET "External.glslang" PROPERTY FOLDER "External" ) 184 | set_property( TARGET "External.glslang-main" PROPERTY FOLDER "External" ) 185 | 186 | set( GLSLANG_DEFINITIONS "" ) 187 | 188 | if (${ENABLE_OPT}) 189 | set( GLSLANG_DEFINITIONS "${GLSLANG_DEFINITIONS}" "ENABLE_OPT" ) 190 | endif () 191 | 192 | # glslang libraries 193 | set( GLSLANG_LIBNAMES "SPIRV" "glslang" "OSDependent" "MachineIndependent" "GenericCodeGen" ) 194 | 195 | if (${ENABLE_HLSL}) 196 | set( GLSLANG_DEFINITIONS "${GLSLANG_DEFINITIONS}" "ENABLE_HLSL" ) 197 | set( GLSLANG_LIBNAMES "${GLSLANG_LIBNAMES}" "HLSL" ) 198 | endif () 199 | 200 | if (UNIX) 201 | set( GLSLANG_LIBNAMES "${GLSLANG_LIBNAMES}" "pthread" ) 202 | endif () 203 | 204 | set( GLSLANG_LIBNAMES "${GLSLANG_LIBNAMES}" "OGLCompiler" ) 205 | 206 | if (${ENABLE_OPT}) 207 | set( GLSLANG_LIBNAMES "${GLSLANG_LIBNAMES}" "SPIRV-Tools" "SPIRV-Tools-opt" ) 208 | endif () 209 | 210 | if (MSVC) 211 | set( DBG_POSTFIX "${CMAKE_DEBUG_POSTFIX}" ) 212 | else () 213 | set( DBG_POSTFIX "" ) 214 | endif () 215 | 216 | set( GLSLANG_LIBRARIES "" ) 217 | foreach ( LIBNAME ${GLSLANG_LIBNAMES} ) 218 | if ( ${LIBNAME} STREQUAL "pthread" ) 219 | set( GLSLANG_LIBRARIES "${GLSLANG_LIBRARIES}" "${LIBNAME}" ) 220 | else () 221 | set( GLSLANG_LIBRARIES "${GLSLANG_LIBRARIES}" 222 | "$<$:${GLSLANG_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${LIBNAME}${DBG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}>" 223 | "$<$:${GLSLANG_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${LIBNAME}${CMAKE_STATIC_LIBRARY_SUFFIX}>" 224 | "$<$:${GLSLANG_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${LIBNAME}${CMAKE_STATIC_LIBRARY_SUFFIX}>" ) 225 | endif () 226 | endforeach () 227 | 228 | add_library( "GLSLang-lib" INTERFACE ) 229 | set_property( TARGET "GLSLang-lib" PROPERTY INTERFACE_LINK_LIBRARIES "${GLSLANG_LIBRARIES}" ) 230 | target_include_directories( "GLSLang-lib" INTERFACE "${GLSLANG_INSTALL_DIR}/include" ) 231 | target_compile_definitions( "GLSLang-lib" INTERFACE "${GLSLANG_DEFINITIONS}" ) 232 | add_dependencies( "GLSLang-lib" "External.glslang-main" ) 233 | 234 | endif () 235 | -------------------------------------------------------------------------------- /cmake/download_spirvcross.cmake: -------------------------------------------------------------------------------- 1 | # download SPIRV-Cross (Apache-2.0 license) 2 | 3 | if (TRUE) 4 | set( EXTERNAL_SPIRV_CROSS_PATH "" CACHE PATH "path to SPIRV-Cross source" ) 5 | mark_as_advanced( EXTERNAL_SPIRV_CROSS_PATH ) 6 | 7 | # reset to default 8 | if (NOT EXISTS "${EXTERNAL_SPIRV_CROSS_PATH}/spirv_cross.hpp") 9 | message( STATUS "SPIRV-Cross is not found in \"${EXTERNAL_SPIRV_CROSS_PATH}\"" ) 10 | set( EXTERNAL_SPIRV_CROSS_PATH "${EXTERNALS_PATH}/SPIRV-Cross" CACHE PATH "" FORCE ) 11 | else () 12 | message( STATUS "SPIRV-Cross found in \"${EXTERNAL_SPIRV_CROSS_PATH}\"" ) 13 | endif () 14 | 15 | # select version 16 | if (${EXTERNALS_USE_STABLE_VERSIONS}) 17 | set( SPIRVCROSS_TAG "2020-09-17" ) 18 | else () 19 | set( SPIRVCROSS_TAG "master" ) 20 | endif () 21 | 22 | set( SPIRV_CROSS_INSTALL_DIR "${EXTERNALS_INSTALL_PATH}/SPIRV-Cross" ) 23 | 24 | ExternalProject_Add( "External.SPIRV-Cross" 25 | LOG_OUTPUT_ON_FAILURE 1 26 | LIST_SEPARATOR "${LIST_SEPARATOR}" 27 | # download 28 | GIT_REPOSITORY "https://github.com/KhronosGroup/SPIRV-Cross.git" 29 | GIT_TAG ${SPIRVCROSS_TAG} 30 | GIT_PROGRESS 1 31 | # update 32 | PATCH_COMMAND "" 33 | UPDATE_DISCONNECTED 1 34 | # configure 35 | SOURCE_DIR "${EXTERNAL_SPIRV_CROSS_PATH}" 36 | CMAKE_GENERATOR "${CMAKE_GENERATOR}" 37 | CMAKE_GENERATOR_PLATFORM "${CMAKE_GENERATOR_PLATFORM}" 38 | CMAKE_GENERATOR_TOOLSET "${CMAKE_GENERATOR_TOOLSET}" 39 | CMAKE_ARGS "-DCMAKE_CONFIGURATION_TYPES=${EXTERNAL_CONFIGURATION_TYPES}" 40 | "-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION}" 41 | "-DCMAKE_INSTALL_PREFIX=${SPIRV_CROSS_INSTALL_DIR}" 42 | "-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS=ON" 43 | ${BUILD_TARGET_FLAGS} 44 | LOG_CONFIGURE 1 45 | # build 46 | BINARY_DIR "${CMAKE_BINARY_DIR}/build-SPIRV-Cross" 47 | BUILD_COMMAND "${CMAKE_COMMAND}" 48 | --build . 49 | --config $ 50 | LOG_BUILD 1 51 | # install 52 | INSTALL_DIR "${SPIRV_CROSS_INSTALL_DIR}" 53 | LOG_INSTALL 1 54 | # test 55 | TEST_COMMAND "" 56 | ) 57 | set_property( TARGET "External.SPIRV-Cross" PROPERTY FOLDER "External" ) 58 | 59 | add_library( "SPIRV-Cross-lib" INTERFACE ) 60 | target_include_directories( "SPIRV-Cross-lib" INTERFACE "${EXTERNAL_SPIRV_CROSS_PATH}" ) 61 | 62 | set_property( TARGET "SPIRV-Cross-lib" PROPERTY INTERFACE_LINK_LIBRARIES 63 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-cored${CMAKE_STATIC_LIBRARY_SUFFIX}>" 64 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-glsld${CMAKE_STATIC_LIBRARY_SUFFIX}>" 65 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-core${CMAKE_STATIC_LIBRARY_SUFFIX}>" 66 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-glsl${CMAKE_STATIC_LIBRARY_SUFFIX}>" 67 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-core${CMAKE_STATIC_LIBRARY_SUFFIX}>" 68 | "$<$:${SPIRV_CROSS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spirv-cross-glsl${CMAKE_STATIC_LIBRARY_SUFFIX}>" ) 69 | 70 | add_dependencies( "SPIRV-Cross-lib" "External.SPIRV-Cross" ) 71 | endif () 72 | -------------------------------------------------------------------------------- /cmake/download_vk.cmake: -------------------------------------------------------------------------------- 1 | # Find or download Vulkan headers 2 | 3 | include(FetchContent) 4 | set( FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "don't update externals" ) 5 | mark_as_advanced( FETCHCONTENT_BASE_DIR FETCHCONTENT_FULLY_DISCONNECTED ) 6 | mark_as_advanced( FETCHCONTENT_QUIET FETCHCONTENT_UPDATES_DISCONNECTED ) 7 | 8 | 9 | if (EXISTS "${EXTERNALS_PATH}/vulkan/vulkan_core.h") 10 | set( Vulkan_INCLUDE_DIRS "${EXTERNALS_PATH}" ) 11 | set( Vulkan_FOUND TRUE ) 12 | 13 | elseif (EXISTS "${EXTERNALS_PATH}/vulkan/include/vulkan/vulkan_core.h") 14 | set( Vulkan_INCLUDE_DIRS "${EXTERNALS_PATH}/vulkan/include" ) 15 | set( Vulkan_FOUND TRUE ) 16 | 17 | elseif (EXISTS "${EXTERNALS_PATH}/Vulkan-Headers/include/vulkan/vulkan_core.h") 18 | set( Vulkan_INCLUDE_DIRS "${EXTERNALS_PATH}/Vulkan-Headers/include" ) 19 | set( Vulkan_FOUND TRUE ) 20 | endif () 21 | 22 | 23 | set( VULKAN_HEADERS_TAG "v1.2.162" ) 24 | 25 | # download 26 | if (NOT Vulkan_FOUND AND NOT CMAKE_VERSION VERSION_LESS 3.11.0) 27 | FetchContent_Declare( ExternalVulkanHeaders 28 | GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git 29 | GIT_TAG ${VULKAN_HEADERS_TAG} 30 | SOURCE_DIR "${EXTERNALS_PATH}/Vulkan-Headers" 31 | ) 32 | 33 | FetchContent_GetProperties( ExternalVulkanHeaders ) 34 | if (NOT ExternalVulkanHeaders_POPULATED) 35 | message( STATUS "downloading Vulkan-Headers" ) 36 | FetchContent_Populate( ExternalVulkanHeaders ) 37 | endif () 38 | 39 | set( Vulkan_INCLUDE_DIRS "${EXTERNALS_PATH}/Vulkan-Headers/include" ) 40 | set( Vulkan_FOUND TRUE ) 41 | endif () 42 | 43 | 44 | if (NOT Vulkan_FOUND) 45 | message( FATAL_ERROR "Vulkan headers is not found! Install VulkanSDK or download from https://github.com/KhronosGroup/Vulkan-Headers" ) 46 | endif () 47 | 48 | add_library( "Vulkan-lib" INTERFACE ) 49 | target_include_directories( "Vulkan-lib" INTERFACE "${Vulkan_INCLUDE_DIRS}" ) 50 | -------------------------------------------------------------------------------- /cmake/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/azhirnov/glsl_trace/d6499dda98640d38cc7a918fae2209808bd6db24/cmake/main.cpp -------------------------------------------------------------------------------- /cmake/project_template.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.10 FATAL_ERROR ) 2 | 3 | set( CMAKE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ) 4 | file( GLOB_RECURSE CMAKE_SOURCES "${CMAKE_FOLDER}/*.*" ) 5 | 6 | add_library( "ProjectTemplate" STATIC EXCLUDE_FROM_ALL ${CMAKE_SOURCES} ) 7 | set_property( TARGET "ProjectTemplate" PROPERTY FOLDER "Utils" ) 8 | source_group( TREE "${CMAKE_FOLDER}/.." FILES ${CMAKE_SOURCES} ) 9 | 10 | target_compile_definitions( "ProjectTemplate" PUBLIC ${COMPILER_DEFINITIONS} ) 11 | target_link_libraries( "ProjectTemplate" PUBLIC "${LINK_LIBRARIES}" ) 12 | 13 | # Debug 14 | if (PROJECTS_SHARED_CXX_FLAGS_DEBUG) 15 | target_compile_options( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_CXX_FLAGS_DEBUG}> ) 16 | endif () 17 | if (PROJECTS_SHARED_DEFINES_DEBUG) 18 | target_compile_definitions( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_DEFINES_DEBUG}> ) 19 | endif () 20 | if (PROJECTS_SHARED_LINKER_FLAGS_DEBUG) 21 | set_target_properties( "ProjectTemplate" PROPERTIES LINK_FLAGS_DEBUG ${PROJECTS_SHARED_LINKER_FLAGS_DEBUG} ) 22 | endif () 23 | 24 | # Release 25 | if (PROJECTS_SHARED_CXX_FLAGS_RELEASE) 26 | target_compile_options( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_CXX_FLAGS_RELEASE}> ) 27 | endif () 28 | if (PROJECTS_SHARED_DEFINES_RELEASE) 29 | target_compile_definitions( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_DEFINES_RELEASE}> ) 30 | endif () 31 | if (PROJECTS_SHARED_LINKER_FLAGS_RELEASE) 32 | set_target_properties( "ProjectTemplate" PROPERTIES LINK_FLAGS_RELEASE ${PROJECTS_SHARED_LINKER_FLAGS_RELEASE} ) 33 | endif () 34 | 35 | # Profile 36 | if (PROJECTS_SHARED_DEFINES_PROFILE) 37 | target_compile_definitions( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_DEFINES_PROFILE}> ) 38 | endif () 39 | if (PROJECTS_SHARED_LINKER_FLAGS_PROFILE) 40 | set_target_properties( "ProjectTemplate" PROPERTIES LINK_FLAGS_PROFILE ${PROJECTS_SHARED_LINKER_FLAGS_PROFILE} ) 41 | endif () 42 | if (PROJECTS_SHARED_CXX_FLAGS_PROFILE) 43 | target_compile_options( "ProjectTemplate" PUBLIC $<$: ${PROJECTS_SHARED_CXX_FLAGS_PROFILE}> ) 44 | endif () 45 | 46 | set_target_properties( "ProjectTemplate" PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES ) 47 | target_compile_features( "ProjectTemplate" PUBLIC cxx_std_17 ) 48 | 49 | if (${CI_BUILD}) 50 | target_compile_definitions( "ProjectTemplate" PUBLIC "CI_BUILD" ) 51 | endif () 52 | -------------------------------------------------------------------------------- /shader_trace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.10 FATAL_ERROR ) 2 | 3 | file( GLOB_RECURSE SOURCES "*.*" ) 4 | add_library( "ShaderTrace" STATIC ${SOURCES} ) 5 | source_group( TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES} ) 6 | target_include_directories( "ShaderTrace" PUBLIC "include" ) 7 | set_property( TARGET "ShaderTrace" PROPERTY FOLDER "" ) 8 | target_link_libraries( "ShaderTrace" PUBLIC "ProjectTemplate" ) 9 | target_link_libraries( "ShaderTrace" PUBLIC "GLSLang-lib" ) 10 | 11 | install( TARGETS "ShaderTrace" ARCHIVE DESTINATION "libs/$" ) 12 | install( DIRECTORY "include" DESTINATION "include/ShaderTrace" FILES_MATCHING PATTERN "*.h*" ) 13 | -------------------------------------------------------------------------------- /shader_trace/include/ShaderTrace.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | /* 3 | GLSL Trace project 4 | https://github.com/azhirnov/glsl_trace 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace glslang { 14 | class TIntermediate; 15 | } 16 | 17 | 18 | struct ShaderTrace 19 | { 20 | public: 21 | enum class VariableID : uint32_t { Unknown = ~0u }; 22 | 23 | struct SourcePoint 24 | { 25 | uint64_t value; 26 | 27 | SourcePoint () : value{~0ull} {} 28 | SourcePoint (uint32_t line, uint32_t column) : value{(uint64_t(line) << 32) | column } {} 29 | 30 | uint32_t Line () const { return uint32_t(value >> 32); } 31 | uint32_t Column () const { return uint32_t(value & 0xFFFFFFFF); } 32 | }; 33 | 34 | struct SourceLocation 35 | { 36 | uint32_t sourceId = ~0u; 37 | SourcePoint begin; 38 | SourcePoint end; 39 | 40 | SourceLocation () {} 41 | SourceLocation (uint32_t sourceId, uint32_t line, uint32_t column) : sourceId{sourceId}, begin{line, column}, end{line, column} {} 42 | 43 | bool operator == (const SourceLocation &rhs) const { return sourceId == rhs.sourceId && begin.value == rhs.begin.value && end.value == rhs.end.value; } 44 | }; 45 | 46 | struct ExprInfo 47 | { 48 | VariableID varID = VariableID::Unknown; // ID of output variable 49 | uint32_t swizzle = 0; 50 | SourceLocation range; // begin and end location of expression 51 | SourcePoint point; // location of operator 52 | std::vector vars; // all variables IDs in this expression 53 | }; 54 | 55 | struct SourceInfo 56 | { 57 | using LineRange = std::pair< size_t, size_t >; 58 | 59 | std::string code; 60 | std::vector lines; // offset in bytes for each line in 'code' 61 | }; 62 | 63 | using VarNames_t = std::unordered_map< VariableID, std::string >; 64 | using ExprInfos_t = std::vector< ExprInfo >; 65 | using Sources_t = std::vector< SourceInfo >; 66 | using FileMap_t = std::unordered_map< std::string, uint32_t >; // index in '_sources' 67 | 68 | static constexpr int TBasicType_Clock = 0xcc; // 4x uint64 69 | static constexpr uint32_t InitialPositionMask = 0x80000000u; 70 | 71 | 72 | private: 73 | ExprInfos_t _exprLocations; 74 | VarNames_t _varNames; 75 | Sources_t _sources; 76 | FileMap_t _fileMap; 77 | uint64_t _posOffset = 0; 78 | uint64_t _dataOffset = 0; 79 | uint32_t _initialPosition; 80 | 81 | 82 | public: 83 | ShaderTrace () {} 84 | 85 | ShaderTrace (ShaderTrace &&) = delete; 86 | ShaderTrace (const ShaderTrace &) = delete; 87 | ShaderTrace& operator = (ShaderTrace &&) = delete; 88 | ShaderTrace& operator = (const ShaderTrace &) = delete; 89 | 90 | // Log all function results, log all function calls, log some operator results. 91 | // Use 'ParseShaderTrace' to get trace as string. 92 | bool InsertTraceRecording (glslang::TIntermediate &, uint32_t descSetIndex); 93 | 94 | // Insert time measurement into user-defined functions. 95 | // Use 'ParseShaderTrace' to get trace as string. 96 | bool InsertFunctionProfiler (glslang::TIntermediate &, uint32_t descSetIndex, bool shaderSubgroupClock, bool shaderDeviceClock); 97 | 98 | // Insert time measurement into entry function, summarize shader invocation times in storage buffer. 99 | bool InsertShaderClockHeatmap (glslang::TIntermediate &, uint32_t descSetIndex); 100 | 101 | // Converts binary trace into string. 102 | bool ParseShaderTrace (const void *ptr, uint64_t maxSize, std::vector &result) const; 103 | 104 | // Source code required for 'ParseShaderTrace' function. 105 | void SetSource (const char* const* sources, const size_t *lengths, size_t count); 106 | void SetSource (const char* source, size_t length); 107 | void IncludeSource (const char* filename, const char* source, size_t length); // if used '#include' 108 | void GetSource (std::string &result) const; 109 | 110 | private: 111 | void _AppendSource (const char* source, size_t length); 112 | }; 113 | -------------------------------------------------------------------------------- /shader_trace/source/Common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #pragma once 4 | 5 | #include "../include/ShaderTrace.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using std::vector; 11 | using std::string; 12 | using std::unordered_map; 13 | using std::unordered_set; 14 | using std::min; 15 | using std::max; 16 | using std::to_string; 17 | 18 | using uint = uint32_t; 19 | 20 | #define HIGH_DETAIL_TRACE 21 | #define USE_STORAGE_QUALIFIERS 22 | 23 | #include 24 | 25 | #ifndef OUT 26 | # define OUT 27 | #endif 28 | 29 | #ifndef INOUT 30 | # define INOUT 31 | #endif 32 | 33 | #ifdef _MSC_VER 34 | # if !defined(and) 35 | # define not ! 36 | # define and && 37 | # define or || 38 | # endif 39 | #endif 40 | 41 | #ifndef CHECK_ERR 42 | # ifdef _DEBUG 43 | # define ASSERT( _expr_ ) { assert(_expr_); } 44 | # else 45 | # define ASSERT( _expr_ ) {} 46 | # endif 47 | # define __GETARG_0( _0_, ... ) _0_ 48 | # define __GETARG_1( _0_, _1_, ... ) _1_ 49 | # define __CHECK_ERR( _expr_, _ret_ ) {if (not (_expr_)) { ASSERT(!(#_expr_)); return _ret_; } } 50 | # define CHECK_ERR( ... ) __CHECK_ERR( __GETARG_0( __VA_ARGS__ ), __GETARG_1( __VA_ARGS__, 0 )) 51 | # define RETURN_ERR( _msg_ ) { ASSERT(!(#_msg_)); return 0; } 52 | # define CHECK( _expr_ ) { ASSERT(_expr_); } 53 | #endif 54 | 55 | #ifndef ND_ 56 | # if defined(_MSC_VER) 57 | # if _MSC_VER >= 1917 58 | # define ND_ [[nodiscard]] 59 | # endif 60 | # elif defined(__clang__) 61 | # if __has_feature( cxx_attributes ) 62 | # define ND_ [[nodiscard]] 63 | # endif 64 | # elif defined(__gcc__) 65 | # if __has_cpp_attribute( nodiscard ) 66 | # define ND_ [[nodiscard]] 67 | # endif 68 | # endif 69 | # ifndef ND_ 70 | # define ND_ 71 | # endif 72 | #endif 73 | 74 | #ifdef _MSC_VER 75 | # define FUNCTION_NAME __FUNCTION__ 76 | #elif defined(__clang__) || defined(__gcc__) 77 | # define FUNCTION_NAME __func__ 78 | #else 79 | # define FUNCTION_NAME "unknown function" 80 | #endif 81 | 82 | #ifndef BEGIN_ENUM_CHECKS 83 | # if defined(_MSC_VER) 84 | # define BEGIN_ENUM_CHECKS() \ 85 | __pragma (warning (push)) \ 86 | __pragma (warning (error: 4061)) /*enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label*/ \ 87 | __pragma (warning (error: 4062)) /*enumerator 'identifier' in switch of enum 'enumeration' is not handled*/ \ 88 | __pragma (warning (error: 4063)) /*case 'number' is not a valid value for switch of enum 'type'*/ \ 89 | 90 | # define END_ENUM_CHECKS() \ 91 | __pragma (warning (pop)) \ 92 | 93 | # elif defined(__clang__) 94 | # define BEGIN_ENUM_CHECKS() \ 95 | _Pragma( "clang diagnostic error \"-Wswitch\"" ) 96 | 97 | # define END_ENUM_CHECKS() \ 98 | _Pragma( "clang diagnostic ignored \"-Wswitch\"" ) 99 | 100 | # else 101 | # define BEGIN_ENUM_CHECKS() 102 | # define END_ENUM_CHECKS() 103 | 104 | # endif 105 | #endif // BEGIN_ENUM_CHECKS 106 | 107 | 108 | // glslang includes 109 | #include "glslang/MachineIndependent/localintermediate.h" 110 | #include "glslang/Include/intermediate.h" 111 | 112 | ND_ std::string GetFunctionName (glslang::TIntermOperator *op); 113 | 114 | bool ValidateInterm (glslang::TIntermediate &intermediate); 115 | 116 | static const char* RT_LaunchID[] = { "gl_LaunchID", "gl_LaunchIDNV" }; 117 | static const char* RT_LaunchSize[] = { "gl_LaunchSize", "gl_LaunchSizeNV" }; 118 | static const char* RT_InstanceCustomIndex[]= { "gl_InstanceCustomIndex", "gl_InstanceCustomIndexNV" }; 119 | static const char* RT_WorldRayOrigin[] = { "gl_WorldRayOrigin", "gl_WorldRayOriginNV" }; 120 | static const char* RT_WorldRayDirection[] = { "gl_WorldRayDirection", "gl_WorldRayDirectionNV" }; 121 | static const char* RT_ObjectRayOrigin[] = { "gl_ObjectRayOrigin", "gl_ObjectRayOriginNV" }; 122 | static const char* RT_ObjectRayDirection[] = { "gl_ObjectRayDirection", "gl_ObjectRayDirectionNV" }; 123 | static const char* RT_RayTmin[] = { "gl_RayTmin", "gl_RayTminNV" }; 124 | static const char* RT_RayTmax[] = { "gl_RayTmax", "gl_RayTmaxNV" }; 125 | static const char* RT_IncomingRayFlags[] = { "gl_IncomingRayFlags", "gl_IncomingRayFlagsNV" }; 126 | static const char* RT_ObjectToWorld[] = { "gl_ObjectToWorld", "gl_ObjectToWorldNV" }; 127 | static const char* RT_WorldToObject[] = { "gl_WorldToObject", "gl_WorldToObjectNV" }; 128 | static const char* RT_HitT[] = { "gl_HitT", "gl_HitTNV" }; 129 | static const char* RT_HitKind[] = { "gl_HitKind", "gl_HitKindNV" }; 130 | static const char* RT_InstanceID[] = { "gl_InstanceID", "gl_InstanceIDNV" }; 131 | -------------------------------------------------------------------------------- /shader_trace/source/ShaderTrace.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Common.h" 4 | 5 | /* 6 | ================================================= 7 | _AppendSource 8 | ================================================= 9 | */ 10 | void ShaderTrace::_AppendSource (const char* source, size_t length) 11 | { 12 | ASSERT( length > 0 ); 13 | 14 | SourceInfo info; 15 | size_t pos = 0; 16 | 17 | info.code.assign( source, length ); 18 | info.lines.reserve( 64 ); 19 | 20 | for (size_t j = 0, len = info.code.length(); j < len; ++j) 21 | { 22 | const char c = info.code[j]; 23 | const char n = (j+1) >= len ? 0 : info.code[j+1]; 24 | 25 | // windows style "\r\n" 26 | if ( c == '\r' and n == '\n' ) 27 | { 28 | info.lines.push_back({ pos, j }); 29 | pos = (++j) + 1; 30 | } 31 | else 32 | // linux style "\n" (or mac style "\r") 33 | if ( c == '\n' or c == '\r' ) 34 | { 35 | info.lines.push_back({ pos, j }); 36 | pos = j + 1; 37 | } 38 | } 39 | 40 | if ( pos < info.code.length() ) 41 | info.lines.push_back({ pos, info.code.length() }); 42 | 43 | _sources.push_back( std::move(info) ); 44 | } 45 | 46 | /* 47 | ================================================= 48 | SetSource 49 | ================================================= 50 | */ 51 | void ShaderTrace::SetSource (const char* const* sources, const size_t *lengths, size_t count) 52 | { 53 | _sources.clear(); 54 | _sources.reserve( count ); 55 | 56 | for (size_t i = 0; i < count; ++i) 57 | { 58 | ASSERT( sources[i] != nullptr ); 59 | _AppendSource( sources[i], (lengths ? lengths[i] : strlen(sources[i])) ); 60 | } 61 | } 62 | 63 | void ShaderTrace::SetSource (const char* source, size_t length) 64 | { 65 | ASSERT( length > 0 ); 66 | 67 | const char* sources[] = { source }; 68 | return SetSource( sources, &length, 1 ); 69 | } 70 | 71 | void ShaderTrace::IncludeSource (const char* filename, const char* source, size_t length) 72 | { 73 | ASSERT( length > 0 ); 74 | 75 | _fileMap.insert_or_assign( string(filename), uint(_sources.size()) ); 76 | _AppendSource( source, length ); 77 | } 78 | 79 | /* 80 | ================================================= 81 | GetSource 82 | ================================================= 83 | */ 84 | void ShaderTrace::GetSource (OUT string &result) const 85 | { 86 | size_t total_size = _sources.size()*2; 87 | 88 | for (auto& src : _sources) { 89 | total_size += src.code.length(); 90 | } 91 | 92 | result.clear(); 93 | result.reserve( total_size ); 94 | 95 | for (auto& src : _sources) { 96 | result.append( src.code ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /tests/opengl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.10 FATAL_ERROR ) 2 | 3 | set( UTILS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../utils" ) 4 | 5 | file( GLOB_RECURSE SOURCES "*.*" ) 6 | file( GLOB_RECURSE UTILS_SRC "${UTILS_DIR}/*.*" ) 7 | 8 | add_executable( "Tests.OpenGL" ${SOURCES} ${UTILS_SRC} ) 9 | 10 | target_include_directories( "Tests.OpenGL" PUBLIC "../utils" ) 11 | 12 | source_group( TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES} ) 13 | source_group( TREE ${UTILS_DIR} FILES ${UTILS_SRC} ) 14 | 15 | set_property( TARGET "Tests.OpenGL" PROPERTY FOLDER "" ) 16 | target_link_libraries( "Tests.OpenGL" PUBLIC "ShaderTrace" ) 17 | target_link_libraries( "Tests.OpenGL" PUBLIC "SPIRV-Cross-lib" ) 18 | target_link_libraries( "Tests.OpenGL" PUBLIC "GLFW-lib" ) 19 | target_link_libraries( "Tests.OpenGL" PUBLIC "GLEW-lib" ) 20 | target_link_libraries( "Tests.OpenGL" PUBLIC "opengl32" ) 21 | 22 | target_compile_definitions( "Tests.OpenGL" PUBLIC "ENABLE_OPENGL" "DATA_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/../ref/\"" ) 23 | 24 | if (NOT CI_BUILD) 25 | add_test( NAME "Tests.OpenGL" COMMAND "Tests.OpenGL" ) 26 | endif () 27 | -------------------------------------------------------------------------------- /tests/opengl/ShaderCompiler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "ShaderCompiler.h" 4 | 5 | // glslang includes 6 | #include "glslang/MachineIndependent/localintermediate.h" 7 | #include "glslang/Include/intermediate.h" 8 | #include "glslang/SPIRV/doc.h" 9 | #include "glslang/SPIRV/disassemble.h" 10 | #include "glslang/SPIRV/GlslangToSpv.h" 11 | #include "glslang/SPIRV/GLSL.std.450.h" 12 | #include "StandAlone/ResourceLimits.cpp" 13 | using namespace glslang; 14 | 15 | // spirv cross 16 | #include "spirv_cross.hpp" 17 | #include "spirv_glsl.hpp" 18 | 19 | 20 | bool enableShaderSubgroupClock = false; 21 | bool enableShaderDeviceClock = false; 22 | 23 | /* 24 | ================================================= 25 | CreateShader 26 | ================================================= 27 | */ 28 | bool CreateShader (OUT GLuint & result, 29 | OUT ShaderTrace* dbgInfo, 30 | GLenum shaderType, 31 | const char * inSource, 32 | ETraceMode mode) 33 | { 34 | EShLanguage sh_lang; 35 | std::string src; 36 | std::string header = "#version 450 core\n" 37 | "#extension GL_ARB_separate_shader_objects : require\n" 38 | "#extension GL_ARB_shading_language_420pack : require\n"; 39 | 40 | if (enableShaderSubgroupClock) 41 | header += "#extension GL_ARB_shader_clock : require\n"; 42 | 43 | if (enableShaderDeviceClock) 44 | header += "#extension GL_EXT_shader_realtime_clock : require\n"; 45 | 46 | switch ( shaderType ) 47 | { 48 | case GL_COMPUTE_SHADER : sh_lang = EShLangCompute; break; 49 | case GL_VERTEX_SHADER : sh_lang = EShLangVertex; break; 50 | case GL_TESS_CONTROL_SHADER : sh_lang = EShLangTessControl; break; 51 | case GL_TESS_EVALUATION_SHADER : sh_lang = EShLangTessEvaluation; break; 52 | case GL_GEOMETRY_SHADER : sh_lang = EShLangGeometry; break; 53 | case GL_FRAGMENT_SHADER : sh_lang = EShLangFragment; break; 54 | default : 55 | RETURN_ERR( "unknown shader type" ); 56 | } 57 | 58 | CHECK_ERR( CompileGLSL( OUT src, OUT dbgInfo, {header.c_str(), inSource}, sh_lang, mode )); 59 | 60 | GLuint shader = glCreateShader( shaderType ); 61 | 62 | inSource = src.c_str(); 63 | glShaderSource( shader, 1, &inSource, nullptr ); 64 | glCompileShader( shader ); 65 | 66 | GLint status = 0; 67 | glGetShaderiv( shader, GL_COMPILE_STATUS, OUT &status ); 68 | 69 | if ( status != GL_TRUE ) 70 | { 71 | GLchar buf[1024] = {}; 72 | glGetShaderInfoLog( shader, sizeof(buf), nullptr, buf ); 73 | glDeleteShader( shader ); 74 | 75 | RETURN_ERR( "shader compilation failed" ); 76 | } 77 | 78 | GLuint prog = glCreateProgram(); 79 | glAttachShader( prog, shader ); 80 | 81 | glProgramParameteri( prog, GL_PROGRAM_SEPARABLE, GL_TRUE ); 82 | glLinkProgram( prog ); 83 | glGetProgramiv( prog, GL_LINK_STATUS, OUT &status ); 84 | 85 | if ( status != GL_TRUE ) 86 | { 87 | GLchar buf[1024] = {}; 88 | glGetProgramInfoLog( prog, sizeof(buf), nullptr, buf ); 89 | 90 | glDeleteShader( shader ); 91 | glDeleteProgram( prog ); 92 | 93 | RETURN_ERR( "failed to link program" ); 94 | } 95 | 96 | glDeleteShader( shader ); 97 | 98 | result = prog; 99 | return true; 100 | } 101 | 102 | /* 103 | ================================================= 104 | CompileGLSL 105 | ================================================= 106 | */ 107 | bool CompileGLSL (OUT std::string& glslResult, 108 | OUT ShaderTrace* dbgInfo, 109 | std::vector source, 110 | EShLanguage shaderType, 111 | ETraceMode mode) 112 | { 113 | EShMessages messages = EShMsgDefault; 114 | TProgram program; 115 | TShader shader { shaderType }; 116 | TBuiltInResource builtin_res = DefaultTBuiltInResource; 117 | 118 | shader.setStrings( source.data(), int(source.size()) ); 119 | shader.setEntryPoint( "main" ); 120 | shader.setEnvInput( EShSourceGlsl, shaderType, EShClientOpenGL, 110 ); 121 | shader.setEnvClient( EShClientOpenGL, EShTargetOpenGL_450 ); 122 | shader.setEnvTarget( EshTargetSpv, EShTargetSpv_1_3 ); 123 | 124 | //shader.setAutoMapLocations( true ); 125 | 126 | CHECK_ERR( shader.parse( &builtin_res, 450, ECoreProfile, false, true, messages )); 127 | 128 | program.addShader( &shader ); 129 | 130 | CHECK_ERR( program.link( messages )); 131 | 132 | TIntermediate* intermediate = program.getIntermediate( shader.getStage() ); 133 | CHECK_ERR( intermediate ); 134 | 135 | if ( dbgInfo ) 136 | { 137 | switch ( mode ) 138 | { 139 | case ETraceMode::DebugTrace : 140 | CHECK_ERR( dbgInfo->InsertTraceRecording( INOUT *intermediate, 8 )); 141 | break; 142 | 143 | case ETraceMode::Performance : 144 | CHECK_ERR( dbgInfo->InsertFunctionProfiler( INOUT *intermediate, 8, enableShaderSubgroupClock, enableShaderDeviceClock )); 145 | break; 146 | 147 | default : 148 | RETURN_ERR( "unknown shader trace mode" ); 149 | } 150 | 151 | dbgInfo->SetSource( source.data(), nullptr, source.size() ); 152 | } 153 | 154 | SpvOptions spv_options; 155 | spv::SpvBuildLogger logger; 156 | 157 | spv_options.generateDebugInfo = false; 158 | spv_options.disableOptimizer = true; 159 | spv_options.optimizeSize = false; 160 | spv_options.validate = false; 161 | 162 | std::vector spirv; 163 | GlslangToSpv( *intermediate, OUT spirv, &logger, &spv_options ); 164 | 165 | CHECK_ERR( spirv.size() ); 166 | 167 | spirv_cross::CompilerGLSL compiler {spirv.data(), spirv.size()}; 168 | spirv_cross::CompilerGLSL::Options opt = {}; 169 | 170 | opt.version = 450; 171 | opt.es = false; 172 | opt.vulkan_semantics = false; 173 | opt.separate_shader_objects = true; 174 | opt.enable_420pack_extension = true; 175 | 176 | opt.vertex.fixup_clipspace = false; 177 | opt.vertex.flip_vert_y = false; 178 | opt.vertex.support_nonzero_base_instance = true; 179 | 180 | opt.fragment.default_float_precision = spirv_cross::CompilerGLSL::Options::Precision::Highp; 181 | opt.fragment.default_int_precision = spirv_cross::CompilerGLSL::Options::Precision::Highp; 182 | 183 | compiler.set_common_options(opt); 184 | 185 | glslResult = compiler.compile(); 186 | return true; 187 | } 188 | -------------------------------------------------------------------------------- /tests/opengl/ShaderCompiler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #pragma once 4 | 5 | #include "ShaderTrace.h" 6 | #include "../source/Common.h" 7 | 8 | #include "GL/glew.h" 9 | 10 | #include 11 | #include 12 | 13 | enum class ETraceMode 14 | { 15 | None, 16 | DebugTrace, 17 | Performance, 18 | }; 19 | 20 | extern bool enableShaderSubgroupClock; 21 | extern bool enableShaderDeviceClock; 22 | 23 | bool CompileGLSL (OUT std::string& glslResult, 24 | OUT ShaderTrace* dbgInfo, 25 | std::vector source, 26 | EShLanguage shaderType, 27 | ETraceMode mode); 28 | 29 | bool CreateShader (OUT GLuint & shader, 30 | OUT ShaderTrace* dbgInfo, 31 | GLenum shaderType, 32 | const char * source, 33 | ETraceMode mode); 34 | -------------------------------------------------------------------------------- /tests/opengl/ShaderPerf_Test1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "ShaderCompiler.h" 4 | #include "Utils.h" 5 | 6 | extern bool ShaderPerf_Test1 () 7 | { 8 | static const char vert_shader_source[] = R"#( 9 | const vec2 g_Positions[] = { 10 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 11 | {-1.0f, 2.0f}, // primitive 1 - miss 12 | {-2.0f, 0.0f} // primitive 2 - must hit 13 | }; 14 | 15 | layout(location = 0) out vec4 out_Position; 16 | 17 | layout(location=2) out VertOutput { 18 | vec2 out_Texcoord; 19 | vec4 out_Color; 20 | }; 21 | 22 | void main() 23 | { 24 | out_Position = vec4( g_Positions[gl_VertexID], float(gl_VertexID) * 0.01f, 1.0f ); 25 | gl_Position = out_Position; 26 | out_Texcoord = g_Positions[gl_VertexID].xy * 0.5f + 0.5f; 27 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexID) / float(g_Positions.length())); 28 | })#"; 29 | 30 | static const char frag_shader_source[] = R"#( 31 | layout(location = 0) out vec4 out_Color; 32 | 33 | layout(location = 0) in vec4 in_Position; 34 | 35 | layout(location=2) in VertOutput { 36 | vec2 in_Texcoord; 37 | vec4 in_Color; 38 | }; 39 | 40 | float Fn2 (int i, float x) 41 | { 42 | return sin( x ) * float(i); 43 | } 44 | 45 | float Fn1 (const int i, in vec2 k) 46 | { 47 | float f = 0.0f; 48 | for (int j = 0; j < 10; ++j) 49 | { 50 | f += cos( 1.5432f * float(j) ) * Fn2( j, k[j&1] ); 51 | 52 | if ( j+i == 12 ) 53 | return f + 12.0f; 54 | } 55 | return f; 56 | } 57 | 58 | void main () 59 | { 60 | float c = Fn1( 3, in_Texcoord.xy + in_Position.yx ); 61 | out_Color = vec4(c); 62 | })#"; 63 | 64 | GLuint prog, vert, frag; 65 | ShaderTrace dbg_info; 66 | 67 | CHECK_ERR( CreateShader( OUT vert, nullptr, GL_VERTEX_SHADER, vert_shader_source, ETraceMode::None )); 68 | CHECK_ERR( CreateShader( OUT frag, OUT &dbg_info, GL_FRAGMENT_SHADER, frag_shader_source, ETraceMode::Performance )); 69 | 70 | glCreateProgramPipelines( 1, OUT &prog ); 71 | glUseProgramStages( prog, GL_VERTEX_SHADER_BIT, vert ); 72 | glUseProgramStages( prog, GL_FRAGMENT_SHADER_BIT, frag ); 73 | glBindProgramPipeline( prog ); 74 | 75 | uint width = 16, height = 16; 76 | 77 | GLuint dbg_buffer; 78 | CHECK_ERR( CreateDebugOutputBuffer( OUT dbg_buffer, {vert, frag} )); 79 | 80 | GLuint vao; 81 | glCreateVertexArrays( 1, OUT &vao ); 82 | glBindVertexArray( vao ); 83 | 84 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, dbg_buffer ); 85 | uint data[] = { width/2, height/2 }; // selected pixel 86 | glBufferSubData( GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data ); 87 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); 88 | glMemoryBarrier( GL_BUFFER_UPDATE_BARRIER_BIT ); 89 | 90 | GLuint rt; 91 | glGenRenderbuffers( 1, OUT &rt ); 92 | glBindRenderbuffer( GL_RENDERBUFFER, rt ); 93 | glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA8, width, height ); 94 | glBindRenderbuffer( GL_RENDERBUFFER, 0 ); 95 | 96 | GLuint fbo; 97 | glGenFramebuffers( 1, OUT &fbo ); 98 | glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fbo ); 99 | glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt ); 100 | 101 | glViewport( 0, 0, width, height ); 102 | glDrawArrays( GL_TRIANGLE_STRIP, 0, 5 ); 103 | 104 | glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); 105 | glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT ); 106 | 107 | glDeleteRenderbuffers( 1, &rt ); 108 | glDeleteFramebuffers( 1, &fbo ); 109 | glDeleteProgramPipelines( 1, &prog ); 110 | glDeleteProgram( vert ); 111 | glDeleteProgram( frag ); 112 | glDeleteVertexArrays( 1, &vao ); 113 | 114 | glFinish(); 115 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, dbg_buffer ); 116 | void* trace = glMapBuffer( GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY ); 117 | CHECK_ERR( trace ); 118 | 119 | std::vector result; 120 | CHECK_ERR( dbg_info.ParseShaderTrace( trace, BufferSize, OUT result )); 121 | CHECK_ERR( result.size() ); 122 | 123 | glUnmapBuffer( GL_SHADER_STORAGE_BUFFER ); 124 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); 125 | glDeleteBuffers( 1, &dbg_buffer ); 126 | 127 | TEST_PASSED(); 128 | return true; 129 | } 130 | -------------------------------------------------------------------------------- /tests/opengl/ShaderTrace_Test1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "ShaderCompiler.h" 4 | #include "Utils.h" 5 | 6 | extern bool ShaderTrace_Test1 () 7 | { 8 | static const char vert_shader_source[] = R"#( 9 | const vec2 g_Positions[] = { 10 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 11 | {-1.0f, 2.0f}, // primitive 1 - miss 12 | {-2.0f, 0.0f} // primitive 2 - must hit 13 | }; 14 | 15 | layout(location=0) out vec4 out_Position; 16 | 17 | layout(location=2) out VertOutput { 18 | vec2 out_Texcoord; 19 | vec4 out_Color; 20 | }; 21 | 22 | void main() 23 | { 24 | out_Position = vec4( g_Positions[gl_VertexID], float(gl_VertexID) * 0.01f, 1.0f ); 25 | gl_Position = out_Position; 26 | out_Texcoord = g_Positions[gl_VertexID].xy * 0.5f + 0.5f; 27 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexID) / float(g_Positions.length())); 28 | })#"; 29 | 30 | static const char frag_shader_source[] = R"#( 31 | layout(location = 0) out vec4 out_Color; 32 | 33 | layout(location=0) in vec4 in_Position; 34 | 35 | layout(location=2) in VertOutput { 36 | vec2 in_Texcoord; 37 | vec4 in_Color; 38 | }; 39 | 40 | float Fn1 (const int i, in float k, out int res) 41 | { 42 | float f = 0.0f; 43 | res = 11; 44 | for (int j = i; j < 10; ++j) { 45 | f += 1.2f * 46 | cos(float(j) + k); 47 | if (f > 15.7f) { 48 | res = j; 49 | return f * 10.0f; 50 | } 51 | } 52 | return fract(f + k); 53 | } 54 | 55 | void main () 56 | { 57 | ivec2 c1; 58 | float c0 = Fn1( 3, in_Texcoord.x + in_Position.y, c1.x ); 59 | out_Color[1] = c0 + float(c1.x); 60 | return; 61 | })#"; 62 | 63 | GLuint prog, vert, frag; 64 | ShaderTrace dbg_info; 65 | 66 | CHECK_ERR( CreateShader( OUT vert, nullptr, GL_VERTEX_SHADER, vert_shader_source, ETraceMode::None )); 67 | CHECK_ERR( CreateShader( OUT frag, OUT &dbg_info, GL_FRAGMENT_SHADER, frag_shader_source, ETraceMode::DebugTrace )); 68 | 69 | glCreateProgramPipelines( 1, OUT &prog ); 70 | glUseProgramStages( prog, GL_VERTEX_SHADER_BIT, vert ); 71 | glUseProgramStages( prog, GL_FRAGMENT_SHADER_BIT, frag ); 72 | glBindProgramPipeline( prog ); 73 | 74 | GLuint dbg_buffer; 75 | CHECK_ERR( CreateDebugOutputBuffer( OUT dbg_buffer, {vert, frag} )); 76 | 77 | GLuint vao; 78 | glCreateVertexArrays( 1, OUT &vao ); 79 | glBindVertexArray( vao ); 80 | 81 | uint width = 16, height = 16; 82 | 83 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, dbg_buffer ); 84 | uint data[] = { width/2, height/2 }; // selected pixel 85 | glBufferSubData( GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data ); 86 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); 87 | glMemoryBarrier( GL_BUFFER_UPDATE_BARRIER_BIT ); 88 | 89 | GLuint rt; 90 | glGenRenderbuffers( 1, OUT &rt ); 91 | glBindRenderbuffer( GL_RENDERBUFFER, rt ); 92 | glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA8, width, height ); 93 | glBindRenderbuffer( GL_RENDERBUFFER, 0 ); 94 | 95 | GLuint fbo; 96 | glGenFramebuffers( 1, OUT &fbo ); 97 | glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fbo ); 98 | glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt ); 99 | 100 | glViewport( 0, 0, width, height ); 101 | glDrawArrays( GL_TRIANGLE_STRIP, 0, 5 ); 102 | 103 | glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); 104 | glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT ); 105 | 106 | glDeleteRenderbuffers( 1, &rt ); 107 | glDeleteFramebuffers( 1, &fbo ); 108 | 109 | glDeleteProgramPipelines( 1, &prog ); 110 | glDeleteProgram( vert ); 111 | glDeleteProgram( frag ); 112 | glDeleteVertexArrays( 1, &vao ); 113 | 114 | glFinish(); 115 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, dbg_buffer ); 116 | void* trace = glMapBuffer( GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY ); 117 | CHECK_ERR( trace ); 118 | 119 | CHECK_ERR( TestDebugTraceOutput( {&dbg_info}, trace, "ShaderTrace_Test1.txt" )); 120 | 121 | glUnmapBuffer( GL_SHADER_STORAGE_BUFFER ); 122 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); 123 | glDeleteBuffers( 1, &dbg_buffer ); 124 | 125 | TEST_PASSED(); 126 | return true; 127 | } 128 | -------------------------------------------------------------------------------- /tests/opengl/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "GL/glew.h" 4 | #include "GLFW/glfw3.h" 5 | #include "../source/Common.h" 6 | #include "ShaderCompiler.h" 7 | #include 8 | 9 | using namespace std::string_literals; 10 | 11 | extern bool ShaderPerf_Test1 (); 12 | extern bool ShaderTrace_Test1 (); 13 | 14 | 15 | void GLAPIENTRY DbgCallback (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) 16 | { 17 | std::cout << "OpenGL error: " << message << std::endl; 18 | } 19 | 20 | 21 | int main () 22 | { 23 | glslang::InitializeProcess(); 24 | 25 | CHECK_ERR( glfwInit() == GLFW_TRUE, 1 ); 26 | 27 | glfwWindowHint( GLFW_CLIENT_API, GLFW_OPENGL_API ); 28 | glfwWindowHint( GLFW_DOUBLEBUFFER, 1 ); 29 | glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 ); 30 | glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 5 ); 31 | glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, 1 ); 32 | glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, 1 ); 33 | glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); 34 | 35 | GLFWwindow* wnd = glfwCreateWindow( 800, 600, "GLSL-Trace", nullptr, nullptr ); 36 | CHECK_ERR( wnd, 1 ); 37 | 38 | glfwMakeContextCurrent( wnd ); 39 | 40 | CHECK_ERR( glewInit() == GL_NO_ERROR, 1 ); 41 | 42 | glDebugMessageCallback( DbgCallback, nullptr ); 43 | glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE ); 44 | glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS ); 45 | glEnable( GL_DEBUG_OUTPUT ); 46 | 47 | GLint ext_count = 0; 48 | glGetIntegerv( GL_NUM_EXTENSIONS, &ext_count ); 49 | 50 | for (int i = 0; i < ext_count; ++i) 51 | { 52 | const char* ext = (const char*)glGetStringi(GL_EXTENSIONS, i); 53 | enableShaderDeviceClock |= ("GL_EXT_shader_realtime_clock"s == ext); 54 | enableShaderSubgroupClock |= ("GL_ARB_shader_clock"s == ext); 55 | } 56 | 57 | for (int i = 0; i < 10; ++i) 58 | { 59 | if ( glfwWindowShouldClose( wnd )) 60 | break; 61 | 62 | if ( i == 1 ) 63 | { 64 | CHECK_ERR( ShaderTrace_Test1(), 1 ); 65 | 66 | if ( enableShaderDeviceClock or enableShaderSubgroupClock ) 67 | CHECK_ERR( ShaderPerf_Test1(), 1 ); 68 | } 69 | 70 | glfwPollEvents(); 71 | glfwSwapBuffers( wnd ); 72 | } 73 | 74 | glfwDestroyWindow( wnd ); 75 | glfwTerminate(); 76 | 77 | glslang::FinalizeProcess(); 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test1.txt: -------------------------------------------------------------------------------- 1 | //> gl_FragCoord: float4 {8.500000, 8.500000, 0.505312, 1.000000} 2 | //> gl_PrimitiveID: int {0} 3 | //> in_Position: float4 {0.062500, 0.062500, 0.010625, 1.000000} 4 | //> (out): float4 {0.915000, 0.427500, 0.021250, 0.842500} 5 | no source 6 | 7 | //> k: float {0.593750} 8 | //> i: int {3} 9 | 11. float Fn1 (const int i, in float k, out int res) 10 | 11 | //> f: float {0.000000} 12 | 13. f = 0.0f; 13 | 14 | //> res: int {11} 15 | 14. res = 11; 16 | 17 | //> j: int {3} 18 | // i: int {3} 19 | 15. j = i; j < 10; ++j) { 20 | 21 | //> (out): bool {true} 22 | // i: int {3} 23 | // j: int {3} 24 | 15. for (int j = i; j < 10; ++j) { 25 | 26 | //> cos(): float {-0.899507} 27 | // k: float {0.593750} 28 | // j: int {3} 29 | 16. * 30 | 17. cos(float(j) + k); 31 | 32 | //> f: float {-1.079408} 33 | // k: float {0.593750} 34 | // j: int {3} 35 | // cos(): float {-0.899507} 36 | 16. f += 1.2f * 37 | 17. cos(float(j) + k); 38 | 39 | //> (out): bool {false} 40 | // f: float {-1.079408} 41 | 18. if (f > 15.7f) { 42 | 43 | //> j: int {4} 44 | 15. ++j) { 45 | 46 | //> (out): bool {true} 47 | // i: int {3} 48 | // j: int {4} 49 | 15. for (int j = i; j < 10; ++j) { 50 | 51 | //> cos(): float {-0.118361} 52 | // k: float {0.593750} 53 | // j: int {4} 54 | 16. * 55 | 17. cos(float(j) + k); 56 | 57 | //> f: float {-1.221441} 58 | // k: float {0.593750} 59 | // j: int {4} 60 | // cos(): float {-0.118361} 61 | 16. f += 1.2f * 62 | 17. cos(float(j) + k); 63 | 64 | //> (out): bool {false} 65 | // f: float {-1.221441} 66 | 18. if (f > 15.7f) { 67 | 68 | //> j: int {5} 69 | 15. ++j) { 70 | 71 | //> (out): bool {true} 72 | // i: int {3} 73 | // j: int {5} 74 | 15. for (int j = i; j < 10; ++j) { 75 | 76 | //> cos(): float {0.771605} 77 | // k: float {0.593750} 78 | // j: int {5} 79 | 16. * 80 | 17. cos(float(j) + k); 81 | 82 | //> f: float {-0.295515} 83 | // k: float {0.593750} 84 | // j: int {5} 85 | // cos(): float {0.771605} 86 | 16. f += 1.2f * 87 | 17. cos(float(j) + k); 88 | 89 | //> (out): bool {false} 90 | // f: float {-0.295515} 91 | 18. if (f > 15.7f) { 92 | 93 | //> j: int {6} 94 | 15. ++j) { 95 | 96 | //> (out): bool {true} 97 | // i: int {3} 98 | // j: int {6} 99 | 15. for (int j = i; j < 10; ++j) { 100 | 101 | //> cos(): float {0.952161} 102 | // k: float {0.593750} 103 | // j: int {6} 104 | 16. * 105 | 17. cos(float(j) + k); 106 | 107 | //> f: float {0.847079} 108 | // k: float {0.593750} 109 | // j: int {6} 110 | // cos(): float {0.952161} 111 | 16. f += 1.2f * 112 | 17. cos(float(j) + k); 113 | 114 | //> (out): bool {false} 115 | // f: float {0.847079} 116 | 18. if (f > 15.7f) { 117 | 118 | //> j: int {7} 119 | 15. ++j) { 120 | 121 | //> (out): bool {true} 122 | // i: int {3} 123 | // j: int {7} 124 | 15. for (int j = i; j < 10; ++j) { 125 | 126 | //> cos(): float {0.257305} 127 | // k: float {0.593750} 128 | // j: int {7} 129 | 16. * 130 | 17. cos(float(j) + k); 131 | 132 | //> f: float {1.155844} 133 | // k: float {0.593750} 134 | // j: int {7} 135 | // cos(): float {0.257305} 136 | 16. f += 1.2f * 137 | 17. cos(float(j) + k); 138 | 139 | //> (out): bool {false} 140 | // f: float {1.155844} 141 | 18. if (f > 15.7f) { 142 | 143 | //> j: int {8} 144 | 15. ++j) { 145 | 146 | //> (out): bool {true} 147 | // i: int {3} 148 | // j: int {8} 149 | 15. for (int j = i; j < 10; ++j) { 150 | 151 | //> cos(): float {-0.674116} 152 | // k: float {0.593750} 153 | // j: int {8} 154 | 16. * 155 | 17. cos(float(j) + k); 156 | 157 | //> f: float {0.346905} 158 | // k: float {0.593750} 159 | // j: int {8} 160 | // cos(): float {-0.674116} 161 | 16. f += 1.2f * 162 | 17. cos(float(j) + k); 163 | 164 | //> (out): bool {false} 165 | // f: float {0.346905} 166 | 18. if (f > 15.7f) { 167 | 168 | //> j: int {9} 169 | 15. ++j) { 170 | 171 | //> (out): bool {true} 172 | // i: int {3} 173 | // j: int {9} 174 | 15. for (int j = i; j < 10; ++j) { 175 | 176 | //> cos(): float {-0.985758} 177 | // k: float {0.593750} 178 | // j: int {9} 179 | 16. * 180 | 17. cos(float(j) + k); 181 | 182 | //> f: float {-0.836005} 183 | // k: float {0.593750} 184 | // j: int {9} 185 | // cos(): float {-0.985758} 186 | 16. f += 1.2f * 187 | 17. cos(float(j) + k); 188 | 189 | //> (out): bool {false} 190 | // f: float {-0.836005} 191 | 18. if (f > 15.7f) { 192 | 193 | //> j: int {10} 194 | 15. ++j) { 195 | 196 | //> (out): bool {false} 197 | // i: int {3} 198 | // j: int {10} 199 | 15. for (int j = i; j < 10; ++j) { 200 | 201 | //> fract(): float {0.757745} 202 | // k: float {0.593750} 203 | // f: float {-0.836005} 204 | 23. return fract(f + k); 205 | 206 | //> c0: float {0.757745} 207 | // in_Position: float4 {0.062500, 0.062500, 0.010625, 1.000000} 208 | 29. c0 = Fn1( 3, in_Texcoord.x + in_Position.y, c1.x ); 209 | 210 | //> out_Color: float2 {0.000000, 11.757745} 211 | // c0: float {0.757745} 212 | 30. out_Color[1] = c0 + float(c1.x); 213 | 214 | //> (out): void 215 | 31. return; 216 | 217 | //--------------------------- 218 | 219 | //> gl_FragCoord: float4 {8.500000, 8.500000, 0.514201, 1.000000} 220 | //> gl_PrimitiveID: int {2} 221 | //> in_Position: float4 {0.062500, 0.062500, 0.028403, 1.000000} 222 | //> (out): float4 {0.772778, 0.640833, 0.056806, 0.913611} 223 | no source 224 | 225 | //> k: float {0.593750} 226 | //> i: int {3} 227 | 11. float Fn1 (const int i, in float k, out int res) 228 | 229 | //> f: float {0.000000} 230 | 13. f = 0.0f; 231 | 232 | //> res: int {11} 233 | 14. res = 11; 234 | 235 | //> j: int {3} 236 | // i: int {3} 237 | 15. j = i; j < 10; ++j) { 238 | 239 | //> (out): bool {true} 240 | // i: int {3} 241 | // j: int {3} 242 | 15. for (int j = i; j < 10; ++j) { 243 | 244 | //> cos(): float {-0.899507} 245 | // k: float {0.593750} 246 | // j: int {3} 247 | 16. * 248 | 17. cos(float(j) + k); 249 | 250 | //> f: float {-1.079408} 251 | // k: float {0.593750} 252 | // j: int {3} 253 | // cos(): float {-0.899507} 254 | 16. f += 1.2f * 255 | 17. cos(float(j) + k); 256 | 257 | //> (out): bool {false} 258 | // f: float {-1.079408} 259 | 18. if (f > 15.7f) { 260 | 261 | //> j: int {4} 262 | 15. ++j) { 263 | 264 | //> (out): bool {true} 265 | // i: int {3} 266 | // j: int {4} 267 | 15. for (int j = i; j < 10; ++j) { 268 | 269 | //> cos(): float {-0.118361} 270 | // k: float {0.593750} 271 | // j: int {4} 272 | 16. * 273 | 17. cos(float(j) + k); 274 | 275 | //> f: float {-1.221441} 276 | // k: float {0.593750} 277 | // j: int {4} 278 | // cos(): float {-0.118361} 279 | 16. f += 1.2f * 280 | 17. cos(float(j) + k); 281 | 282 | //> (out): bool {false} 283 | // f: float {-1.221441} 284 | 18. if (f > 15.7f) { 285 | 286 | //> j: int {5} 287 | 15. ++j) { 288 | 289 | //> (out): bool {true} 290 | // i: int {3} 291 | // j: int {5} 292 | 15. for (int j = i; j < 10; ++j) { 293 | 294 | //> cos(): float {0.771605} 295 | // k: float {0.593750} 296 | // j: int {5} 297 | 16. * 298 | 17. cos(float(j) + k); 299 | 300 | //> f: float {-0.295515} 301 | // k: float {0.593750} 302 | // j: int {5} 303 | // cos(): float {0.771605} 304 | 16. f += 1.2f * 305 | 17. cos(float(j) + k); 306 | 307 | //> (out): bool {false} 308 | // f: float {-0.295515} 309 | 18. if (f > 15.7f) { 310 | 311 | //> j: int {6} 312 | 15. ++j) { 313 | 314 | //> (out): bool {true} 315 | // i: int {3} 316 | // j: int {6} 317 | 15. for (int j = i; j < 10; ++j) { 318 | 319 | //> cos(): float {0.952161} 320 | // k: float {0.593750} 321 | // j: int {6} 322 | 16. * 323 | 17. cos(float(j) + k); 324 | 325 | //> f: float {0.847079} 326 | // k: float {0.593750} 327 | // j: int {6} 328 | // cos(): float {0.952161} 329 | 16. f += 1.2f * 330 | 17. cos(float(j) + k); 331 | 332 | //> (out): bool {false} 333 | // f: float {0.847079} 334 | 18. if (f > 15.7f) { 335 | 336 | //> j: int {7} 337 | 15. ++j) { 338 | 339 | //> (out): bool {true} 340 | // i: int {3} 341 | // j: int {7} 342 | 15. for (int j = i; j < 10; ++j) { 343 | 344 | //> cos(): float {0.257305} 345 | // k: float {0.593750} 346 | // j: int {7} 347 | 16. * 348 | 17. cos(float(j) + k); 349 | 350 | //> f: float {1.155844} 351 | // k: float {0.593750} 352 | // j: int {7} 353 | // cos(): float {0.257305} 354 | 16. f += 1.2f * 355 | 17. cos(float(j) + k); 356 | 357 | //> (out): bool {false} 358 | // f: float {1.155844} 359 | 18. if (f > 15.7f) { 360 | 361 | //> j: int {8} 362 | 15. ++j) { 363 | 364 | //> (out): bool {true} 365 | // i: int {3} 366 | // j: int {8} 367 | 15. for (int j = i; j < 10; ++j) { 368 | 369 | //> cos(): float {-0.674116} 370 | // k: float {0.593750} 371 | // j: int {8} 372 | 16. * 373 | 17. cos(float(j) + k); 374 | 375 | //> f: float {0.346905} 376 | // k: float {0.593750} 377 | // j: int {8} 378 | // cos(): float {-0.674116} 379 | 16. f += 1.2f * 380 | 17. cos(float(j) + k); 381 | 382 | //> (out): bool {false} 383 | // f: float {0.346905} 384 | 18. if (f > 15.7f) { 385 | 386 | //> j: int {9} 387 | 15. ++j) { 388 | 389 | //> (out): bool {true} 390 | // i: int {3} 391 | // j: int {9} 392 | 15. for (int j = i; j < 10; ++j) { 393 | 394 | //> cos(): float {-0.985758} 395 | // k: float {0.593750} 396 | // j: int {9} 397 | 16. * 398 | 17. cos(float(j) + k); 399 | 400 | //> f: float {-0.836005} 401 | // k: float {0.593750} 402 | // j: int {9} 403 | // cos(): float {-0.985758} 404 | 16. f += 1.2f * 405 | 17. cos(float(j) + k); 406 | 407 | //> (out): bool {false} 408 | // f: float {-0.836005} 409 | 18. if (f > 15.7f) { 410 | 411 | //> j: int {10} 412 | 15. ++j) { 413 | 414 | //> (out): bool {false} 415 | // i: int {3} 416 | // j: int {10} 417 | 15. for (int j = i; j < 10; ++j) { 418 | 419 | //> fract(): float {0.757745} 420 | // k: float {0.593750} 421 | // f: float {-0.836005} 422 | 23. return fract(f + k); 423 | 424 | //> c0: float {0.757745} 425 | // in_Position: float4 {0.062500, 0.062500, 0.028403, 1.000000} 426 | 29. c0 = Fn1( 3, in_Texcoord.x + in_Position.y, c1.x ); 427 | 428 | //> out_Color: float2 {0.000000, 11.757745} 429 | // c0: float {0.757745} 430 | 30. out_Color[1] = c0 + float(c1.x); 431 | 432 | //> (out): void 433 | 31. return; 434 | 435 | //--------------------------- 436 | 437 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test10.txt: -------------------------------------------------------------------------------- 1 | //> gl_GlobalInvocationID: uint3 {0, 0, 0} 2 | //> gl_LocalInvocationID: uint3 {0, 0, 0} 3 | //> gl_WorkGroupID: uint3 {0, 0, 0} 4 | no source 5 | 6 | //> (out): float4 {-1.000000, -1.000000, 0.000000, 1.000000} 7 | 33. gl_MeshVerticesNV[I].gl_Position = vec4(g_Positions[I], 0.0f, 1.0f); 8 | 9 | //> (out): float4 {0.000000, 0.000000, 0.000000, 0.000000} 10 | 34. Output[I].color = g_Positions[I].xyxy * 0.5f + 0.5f; 11 | 12 | //> (out): uint {0} 13 | 35. gl_PrimitiveIndicesNV[I] = I; 14 | 15 | //> (out): bool {true} 16 | 37. if ( I == 0 ) 17 | 18 | //> gl_PrimitiveCountNV: uint {3} 19 | 38. gl_PrimitiveCountNV = 3; 20 | 21 | //--------------------------- 22 | 23 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test14.txt: -------------------------------------------------------------------------------- 1 | //> gl_LaunchIDNV: uint3 {50, 50, 0} 2 | no source 3 | 4 | //> payload: float4 {0.412000, 0.796000, 1.000000, 1.000000} 5 | 8. payload = vec4( 0.412f, 0.796f, 1.0f, 1.0f ); 6 | 7 | //--------------------------- 8 | 9 | //> gl_LaunchIDNV: uint3 {60, 40, 0} 10 | no source 11 | 12 | //> uv: float2 {0.472441, 0.314961} 13 | // gl_LaunchIDNV: uint3 {60, 40, 0} 14 | 10. uv = vec2(gl_LaunchIDNV.xy) / vec2(gl_LaunchSizeNV.xy - 1); 15 | 16 | //> origin: float3 {0.472441, 0.685039, -1.000000} 17 | // uv: float2 {0.472441, 0.314961} 18 | 11. origin = vec3(uv.x, 1.0f - uv.y, -1.0f); 19 | 20 | //> traceNV(): void 21 | // origin: float3 {0.472441, 0.685039, -1.000000} 22 | 14. un_RtScene, /*rayFlags*/gl_RayFlagsNoneNV, /*cullMask*/0xFF, 23 | 15. /*sbtRecordOffset*/0, /*sbtRecordStride*/0, /*missIndex*/0, 24 | 16. /*origin*/origin, /*Tmin*/0.0f, 25 | 17. /*direction*/direction, /*Tmax*/10.0f, 26 | 18. /*payload*/PAYLOAD_LOC ); 27 | 28 | //> imageStore(): void 29 | // gl_LaunchIDNV: uint3 {60, 40, 0} 30 | 20. imageStore( un_Output, ivec2(gl_LaunchIDNV), payload ); 31 | 32 | //--------------------------- 33 | 34 | //> gl_LaunchIDNV: uint3 {70, 80, 0} 35 | no source 36 | 37 | //> barycentrics: float3 {0.277559, 0.482283, 0.240157} 38 | 9. barycentrics = vec3(1.0f - HitAttribs.x - HitAttribs.y, HitAttribs.x, HitAttribs.y); 39 | 40 | //> payload: float4 {0.277559, 0.482283, 0.240157, 1.000000} 41 | // barycentrics: float3 {0.277559, 0.482283, 0.240157} 42 | 10. payload = vec4(barycentrics, 1.0); 43 | 44 | //--------------------------- 45 | 46 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test2.txt: -------------------------------------------------------------------------------- 1 | //> gl_GlobalInvocationID: uint3 {8, 8, 0} 2 | //> gl_LocalInvocationID: uint3 {0, 0, 0} 3 | //> gl_WorkGroupID: uint3 {8, 8, 0} 4 | no source 5 | 6 | //> point: float2 {0.533333, 0.533333} 7 | // gl_GlobalInvocationID: uint3 {8, 8, 0} 8 | 8. point = (vec3(gl_GlobalInvocationID) / vec3(gl_NumWorkGroups * gl_WorkGroupSize - 1)).xy; 9 | 10 | //> (out): bool {false} 11 | // gl_GlobalInvocationID: uint3 {8, 8, 0} 12 | 10. if ( (gl_GlobalInvocationID.x & 1) == 1 ) 13 | 14 | //> color: float4 {0.533333, 0.533333, 0.533333, 0.533333} 15 | // point: float2 {0.533333, 0.533333} 16 | 16. color = point.xyyx; 17 | 18 | //> cos(): float {0.861117} 19 | // color: float4 {0.533333, 0.533333, 0.533333, 0.533333} 20 | 17. color.x = cos(color.y) * color.z; 21 | 22 | //> color: float4 {0.459263, 0.533333, 0.533333, 0.533333} 23 | // cos(): float {0.861117} 24 | 17. color.x = cos(color.y) * color.z; 25 | 26 | //> Test1(): void 27 | 23. Test1( color ); 28 | 29 | //> imageStore(): void 30 | // gl_GlobalInvocationID: uint3 {8, 8, 0} 31 | 24. imageStore( un_OutImage, ivec2(gl_GlobalInvocationID.xy), color ); 32 | 33 | //--------------------------- 34 | 35 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test4.txt: -------------------------------------------------------------------------------- 1 | //> gl_FragCoord: float4 {8.500000, 8.500000, 0.021250, 1.000000} 2 | //> gl_PrimitiveID: int {0} 3 | no source 4 | 5 | //> i: ulong {18446744069414584320} 6 | 8. i = 0xFFFFFFFF00000000ul; 7 | 8 | //> d: double2 {1.23400000e+50, 3.87573200} 9 | 9. d = dvec2(1.234e+50LF, 3.875732LF); 10 | 11 | //> i: ulong {18446744073709551615} 12 | 11. i |= 0xFFFFFFFFul; 13 | 14 | //> out_Color: float {1.844674e+19} 15 | // i: ulong {18446744073709551615} 16 | 14. out_Color[0] = float(i); 17 | 18 | //> out_Color: float2 {1.844674e+19, inf} 19 | // d: double2 {1.23400000e+50, 3.87573200} 20 | 15. out_Color[1] = float(d.x); 21 | 22 | //> out_Color: float3 {1.844674e+19, inf, 7.751464} 23 | // d: double2 {1.23400000e+50, 3.87573200} 24 | 16. out_Color[2] = float(d.y); 25 | 26 | //--------------------------- 27 | 28 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test5.txt: -------------------------------------------------------------------------------- 1 | //> gl_VertexIndex: int {4} 2 | //> gl_InstanceIndex: int {0} 3 | no source 4 | 5 | //> out_Position: float4 {-2.000000, 0.000000, 0.040000, 1.000000} 6 | // gl_VertexIndex: int {4} 7 | 21. out_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 8 | 9 | //> (out): float4 {-2.000000, 0.000000, 0.040000, 1.000000} 10 | // out_Position: float4 {-2.000000, 0.000000, 0.040000, 1.000000} 11 | 22. gl_Position = out_Position; 12 | 13 | //> (out): float2 {-0.500000, 0.500000} 14 | // gl_VertexIndex: int {4} 15 | 23. out_Texcoord = g_Positions[gl_VertexIndex].xy * 0.5f + 0.5f; 16 | 17 | //> (out): float4 {0.680000, 0.780000, 0.080000, 0.960000} 18 | // gl_VertexIndex: int {4} 19 | 24. out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexIndex) / float(g_Positions.length())); 20 | 21 | //--------------------------- 22 | 23 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test6.txt: -------------------------------------------------------------------------------- 1 | //> gl_InvocationID: int {0} 2 | //> gl_PrimitiveIDIn: int {1} 3 | no source 4 | 5 | //> pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 6 | 13. pos = gl_in[0].gl_Position; 7 | 8 | //> va: float2 {-0.250000, -1.400000} 9 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 10 | 16. va = pos.xy + vec2(-0.5, -0.5) * size; 11 | 12 | //> (out): float4 {-0.250000, -1.400000, 0.100000, 1.000000} 13 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 14 | // va: float2 {-0.250000, -1.400000} 15 | 17. gl_Position = vec4(va, pos.zw); 16 | 17 | //> out_Color: float4 {1.000000, 1.000000, 1.000000, 1.000000} 18 | 18. out_Color = vec4(1.0f); 19 | 20 | //> EmitVertex(): void 21 | 19. EmitVertex(); 22 | 23 | //> vb: float2 {-0.250000, 0.600000} 24 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 25 | 21. vb = pos.xy + vec2(-0.5, 0.5) * size; 26 | 27 | //> (out): float4 {-0.250000, 0.600000, 0.100000, 1.000000} 28 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 29 | // vb: float2 {-0.250000, 0.600000} 30 | 22. gl_Position = vec4(vb, pos.zw); 31 | 32 | //> out_Color: float4 {0.700000, 0.700000, 0.700000, 0.700000} 33 | 23. out_Color = vec4(0.7f); 34 | 35 | //> EmitVertex(): void 36 | 24. EmitVertex(); 37 | 38 | //> vd: float2 {1.750000, -1.400000} 39 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 40 | 26. vd = pos.xy + vec2(0.5, -0.5) * size; 41 | 42 | //> (out): float4 {1.750000, -1.400000, 0.100000, 1.000000} 43 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 44 | // vd: float2 {1.750000, -1.400000} 45 | 27. gl_Position = vec4(vd, pos.zw); 46 | 47 | //> out_Color: float4 {0.020000, 0.020000, 0.020000, 0.020000} 48 | 28. out_Color = vec4(0.02f); 49 | 50 | //> EmitVertex(): void 51 | 29. EmitVertex(); 52 | 53 | //> vc: float2 {1.750000, 0.600000} 54 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 55 | 31. vc = pos.xy + vec2(0.5, 0.5) * size; 56 | 57 | //> (out): float4 {1.750000, 0.600000, 0.100000, 1.000000} 58 | // pos: float4 {0.750000, -0.400000, 0.100000, 1.000000} 59 | // vc: float2 {1.750000, 0.600000} 60 | 32. gl_Position = vec4(vc, pos.zw); 61 | 62 | //> out_Color: float4 {0.500000, 0.500000, 0.500000, 0.500000} 63 | 33. out_Color = vec4(0.5f); 64 | 65 | //> EmitVertex(): void 66 | 34. EmitVertex(); 67 | 68 | //> EndPrimitive(): void 69 | 36. EndPrimitive(); 70 | 71 | //--------------------------- 72 | 73 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test7.txt: -------------------------------------------------------------------------------- 1 | //> gl_InvocationID: int {2} 2 | //> gl_PrimitiveID: int {0} 3 | no source 4 | 5 | //> (out): bool {false} 6 | // gl_InvocationID: int {2} 7 | 15. if ( I == 0 ) { 8 | 9 | //> (out): float4 {2.000000, -1.000000, 0.020000, 1.000000} 10 | // gl_InvocationID: int {2} 11 | 21. gl_out[I].gl_Position = gl_in[I].gl_Position; 12 | 13 | //> (out): float {5.000000} 14 | // gl_InvocationID: int {2} 15 | 22. out_Level[I] = in_Level[I]; 16 | 17 | //--------------------------- 18 | 19 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test8.txt: -------------------------------------------------------------------------------- 1 | //> gl_PrimitiveID: int {0} 2 | //> gl_TessCoord: float3 {0.000000, 0.000000, 1.000000} 3 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 4 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 5 | no source 6 | 7 | //> pos: float4 {2.000000, -1.000000, 0.020000, 1.000000} 8 | // gl_TessCoord: float3 {0.000000, 0.000000, 1.000000} 9 | 18. pos = Interpolate( gl_in, .gl_Position ); 10 | 11 | //> (out): float4 {2.000000, -1.000000, 0.020000, 1.000000} 12 | // pos: float4 {2.000000, -1.000000, 0.020000, 1.000000} 13 | 19. gl_Position = pos; 14 | 15 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 16 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 17 | 18 | //--------------------------- 19 | 20 | //> gl_PrimitiveID: int {0} 21 | //> gl_TessCoord: float3 {0.000000, 0.500000, 0.500000} 22 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 23 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 24 | no source 25 | 26 | //> pos: float4 {0.500000, 0.500000, 0.015000, 1.000000} 27 | // gl_TessCoord: float3 {0.000000, 0.500000, 0.500000} 28 | 18. pos = Interpolate( gl_in, .gl_Position ); 29 | 30 | //> (out): float4 {0.500000, 0.500000, 0.015000, 1.000000} 31 | // pos: float4 {0.500000, 0.500000, 0.015000, 1.000000} 32 | 19. gl_Position = pos; 33 | 34 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 35 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 36 | 37 | //--------------------------- 38 | 39 | //> gl_PrimitiveID: int {0} 40 | //> gl_TessCoord: float3 {0.000000, 1.000000, 0.000000} 41 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 42 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 43 | no source 44 | 45 | //> pos: float4 {-1.000000, 2.000000, 0.010000, 1.000000} 46 | // gl_TessCoord: float3 {0.000000, 1.000000, 0.000000} 47 | 18. pos = Interpolate( gl_in, .gl_Position ); 48 | 49 | //> (out): float4 {-1.000000, 2.000000, 0.010000, 1.000000} 50 | // pos: float4 {-1.000000, 2.000000, 0.010000, 1.000000} 51 | 19. gl_Position = pos; 52 | 53 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 54 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 55 | 56 | //--------------------------- 57 | 58 | //> gl_PrimitiveID: int {0} 59 | //> gl_TessCoord: float3 {0.222214, 0.222214, 0.555573} 60 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 61 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 62 | no source 63 | 64 | //> pos: float4 {0.666718, -0.333359, 0.013334, 1.000000} 65 | // gl_TessCoord: float3 {0.222214, 0.222214, 0.555573} 66 | 18. pos = Interpolate( gl_in, .gl_Position ); 67 | 68 | //> (out): float4 {0.666718, -0.333359, 0.013334, 1.000000} 69 | // pos: float4 {0.666718, -0.333359, 0.013334, 1.000000} 70 | 19. gl_Position = pos; 71 | 72 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 73 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 74 | 75 | //--------------------------- 76 | 77 | //> gl_PrimitiveID: int {0} 78 | //> gl_TessCoord: float3 {0.222214, 0.555557, 0.222229} 79 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 80 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 81 | no source 82 | 83 | //> pos: float4 {-0.333313, 0.666672, 0.010000, 1.000000} 84 | // gl_TessCoord: float3 {0.222214, 0.555557, 0.222229} 85 | 18. pos = Interpolate( gl_in, .gl_Position ); 86 | 87 | //> (out): float4 {-0.333313, 0.666672, 0.010000, 1.000000} 88 | // pos: float4 {-0.333313, 0.666672, 0.010000, 1.000000} 89 | 19. gl_Position = pos; 90 | 91 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 92 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 93 | 94 | //--------------------------- 95 | 96 | //> gl_PrimitiveID: int {0} 97 | //> gl_TessCoord: float3 {0.500000, 0.000000, 0.500000} 98 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 99 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 100 | no source 101 | 102 | //> pos: float4 {0.500000, -1.000000, 0.010000, 1.000000} 103 | // gl_TessCoord: float3 {0.500000, 0.000000, 0.500000} 104 | 18. pos = Interpolate( gl_in, .gl_Position ); 105 | 106 | //> (out): float4 {0.500000, -1.000000, 0.010000, 1.000000} 107 | // pos: float4 {0.500000, -1.000000, 0.010000, 1.000000} 108 | 19. gl_Position = pos; 109 | 110 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 111 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 112 | 113 | //--------------------------- 114 | 115 | //> gl_PrimitiveID: int {0} 116 | //> gl_TessCoord: float3 {0.500000, 0.500000, 0.000000} 117 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 118 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 119 | no source 120 | 121 | //> pos: float4 {-1.000000, 0.500000, 0.005000, 1.000000} 122 | // gl_TessCoord: float3 {0.500000, 0.500000, 0.000000} 123 | 18. pos = Interpolate( gl_in, .gl_Position ); 124 | 125 | //> (out): float4 {-1.000000, 0.500000, 0.005000, 1.000000} 126 | // pos: float4 {-1.000000, 0.500000, 0.005000, 1.000000} 127 | 19. gl_Position = pos; 128 | 129 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 130 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 131 | 132 | //--------------------------- 133 | 134 | //> gl_PrimitiveID: int {0} 135 | //> gl_TessCoord: float3 {0.555557, 0.222229, 0.222214} 136 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 137 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 138 | no source 139 | 140 | //> pos: float4 {-0.333359, -0.333313, 0.006667, 1.000000} 141 | // gl_TessCoord: float3 {0.555557, 0.222229, 0.222214} 142 | 18. pos = Interpolate( gl_in, .gl_Position ); 143 | 144 | //> (out): float4 {-0.333359, -0.333313, 0.006667, 1.000000} 145 | // pos: float4 {-0.333359, -0.333313, 0.006667, 1.000000} 146 | 19. gl_Position = pos; 147 | 148 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 149 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 150 | 151 | //--------------------------- 152 | 153 | //> gl_PrimitiveID: int {0} 154 | //> gl_TessCoord: float3 {1.000000, 0.000000, 0.000000} 155 | //> gl_TessLevelInner: float2 {3.000000, 3.000000} 156 | //> gl_TessLevelOuter: float4 {1.100000, 1.100000, 1.100000, 1.100000} 157 | no source 158 | 159 | //> pos: float4 {-1.000000, -1.000000, 0.000000, 1.000000} 160 | // gl_TessCoord: float3 {1.000000, 0.000000, 0.000000} 161 | 18. pos = Interpolate( gl_in, .gl_Position ); 162 | 163 | //> (out): float4 {-1.000000, -1.000000, 0.000000, 1.000000} 164 | // pos: float4 {-1.000000, -1.000000, 0.000000, 1.000000} 165 | 19. gl_Position = pos; 166 | 167 | //> out_Color: float4 {0.000000, 1.500000, 3.000000, 1.000000} 168 | 20. out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 169 | 170 | //--------------------------- 171 | 172 | -------------------------------------------------------------------------------- /tests/ref/ShaderTrace_Test9.txt: -------------------------------------------------------------------------------- 1 | //> gl_LaunchIDNV: uint3 {8, 8, 0} 2 | no source 3 | 4 | //> uv: float2 {0.533333, 0.533333} 5 | // gl_LaunchIDNV: uint3 {8, 8, 0} 6 | 8. uv = vec2(gl_LaunchIDNV.xy) / vec2(gl_LaunchSizeNV.xy - 1); 7 | 8 | //> origin: float3 {0.533333, 0.466667, -1.000000} 9 | // uv: float2 {0.533333, 0.533333} 10 | 9. origin = vec3(uv.x, 1.0f - uv.y, -1.0f); 11 | 12 | //> traceNV(): void 13 | // origin: float3 {0.533333, 0.466667, -1.000000} 14 | 12. un_RtScene, /*rayFlags*/gl_RayFlagsNoneNV, /*cullMask*/0xFF, 15 | 13. /*sbtRecordOffset*/0, /*sbtRecordStride*/0, /*missIndex*/0, 16 | 14. /*origin*/origin, /*Tmin*/0.0f, 17 | 15. /*direction*/direction, /*Tmax*/10.0f, 18 | 16. /*payload*/PAYLOAD_LOC ); 19 | 20 | //> imageStore(): void 21 | // gl_LaunchIDNV: uint3 {8, 8, 0} 22 | 18. imageStore( un_Output, ivec2(gl_LaunchIDNV), payload ); 23 | 24 | //--------------------------- 25 | 26 | -------------------------------------------------------------------------------- /tests/utils/Utils.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Utils.h" 4 | #include "../source/Common.h" 5 | 6 | // Warning: 7 | // Before testing on new GPU set 'UpdateReferences' to 'true', run tests, 8 | // using git compare new references with origin, only float values may differ slightly. 9 | // Then set 'UpdateReferences' to 'false' and run tests again. 10 | // All tests must pass. 11 | static const bool UpdateReferences = true; 12 | 13 | #ifndef _MSC_VER 14 | # define fopen_s( _outFile_, _name_, _mode_ ) (*_outFile_=fopen(_name_, _mode_)) 15 | #endif 16 | 17 | /* 18 | ================================================= 19 | TestDebugTraceOutput 20 | ================================================= 21 | */ 22 | bool TestDebugTraceOutput (const std::vector& shaders, 23 | const void* readBackPtr, 24 | const std::string & referenceFile) 25 | { 26 | CHECK_ERR( referenceFile.size() ); 27 | CHECK_ERR( shaders.size() ); 28 | 29 | std::string merged; 30 | std::vector debug_output; 31 | 32 | for (auto& module : shaders) 33 | { 34 | std::vector temp; 35 | CHECK_ERR( module->ParseShaderTrace( readBackPtr, BufferSize, OUT temp )); 36 | CHECK_ERR( temp.size() ); 37 | debug_output.insert( debug_output.end(), temp.begin(), temp.end() ); 38 | } 39 | 40 | std::sort( debug_output.begin(), debug_output.end() ); 41 | for (auto& str : debug_output) { (merged += str) += "//---------------------------\n\n"; } 42 | 43 | if ( UpdateReferences ) 44 | { 45 | FILE* file = nullptr; 46 | fopen_s( OUT &file, (std::string{DATA_PATH} + referenceFile).c_str(), "wb" ); 47 | CHECK_ERR( file ); 48 | CHECK_ERR( fwrite( merged.c_str(), sizeof(merged[0]), merged.size(), file ) == merged.size() ); 49 | fclose( file ); 50 | 51 | return true; 52 | } 53 | 54 | std::string file_data; 55 | { 56 | FILE* file = nullptr; 57 | fopen_s( OUT &file, (std::string{DATA_PATH} + referenceFile).c_str(), "rb" ); 58 | CHECK_ERR( file ); 59 | 60 | CHECK_ERR( fseek( file, 0, SEEK_END ) == 0 ); 61 | const long size = ftell( file ); 62 | CHECK_ERR( fseek( file, 0, SEEK_SET ) == 0 ); 63 | 64 | file_data.resize( size ); 65 | CHECK_ERR( fread( file_data.data(), sizeof(file_data[0]), file_data.size(), file ) == file_data.size() ); 66 | fclose( file ); 67 | } 68 | 69 | CHECK_ERR( file_data == merged ); 70 | return true; 71 | } 72 | 73 | /* 74 | ================================================= 75 | CreateDebugOutputBuffer 76 | ================================================= 77 | */ 78 | #ifdef ENABLE_OPENGL 79 | bool CreateDebugOutputBuffer (OUT GLuint & dbgBuffer, 80 | const std::vector& programs) 81 | { 82 | glGenBuffers( 1, OUT &dbgBuffer ); 83 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, dbgBuffer ); 84 | glBufferStorage( GL_SHADER_STORAGE_BUFFER, BufferSize, nullptr, GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT ); 85 | 86 | uint zero = 0; 87 | glClearBufferData( GL_SHADER_STORAGE_BUFFER, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, &zero ); 88 | 89 | glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); 90 | glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, dbgBuffer ); 91 | 92 | for (auto& prog : programs) 93 | { 94 | GLuint sb_index = glGetProgramResourceIndex( prog, GL_SHADER_STORAGE_BLOCK, "dbg_ShaderTraceStorage" ); 95 | 96 | if ( sb_index == GL_INVALID_INDEX ) 97 | continue; 98 | 99 | glShaderStorageBlockBinding( prog, sb_index, 0 ); 100 | } 101 | return true; 102 | } 103 | #endif // ENABLE_OPENGL 104 | -------------------------------------------------------------------------------- /tests/utils/Utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include "ShaderTrace.h" 8 | 9 | static const size_t BufferSize = 8 << 20; 10 | 11 | bool TestDebugTraceOutput (const std::vector& shaders, 12 | const void* readBackPtr, 13 | const std::string & referenceFile); 14 | 15 | #ifdef ENABLE_OPENGL 16 | #include "GL/glew.h" 17 | bool CreateDebugOutputBuffer (GLuint & dbgBuffer, 18 | const std::vector& programs); 19 | #endif 20 | 21 | 22 | // function name 23 | #ifdef _MSC_VER 24 | # define FUNCTION_NAME __FUNCTION__ 25 | 26 | #elif defined(__clang__) || defined(__gcc__) 27 | # define FUNCTION_NAME __func__ 28 | 29 | #else 30 | # define FUNCTION_NAME "unknown function" 31 | #endif 32 | 33 | #define TEST_PASSED() std::cout << FUNCTION_NAME << " - passed" << std::endl; 34 | -------------------------------------------------------------------------------- /tests/vulkan/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 3.10 FATAL_ERROR ) 2 | 3 | file( GLOB_RECURSE SOURCES "*.*" ) 4 | add_executable( "Tests.Vulkan" ${SOURCES} ${UTILS_SRC} ) 5 | source_group( TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES} ) 6 | 7 | set_property( TARGET "Tests.Vulkan" PROPERTY FOLDER "" ) 8 | target_link_libraries( "Tests.Vulkan" PUBLIC "ShaderTrace" ) 9 | target_link_libraries( "Tests.Vulkan" PUBLIC "Vulkan-lib" ) 10 | 11 | if (FALSE) 12 | target_link_libraries( "Tests.Vulkan" PUBLIC "SPIRV-Cross-lib" ) 13 | target_compile_definitions( "Tests.Vulkan" PUBLIC ENABLE_SPIRV_CROSS ) 14 | endif () 15 | 16 | target_compile_definitions( "Tests.Vulkan" PUBLIC "DATA_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/../ref/\"" ) 17 | target_compile_definitions( "Tests.Vulkan" PUBLIC VK_NO_PROTOTYPES ) 18 | 19 | if (UNIX) 20 | target_link_libraries( "Tests.Vulkan" PUBLIC "dl;pthread" ) 21 | endif () 22 | 23 | if (NOT CI_BUILD) 24 | add_test( NAME "Tests.Vulkan" COMMAND "Tests.Vulkan" ) 25 | endif () 26 | -------------------------------------------------------------------------------- /tests/vulkan/ClockMap_Test1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | { -1.0f, 1.0f }, { -1.0f, -1.0f }, 17 | { 1.0f, 1.0f }, { 1.0f, -1.0f } 18 | }; 19 | 20 | void main() 21 | { 22 | gl_Position = vec4( g_Positions[gl_VertexIndex], 0.0f, 1.0f ); 23 | })#"; 24 | 25 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 26 | } 27 | 28 | // create fragment shader 29 | { 30 | static const char frag_shader_source[] = R"#( 31 | layout(location = 0) out vec4 out_Color; 32 | 33 | // DHash from https://www.shadertoy.com/view/4djSRW 34 | // MIT License... 35 | // Copyright (c)2014 David Hoskins. 36 | float DHash13 (const vec3 p) 37 | { 38 | vec3 p3 = fract( p * 0.1031 ); 39 | p3 += dot( p3, p3.yzx + 19.19 ); 40 | return fract( (p3.x + p3.y) * p3.z ); 41 | } 42 | 43 | vec3 DHash33 (const vec3 p) 44 | { 45 | vec3 p3 = fract( p * vec3(0.1031, 0.1030, 0.0973) ); 46 | p3 += dot( p3, p3.yxz + 19.19 ); 47 | return fract( (p3.xxy + p3.yxx) * p3.zyx ); 48 | } 49 | 50 | float ValueNoise (const vec3 pos) 51 | { 52 | // from https://www.shadertoy.com/view/4sc3z2 53 | // license CC BY-NC-SA 3.0 54 | # define hash( _p_ ) (DHash13( _p_ ) * 2.0 - 1.0) 55 | 56 | vec3 pi = floor(pos); 57 | vec3 pf = pos - pi; 58 | 59 | vec3 w = pf * pf * (3.0 - 2.0 * pf); 60 | 61 | return mix( 62 | mix( 63 | mix(hash(pi + vec3(0, 0, 0)), hash(pi + vec3(1, 0, 0)), w.x), 64 | mix(hash(pi + vec3(0, 0, 1)), hash(pi + vec3(1, 0, 1)), w.x), 65 | w.z), 66 | mix( 67 | mix(hash(pi + vec3(0, 1, 0)), hash(pi + vec3(1, 1, 0)), w.x), 68 | mix(hash(pi + vec3(0, 1, 1)), hash(pi + vec3(1, 1, 1)), w.x), 69 | w.z), 70 | w.y); 71 | # undef hash 72 | } 73 | 74 | vec4 Generator () 75 | { 76 | const int max_iter = 128; 77 | 78 | vec3 p = gl_FragCoord.xyz; 79 | float accum = 0.0; 80 | 81 | for (uint i = 0; i < max_iter; ++i) 82 | { 83 | float n = ValueNoise( p * 4.0 ); 84 | accum += n; 85 | p += DHash33( p ) * 0.1; 86 | } 87 | 88 | return vec4(accum / float(max_iter)); 89 | } 90 | 91 | void main () 92 | { 93 | out_Color = Generator(); 94 | })#"; 95 | 96 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::TimeMap, 0 )); 97 | } 98 | return true; 99 | } 100 | 101 | /* 102 | ================================================= 103 | ClockMap_Test1 104 | ================================================= 105 | */ 106 | extern bool ClockMap_Test1 (Device& vulkan) 107 | { 108 | if ( not vulkan.shaderClockFeat.shaderDeviceClock ) 109 | return true; // not supported 110 | 111 | // create renderpass and framebuffer 112 | uint width = 16, height = 16; 113 | VkRenderPass render_pass; 114 | VkImage color_target; 115 | VkFramebuffer framebuffer; 116 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 117 | OUT render_pass, OUT color_target, OUT framebuffer )); 118 | 119 | 120 | // create pipeline 121 | VkShaderModule vert_shader, frag_shader; 122 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 123 | 124 | VkDescriptorSetLayout ds_layout; 125 | VkDescriptorSet desc_set; 126 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 127 | 128 | VkPipelineLayout ppln_layout; 129 | VkPipeline pipeline; 130 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 131 | 132 | 133 | // build command buffer 134 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 135 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 136 | 137 | // image layout undefined -> color_attachment 138 | { 139 | VkImageMemoryBarrier barrier = {}; 140 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 141 | barrier.srcAccessMask = 0; 142 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 143 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 144 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 145 | barrier.image = color_target; 146 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 147 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 148 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 149 | 150 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 151 | 0, nullptr, 0, nullptr, 1, &barrier); 152 | } 153 | 154 | // setup storage buffer 155 | { 156 | const uint data[] = { BitCast(1.0f), BitCast(1.0f), // scale 157 | width, height }; // dimension 158 | 159 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 160 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 161 | } 162 | 163 | // debug output storage read/write after write 164 | { 165 | VkBufferMemoryBarrier barrier = {}; 166 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 167 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 168 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 169 | barrier.buffer = vulkan.debugOutputBuf; 170 | barrier.offset = 0; 171 | barrier.size = VK_WHOLE_SIZE; 172 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 173 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 174 | 175 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 176 | 0, nullptr, 1, &barrier, 0, nullptr); 177 | } 178 | 179 | // begin render pass 180 | { 181 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 182 | VkRenderPassBeginInfo begin_rp = {}; 183 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 184 | begin_rp.framebuffer = framebuffer; 185 | begin_rp.renderPass = render_pass; 186 | begin_rp.renderArea = { {0,0}, {width, height} }; 187 | begin_rp.clearValueCount = 1; 188 | begin_rp.pClearValues = &clear_value; 189 | 190 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 191 | } 192 | 193 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 194 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 195 | 196 | // set dynamic states 197 | { 198 | VkViewport viewport = {}; 199 | viewport.x = 0.0f; 200 | viewport.y = 0.0f; 201 | viewport.width = float(width); 202 | viewport.height = float(height); 203 | viewport.minDepth = 0.0f; 204 | viewport.maxDepth = 1.0f; 205 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 206 | 207 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 208 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 209 | } 210 | 211 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 4, 1, 0, 0 ); 212 | 213 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 214 | 215 | // debug output storage read after write 216 | { 217 | VkBufferMemoryBarrier barrier = {}; 218 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 219 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 220 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 221 | barrier.buffer = vulkan.debugOutputBuf; 222 | barrier.offset = 0; 223 | barrier.size = VK_WHOLE_SIZE; 224 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 225 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 226 | 227 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 228 | 0, nullptr, 1, &barrier, 0, nullptr); 229 | } 230 | 231 | // copy shader debug output into host visible memory 232 | { 233 | VkBufferCopy region = {}; 234 | region.srcOffset = 0; 235 | region.dstOffset = 0; 236 | region.size = vulkan.debugOutputSize; 237 | 238 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 239 | } 240 | 241 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 242 | 243 | 244 | // submit commands and wait 245 | { 246 | VkSubmitInfo submit = {}; 247 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 248 | submit.commandBufferCount = 1; 249 | submit.pCommandBuffers = &vulkan.cmdBuffer; 250 | 251 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 252 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 253 | } 254 | 255 | CHECK_ERR( vulkan.CheckTimeMap( {frag_shader} )); 256 | 257 | vulkan.FreeTempHandles(); 258 | 259 | std::cout << "ClockMap_Test1 - passed" << std::endl; 260 | return true; 261 | } 262 | -------------------------------------------------------------------------------- /tests/vulkan/Device.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #pragma once 4 | 5 | #include "VulkanLoader.h" 6 | #include 7 | 8 | using namespace std::string_literals; 9 | 10 | enum class ETraceMode 11 | { 12 | None, 13 | DebugTrace, 14 | Performance, 15 | TimeMap, 16 | }; 17 | 18 | 19 | class Device final : public VulkanDeviceFn 20 | { 21 | public: 22 | VkDevice device = VK_NULL_HANDLE; 23 | VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; 24 | VkInstance instance = VK_NULL_HANDLE; 25 | VkQueue queue = VK_NULL_HANDLE; 26 | uint queueFamily = ~0u; 27 | VkCommandPool cmdPool = VK_NULL_HANDLE; 28 | VkCommandBuffer cmdBuffer = VK_NULL_HANDLE; 29 | VkDescriptorPool descPool = VK_NULL_HANDLE; 30 | VkBuffer debugOutputBuf = VK_NULL_HANDLE; 31 | VkBuffer readBackBuf = VK_NULL_HANDLE; 32 | VkDeviceMemory debugOutputMem = VK_NULL_HANDLE; 33 | VkDeviceMemory readBackMem = VK_NULL_HANDLE; 34 | void * readBackPtr = nullptr; 35 | uint debugOutputSize = 128 << 20; 36 | 37 | bool hasMeshShader = false; 38 | bool hasRayTracing = false; 39 | bool hasShaderClock = false; 40 | 41 | VkPhysicalDeviceProperties deviceProps; 42 | VkPhysicalDeviceFeatures deviceFeat; 43 | VkPhysicalDeviceMeshShaderFeaturesNV meshShaderFeat; 44 | VkPhysicalDeviceMeshShaderPropertiesNV meshShaderProps; 45 | VkPhysicalDeviceShaderClockFeaturesKHR shaderClockFeat; 46 | VkPhysicalDeviceRayTracingPropertiesNV rayTracingProps; 47 | 48 | private: 49 | VkPhysicalDeviceMemoryProperties _deviceMemoryProperties; 50 | VkDebugUtilsMessengerEXT _debugUtilsMessenger = VK_NULL_HANDLE; 51 | 52 | using Debuggable_t = unordered_map< VkShaderModule, ShaderTrace* >; 53 | vector _tempBuf; 54 | Debuggable_t _debuggableShaders; 55 | 56 | VulkanDeviceFnTable _deviceFnTable; 57 | 58 | public: 59 | enum class EHandleType 60 | { 61 | Memory, 62 | Buffer, 63 | Image, 64 | ImageView, 65 | Pipeline, 66 | PipelineLayout, 67 | Shader, 68 | DescriptorSetLayout, 69 | RenderPass, 70 | Framebuffer, 71 | AccStruct, 72 | }; 73 | using TempHandles_t = vector>; 74 | TempHandles_t tempHandles; 75 | 76 | 77 | public: 78 | bool Create (); 79 | void Destroy (); 80 | 81 | bool GetMemoryTypeIndex (uint memoryTypeBits, VkMemoryPropertyFlags flags, OUT uint &memoryTypeIndex) const; 82 | 83 | static bool CheckErrors (VkResult errCode, const char *vkcall, const char *func, const char *file, int line); 84 | 85 | bool CreateDebugDescriptorSet (VkShaderStageFlags stages, 86 | OUT VkDescriptorSetLayout &dsLayout, OUT VkDescriptorSet &descSet); 87 | 88 | bool CreateRenderTarget (VkFormat colorFormat, uint width, uint height, VkImageUsageFlags imageUsage, 89 | OUT VkRenderPass &outRenderPass, OUT VkImage &outImage, 90 | OUT VkFramebuffer &outFramebuffer); 91 | 92 | bool CreateGraphicsPipelineVar1 (VkShaderModule vertShader, VkShaderModule fragShader, 93 | VkDescriptorSetLayout dsLayout, VkRenderPass renderPass, 94 | OUT VkPipelineLayout &outPipelineLayout, OUT VkPipeline &outPipeline); 95 | 96 | bool CreateGraphicsPipelineVar2 (VkShaderModule vertShader, VkShaderModule tessContShader, VkShaderModule tessEvalShader, 97 | VkShaderModule fragShader, VkDescriptorSetLayout dsLayout, VkRenderPass renderPass, uint patchSize, 98 | OUT VkPipelineLayout &outPipelineLayout, OUT VkPipeline &outPipeline); 99 | 100 | bool CreateMeshPipelineVar1 (VkShaderModule meshShader, VkShaderModule fragShader, 101 | VkDescriptorSetLayout dsLayout, VkRenderPass renderPass, 102 | OUT VkPipelineLayout &outPipelineLayout, OUT VkPipeline &outPipeline); 103 | 104 | bool CreateRayTracingScene (VkPipeline rtPipeline, uint numGroups, 105 | OUT VkBuffer &shaderBindingTable, 106 | OUT VkAccelerationStructureNV &topLevelAS, OUT VkAccelerationStructureNV &bottomLevelAS); 107 | 108 | bool Compile (OUT VkShaderModule& shaderModule, 109 | vector source, 110 | EShLanguage shaderType, 111 | ETraceMode mode = ETraceMode::None, 112 | uint dbgBufferSetIndex = ~0u, 113 | glslang::EShTargetLanguageVersion spvVersion = glslang::EShTargetSpv_1_3); 114 | 115 | bool TestDebugTraceOutput (vector modules, string referenceFile); 116 | 117 | bool TestPerformanceOutput (vector modules, vector fnNames); 118 | 119 | bool CheckTimeMap (vector modules, float emptyPxFactor = 1.0f); 120 | 121 | void FreeTempHandles (); 122 | 123 | 124 | private: 125 | bool _CreateDevice (); 126 | void _DestroyDevice (); 127 | 128 | bool _CreateResources (); 129 | void _DestroyResources (); 130 | 131 | void _ValidateInstanceVersion (INOUT uint &version) const; 132 | void _ValidateInstanceLayers (INOUT vector &layers) const; 133 | void _ValidateInstanceExtensions (INOUT vector &ext) const; 134 | void _ValidateDeviceExtensions (INOUT vector &ext) const; 135 | 136 | bool _GetDebugOutput (VkShaderModule shaderModule, const void *ptr, VkDeviceSize maxSize, OUT vector &result) const; 137 | 138 | bool _Compile (OUT vector& spirvData, 139 | OUT ShaderTrace* dbgInfo, 140 | uint dbgBufferSetIndex, 141 | vector source, 142 | EShLanguage shaderType, 143 | ETraceMode mode, 144 | glslang::EShTargetLanguageVersion spvVersion); 145 | 146 | VKAPI_ATTR static VkBool32 VKAPI_CALL 147 | _DebugUtilsCallback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, 148 | VkDebugUtilsMessageTypeFlagsEXT messageTypes, 149 | const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, 150 | void* pUserData); 151 | }; 152 | 153 | 154 | /* 155 | ================================================= 156 | BitCast 157 | ================================================= 158 | */ 159 | template 160 | ND_ inline constexpr To BitCast (const From& src) 161 | { 162 | static_assert( sizeof(To) == sizeof(From), "must be same size!" ); 163 | static_assert( alignof(To) == alignof(From), "must be same align!" ); 164 | static_assert( std::is_trivially_copyable::value and std::is_trivial::value, "must be trivial types!" ); 165 | 166 | To dst; 167 | std::memcpy( OUT &dst, &src, sizeof(To) ); 168 | return dst; 169 | } 170 | 171 | 172 | #define VK_CALL( ... ) \ 173 | { \ 174 | const ::VkResult __vk_err__ = (__VA_ARGS__); \ 175 | ::Device::CheckErrors( __vk_err__, #__VA_ARGS__, FUNCTION_NAME, __FILE__, __LINE__ ); \ 176 | } 177 | 178 | #define __PRIVATE_VK_CALL_R( _func_, _ret_, ... ) \ 179 | { \ 180 | const ::VkResult __vk_err__ = (_func_); \ 181 | if ( not ::Device::CheckErrors( __vk_err__, #_func_, FUNCTION_NAME, __FILE__, __LINE__ )) \ 182 | return _ret_; \ 183 | } 184 | 185 | #define VK_CHECK( ... ) \ 186 | __PRIVATE_VK_CALL_R( __GETARG_0( __VA_ARGS__ ), __GETARG_1( __VA_ARGS__, 0 )) 187 | 188 | // function name 189 | #ifdef _MSC_VER 190 | # define FUNCTION_NAME __FUNCTION__ 191 | 192 | #elif defined(__clang__) || defined(__gcc__) 193 | # define FUNCTION_NAME __func__ 194 | 195 | #else 196 | # define FUNCTION_NAME "unknown function" 197 | #endif 198 | 199 | #define TEST_PASSED() std::cout << FUNCTION_NAME << " - passed" << std::endl; 200 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderPerf_Test1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 17 | {-1.0f, 2.0f}, // primitive 1 - miss 18 | {-2.0f, 0.0f} // primitive 2 - must hit 19 | }; 20 | 21 | layout(location = 0) out vec4 out_Position; 22 | 23 | layout(location=2) out VertOutput { 24 | vec2 out_Texcoord; 25 | vec4 out_Color; 26 | }; 27 | 28 | void main() 29 | { 30 | out_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 31 | gl_Position = out_Position; 32 | out_Texcoord = g_Positions[gl_VertexIndex].xy * 0.5f + 0.5f; 33 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexIndex) / float(g_Positions.length())); 34 | })#"; 35 | 36 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 37 | } 38 | 39 | // create fragment shader 40 | { 41 | static const char frag_shader_source[] = R"#( 42 | layout(location = 0) out vec4 out_Color; 43 | 44 | layout(location = 0) in vec4 in_Position; 45 | 46 | layout(location=2) in VertOutput { 47 | vec2 in_Texcoord; 48 | vec4 in_Color; 49 | }; 50 | 51 | float Fn2 (int i, float x) 52 | { 53 | return sin( x ) * float(i); 54 | } 55 | 56 | float Fn1 (const int i, in vec2 k) 57 | { 58 | float f = 0.0f; 59 | for (int j = 0; j < 10; ++j) 60 | { 61 | f += cos( 1.5432f * float(j) ) * Fn2( j, k[j&1] ); 62 | 63 | if ( j+i == 12 ) 64 | return f + 12.0f; 65 | } 66 | return f; 67 | } 68 | 69 | void main () 70 | { 71 | float c = Fn1( 3, in_Texcoord.xy + in_Position.yx ); 72 | out_Color = vec4(c); 73 | })#"; 74 | 75 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::Performance, 0 )); 76 | } 77 | return true; 78 | } 79 | 80 | /* 81 | ================================================= 82 | ShaderPerf_Test1 83 | ================================================= 84 | */ 85 | extern bool ShaderPerf_Test1 (Device& vulkan) 86 | { 87 | // create renderpass and framebuffer 88 | uint width = 16, height = 16; 89 | VkRenderPass render_pass; 90 | VkImage color_target; 91 | VkFramebuffer framebuffer; 92 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 93 | OUT render_pass, OUT color_target, OUT framebuffer )); 94 | 95 | 96 | // create pipeline 97 | VkShaderModule vert_shader, frag_shader; 98 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 99 | 100 | VkDescriptorSetLayout ds_layout; 101 | VkDescriptorSet desc_set; 102 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 103 | 104 | VkPipelineLayout ppln_layout; 105 | VkPipeline pipeline; 106 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 107 | 108 | 109 | // build command buffer 110 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 111 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 112 | 113 | // image layout undefined -> color_attachment 114 | { 115 | VkImageMemoryBarrier barrier = {}; 116 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 117 | barrier.srcAccessMask = 0; 118 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 119 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 120 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 121 | barrier.image = color_target; 122 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 124 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 125 | 126 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 127 | 0, nullptr, 0, nullptr, 1, &barrier); 128 | } 129 | 130 | // setup storage buffer 131 | { 132 | const uint data[] = { width/2, height/2 }; // selected pixel 133 | 134 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 135 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 136 | } 137 | 138 | // debug output storage read/write after write 139 | { 140 | VkBufferMemoryBarrier barrier = {}; 141 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 142 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 143 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 144 | barrier.buffer = vulkan.debugOutputBuf; 145 | barrier.offset = 0; 146 | barrier.size = VK_WHOLE_SIZE; 147 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 148 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 149 | 150 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 151 | 0, nullptr, 1, &barrier, 0, nullptr); 152 | } 153 | 154 | // begin render pass 155 | { 156 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 157 | VkRenderPassBeginInfo begin_rp = {}; 158 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 159 | begin_rp.framebuffer = framebuffer; 160 | begin_rp.renderPass = render_pass; 161 | begin_rp.renderArea = { {0,0}, {width, height} }; 162 | begin_rp.clearValueCount = 1; 163 | begin_rp.pClearValues = &clear_value; 164 | 165 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 166 | } 167 | 168 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 169 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 170 | 171 | // set dynamic states 172 | { 173 | VkViewport viewport = {}; 174 | viewport.x = 0.0f; 175 | viewport.y = 0.0f; 176 | viewport.width = float(width); 177 | viewport.height = float(height); 178 | viewport.minDepth = 0.0f; 179 | viewport.maxDepth = 1.0f; 180 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 181 | 182 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 183 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 184 | } 185 | 186 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 5, 1, 0, 0 ); 187 | 188 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 189 | 190 | // debug output storage read after write 191 | { 192 | VkBufferMemoryBarrier barrier = {}; 193 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 194 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 195 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 196 | barrier.buffer = vulkan.debugOutputBuf; 197 | barrier.offset = 0; 198 | barrier.size = VK_WHOLE_SIZE; 199 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 200 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 201 | 202 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 203 | 0, nullptr, 1, &barrier, 0, nullptr); 204 | } 205 | 206 | // copy shader debug output into host visible memory 207 | { 208 | VkBufferCopy region = {}; 209 | region.srcOffset = 0; 210 | region.dstOffset = 0; 211 | region.size = vulkan.debugOutputSize; 212 | 213 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 214 | } 215 | 216 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 217 | 218 | 219 | // submit commands and wait 220 | { 221 | VkSubmitInfo submit = {}; 222 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 223 | submit.commandBufferCount = 1; 224 | submit.pCommandBuffers = &vulkan.cmdBuffer; 225 | 226 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 227 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 228 | } 229 | 230 | CHECK_ERR( vulkan.TestPerformanceOutput( 231 | {frag_shader}, { 232 | "float Fn2 (int i, float x)"s, 233 | "float Fn1 (const int i, in vec2 k)"s, 234 | "void main ()"s 235 | })); 236 | 237 | vulkan.FreeTempHandles(); 238 | 239 | TEST_PASSED(); 240 | return true; 241 | } 242 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 17 | {-1.0f, 2.0f}, // primitive 1 - miss 18 | {-2.0f, 0.0f} // primitive 2 - must hit 19 | }; 20 | 21 | layout(location=0) out vec4 out_Position; 22 | 23 | layout(location=2) out VertOutput { 24 | vec2 out_Texcoord; 25 | vec4 out_Color; 26 | }; 27 | 28 | void main() 29 | { 30 | out_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 31 | gl_Position = out_Position; 32 | out_Texcoord = g_Positions[gl_VertexIndex].xy * 0.5f + 0.5f; 33 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexIndex) / float(g_Positions.length())); 34 | })#"; 35 | 36 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 37 | } 38 | 39 | // create fragment shader 40 | { 41 | static const char frag_shader_source[] = R"#( 42 | layout(location = 0) out vec4 out_Color; 43 | 44 | layout(location=0) in vec4 in_Position; 45 | 46 | layout(location=2) in VertOutput { 47 | vec2 in_Texcoord; 48 | vec4 in_Color; 49 | }; 50 | 51 | float Fn1 (const int i, in float k, out int res) 52 | { 53 | float f = 0.0f; 54 | res = 11; 55 | for (int j = i; j < 10; ++j) { 56 | f += 1.2f * 57 | cos(float(j) + k); 58 | if (f > 15.7f) { 59 | res = j; 60 | return f * 10.0f; 61 | } 62 | } 63 | return fract(f + k); 64 | } 65 | 66 | void main () 67 | { 68 | ivec2 c1; 69 | float c0 = Fn1( 3, in_Texcoord.x + in_Position.y, c1.x ); 70 | out_Color[1] = c0 + float(c1.x); 71 | return; 72 | })#"; 73 | 74 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::DebugTrace, 0 )); 75 | } 76 | return true; 77 | } 78 | 79 | /* 80 | ================================================= 81 | ShaderTrace_Test1 82 | ================================================= 83 | */ 84 | extern bool ShaderTrace_Test1 (Device& vulkan) 85 | { 86 | // create renderpass and framebuffer 87 | uint width = 16, height = 16; 88 | VkRenderPass render_pass; 89 | VkImage color_target; 90 | VkFramebuffer framebuffer; 91 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 92 | OUT render_pass, OUT color_target, OUT framebuffer )); 93 | 94 | 95 | // create pipeline 96 | VkShaderModule vert_shader, frag_shader; 97 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 98 | 99 | VkDescriptorSetLayout ds_layout; 100 | VkDescriptorSet desc_set; 101 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 102 | 103 | VkPipelineLayout ppln_layout; 104 | VkPipeline pipeline; 105 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 106 | 107 | 108 | // build command buffer 109 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 110 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 111 | 112 | // image layout undefined -> color_attachment 113 | { 114 | VkImageMemoryBarrier barrier = {}; 115 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 116 | barrier.srcAccessMask = 0; 117 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 118 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 119 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 120 | barrier.image = color_target; 121 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 122 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 124 | 125 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 126 | 0, nullptr, 0, nullptr, 1, &barrier); 127 | } 128 | 129 | // setup storage buffer 130 | { 131 | const uint data[] = { width/2, height/2 }; // selected pixel 132 | 133 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 134 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 135 | } 136 | 137 | // debug output storage read/write after write 138 | { 139 | VkBufferMemoryBarrier barrier = {}; 140 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 141 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 142 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 143 | barrier.buffer = vulkan.debugOutputBuf; 144 | barrier.offset = 0; 145 | barrier.size = VK_WHOLE_SIZE; 146 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 147 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 148 | 149 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 150 | 0, nullptr, 1, &barrier, 0, nullptr); 151 | } 152 | 153 | // begin render pass 154 | { 155 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 156 | VkRenderPassBeginInfo begin_rp = {}; 157 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 158 | begin_rp.framebuffer = framebuffer; 159 | begin_rp.renderPass = render_pass; 160 | begin_rp.renderArea = { {0,0}, {width, height} }; 161 | begin_rp.clearValueCount = 1; 162 | begin_rp.pClearValues = &clear_value; 163 | 164 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 165 | } 166 | 167 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 168 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 169 | 170 | // set dynamic states 171 | { 172 | VkViewport viewport = {}; 173 | viewport.x = 0.0f; 174 | viewport.y = 0.0f; 175 | viewport.width = float(width); 176 | viewport.height = float(height); 177 | viewport.minDepth = 0.0f; 178 | viewport.maxDepth = 1.0f; 179 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 180 | 181 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 182 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 183 | } 184 | 185 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 5, 1, 0, 0 ); 186 | 187 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 188 | 189 | // debug output storage read after write 190 | { 191 | VkBufferMemoryBarrier barrier = {}; 192 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 193 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 194 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 195 | barrier.buffer = vulkan.debugOutputBuf; 196 | barrier.offset = 0; 197 | barrier.size = VK_WHOLE_SIZE; 198 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 199 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 200 | 201 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 202 | 0, nullptr, 1, &barrier, 0, nullptr); 203 | } 204 | 205 | // copy shader debug output into host visible memory 206 | { 207 | VkBufferCopy region = {}; 208 | region.srcOffset = 0; 209 | region.dstOffset = 0; 210 | region.size = vulkan.debugOutputSize; 211 | 212 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 213 | } 214 | 215 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 216 | 217 | 218 | // submit commands and wait 219 | { 220 | VkSubmitInfo submit = {}; 221 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 222 | submit.commandBufferCount = 1; 223 | submit.pCommandBuffers = &vulkan.cmdBuffer; 224 | 225 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 226 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 227 | } 228 | 229 | CHECK_ERR( vulkan.TestDebugTraceOutput( {frag_shader}, "ShaderTrace_Test1.txt" )); 230 | 231 | vulkan.FreeTempHandles(); 232 | 233 | TEST_PASSED(); 234 | return true; 235 | } 236 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test10.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &meshShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create mesh shader 13 | { 14 | static const char mesh_shader_source[] = R"#( 15 | #extension GL_NV_mesh_shader : require 16 | 17 | layout(local_size_x=9) in; 18 | layout(triangles) out; 19 | layout(max_vertices=9, max_primitives=3) out; 20 | 21 | //out uint gl_PrimitiveCountNV; 22 | //out uint gl_PrimitiveIndicesNV[]; // [max_primitives * 3 for triangles] 23 | 24 | const vec2 g_Positions[] = { 25 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, { 2.0f, -1.0f}, // primitive 0 - must hit 26 | {-1.0f, 2.0f}, { 2.0f, -1.0f}, {-1.0f, 2.0f}, // primitive 1 - miss 27 | { 2.0f, -1.0f}, {-1.0f, 2.0f}, {-2.0f, 0.0f} // primitive 2 - must hit 28 | }; 29 | 30 | out gl_MeshPerVertexNV { 31 | vec4 gl_Position; 32 | } gl_MeshVerticesNV[]; // [max_vertices] 33 | 34 | layout(location = 0) out MeshOutput { 35 | vec4 color; 36 | } Output[]; // [max_vertices] 37 | 38 | void dbg_EnableTraceRecording (bool b) {} 39 | 40 | void main () 41 | { 42 | const uint I = gl_LocalInvocationID.x; 43 | 44 | dbg_EnableTraceRecording( gl_GlobalInvocationID.x == 0 ); 45 | 46 | gl_MeshVerticesNV[I].gl_Position = vec4(g_Positions[I], 0.0f, 1.0f); 47 | Output[I].color = g_Positions[I].xyxy * 0.5f + 0.5f; 48 | gl_PrimitiveIndicesNV[I] = I; 49 | 50 | if ( I == 0 ) 51 | gl_PrimitiveCountNV = 3; 52 | })#"; 53 | 54 | CHECK_ERR( vulkan.Compile( OUT meshShader, {mesh_shader_source}, EShLangMeshNV, ETraceMode::DebugTrace, 0 )); 55 | } 56 | 57 | // create fragment shader 58 | { 59 | static const char frag_shader_source[] = R"#( 60 | layout(location = 0) out vec4 out_Color; 61 | 62 | layout(location = 0) in MeshOutput { 63 | vec4 color; 64 | } Input; 65 | 66 | void main () 67 | { 68 | out_Color = Input.color; 69 | })#"; 70 | 71 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment )); 72 | } 73 | return true; 74 | } 75 | 76 | /* 77 | ================================================= 78 | ShaderTrace_Test10 79 | ================================================= 80 | */ 81 | extern bool ShaderTrace_Test10 (Device& vulkan) 82 | { 83 | if ( not vulkan.meshShaderFeat.meshShader ) 84 | return true; 85 | 86 | // create renderpass and framebuffer 87 | uint width = 16, height = 16; 88 | VkRenderPass render_pass; 89 | VkImage color_target; 90 | VkFramebuffer framebuffer; 91 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 92 | OUT render_pass, OUT color_target, OUT framebuffer )); 93 | 94 | 95 | // create pipeline 96 | VkShaderModule mesh_shader, frag_shader; 97 | CHECK_ERR( CompileShaders( vulkan, OUT mesh_shader, OUT frag_shader )); 98 | 99 | VkDescriptorSetLayout ds_layout; 100 | VkDescriptorSet desc_set; 101 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_MESH_BIT_NV, OUT ds_layout, OUT desc_set )); 102 | 103 | VkPipelineLayout ppln_layout; 104 | VkPipeline pipeline; 105 | CHECK_ERR( vulkan.CreateMeshPipelineVar1( mesh_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 106 | 107 | 108 | // build command buffer 109 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 110 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 111 | 112 | // image layout undefined -> color_attachment 113 | { 114 | VkImageMemoryBarrier barrier = {}; 115 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 116 | barrier.srcAccessMask = 0; 117 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 118 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 119 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 120 | barrier.image = color_target; 121 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 122 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 124 | 125 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 126 | 0, nullptr, 0, nullptr, 1, &barrier); 127 | } 128 | 129 | // setup storage buffer 130 | { 131 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, VK_WHOLE_SIZE, 0 ); 132 | } 133 | 134 | // debug output storage read/write after write 135 | { 136 | VkBufferMemoryBarrier barrier = {}; 137 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 138 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 139 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 140 | barrier.buffer = vulkan.debugOutputBuf; 141 | barrier.offset = 0; 142 | barrier.size = VK_WHOLE_SIZE; 143 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 144 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 145 | 146 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, 0, 147 | 0, nullptr, 1, &barrier, 0, nullptr); 148 | } 149 | 150 | // begin render pass 151 | { 152 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 153 | VkRenderPassBeginInfo begin_rp = {}; 154 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 155 | begin_rp.framebuffer = framebuffer; 156 | begin_rp.renderPass = render_pass; 157 | begin_rp.renderArea = { {0,0}, {width, height} }; 158 | begin_rp.clearValueCount = 1; 159 | begin_rp.pClearValues = &clear_value; 160 | 161 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 162 | } 163 | 164 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 165 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 166 | 167 | // set dynamic states 168 | { 169 | VkViewport viewport = {}; 170 | viewport.x = 0.0f; 171 | viewport.y = 0.0f; 172 | viewport.width = float(width); 173 | viewport.height = float(height); 174 | viewport.minDepth = 0.0f; 175 | viewport.maxDepth = 1.0f; 176 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 177 | 178 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 179 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 180 | } 181 | 182 | vulkan.vkCmdDrawMeshTasksNV( vulkan.cmdBuffer, 1, 0 ); 183 | 184 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 185 | 186 | // debug output storage read after write 187 | { 188 | VkBufferMemoryBarrier barrier = {}; 189 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 190 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 191 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 192 | barrier.buffer = vulkan.debugOutputBuf; 193 | barrier.offset = 0; 194 | barrier.size = VK_WHOLE_SIZE; 195 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 196 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 197 | 198 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 199 | 0, nullptr, 1, &barrier, 0, nullptr); 200 | } 201 | 202 | // copy shader debug output into host visible memory 203 | { 204 | VkBufferCopy region = {}; 205 | region.srcOffset = 0; 206 | region.dstOffset = 0; 207 | region.size = vulkan.debugOutputSize; 208 | 209 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 210 | } 211 | 212 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 213 | 214 | 215 | // submit commands and wait 216 | { 217 | VkSubmitInfo submit = {}; 218 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 219 | submit.commandBufferCount = 1; 220 | submit.pCommandBuffers = &vulkan.cmdBuffer; 221 | 222 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 223 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 224 | } 225 | 226 | CHECK_ERR( vulkan.TestDebugTraceOutput( {mesh_shader}, "ShaderTrace_Test10.txt" )); 227 | 228 | vulkan.FreeTempHandles(); 229 | 230 | TEST_PASSED(); 231 | return true; 232 | } 233 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test11.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &compShader) 11 | { 12 | // create compute shader 13 | { 14 | static const char comp_shader_source[] = R"#( 15 | layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in; 16 | 17 | layout(binding = 0) writeonly uniform image2D un_OutImage; 18 | 19 | void dbg_EnableTraceRecording (bool b) {} 20 | 21 | void main() 22 | { 23 | vec2 point = (vec3(gl_GlobalInvocationID) / vec3(gl_NumWorkGroups * gl_WorkGroupSize - 1)).xy; 24 | vec4 color; 25 | 26 | // 'point' wasn't recorded into trace 27 | dbg_EnableTraceRecording( gl_LocalInvocationID.x == 0 && gl_LocalInvocationID.y == 0 ); 28 | 29 | if ( (gl_GlobalInvocationID.x & 1) == 1 ) 30 | { 31 | color = vec4(1.0f); 32 | } 33 | else 34 | { 35 | color = point.xyyx; 36 | color.x = cos(color.y) * color.z; 37 | } 38 | imageStore( un_OutImage, ivec2(gl_GlobalInvocationID.xy), color ); 39 | } 40 | )#"; 41 | CHECK_ERR( vulkan.Compile( OUT compShader, {comp_shader_source}, EShLangCompute, ETraceMode::DebugTrace, 1 )); 42 | } 43 | return true; 44 | } 45 | 46 | /* 47 | ================================================= 48 | CreatePipeline 49 | ================================================= 50 | */ 51 | static bool CreatePipeline (Device &vulkan, VkShaderModule compShader, vector dsLayouts, 52 | OUT VkPipelineLayout &outPipelineLayout, OUT VkPipeline &outPipeline) 53 | { 54 | // create pipeline layout 55 | { 56 | VkPipelineLayoutCreateInfo info = {}; 57 | info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 58 | info.setLayoutCount = uint(dsLayouts.size()); 59 | info.pSetLayouts = dsLayouts.data(); 60 | info.pushConstantRangeCount = 0; 61 | info.pPushConstantRanges = nullptr; 62 | 63 | VK_CHECK( vulkan.vkCreatePipelineLayout( vulkan.device, &info, nullptr, OUT &outPipelineLayout )); 64 | vulkan.tempHandles.emplace_back( Device::EHandleType::PipelineLayout, uint64_t(outPipelineLayout) ); 65 | } 66 | 67 | VkComputePipelineCreateInfo info = {}; 68 | info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 69 | info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 70 | info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; 71 | info.stage.module = compShader; 72 | info.stage.pName = "main"; 73 | info.layout = outPipelineLayout; 74 | 75 | VK_CHECK( vulkan.vkCreateComputePipelines( vulkan.device, VK_NULL_HANDLE, 1, &info, nullptr, OUT &outPipeline )); 76 | vulkan.tempHandles.emplace_back( Device::EHandleType::Pipeline, uint64_t(outPipeline) ); 77 | 78 | return true; 79 | } 80 | 81 | /* 82 | ================================================= 83 | ShaderTrace_Test11 84 | ================================================= 85 | */ 86 | extern bool ShaderTrace_Test11 (Device& vulkan) 87 | { 88 | // create image 89 | VkImage image; 90 | VkImageView image_view; 91 | uint width = 16, height = 16; 92 | { 93 | VkImageCreateInfo info = {}; 94 | info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 95 | info.flags = 0; 96 | info.imageType = VK_IMAGE_TYPE_2D; 97 | info.format = VK_FORMAT_R8G8B8A8_UNORM; 98 | info.extent = { width, height, 1 }; 99 | info.mipLevels = 1; 100 | info.arrayLayers = 1; 101 | info.samples = VK_SAMPLE_COUNT_1_BIT; 102 | info.tiling = VK_IMAGE_TILING_OPTIMAL; 103 | info.usage = VK_IMAGE_USAGE_STORAGE_BIT; 104 | info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 105 | info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 106 | 107 | VK_CHECK( vulkan.vkCreateImage( vulkan.device, &info, nullptr, OUT &image )); 108 | vulkan.tempHandles.emplace_back( Device::EHandleType::Image, uint64_t(image) ); 109 | 110 | VkMemoryRequirements mem_req; 111 | vulkan.vkGetImageMemoryRequirements( vulkan.device, image, OUT &mem_req ); 112 | 113 | // allocate device local memory 114 | VkMemoryAllocateInfo alloc_info = {}; 115 | alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 116 | alloc_info.allocationSize = mem_req.size; 117 | CHECK_ERR( vulkan.GetMemoryTypeIndex( mem_req.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, OUT alloc_info.memoryTypeIndex )); 118 | 119 | VkDeviceMemory image_mem; 120 | VK_CHECK( vulkan.vkAllocateMemory( vulkan.device, &alloc_info, nullptr, OUT &image_mem )); 121 | vulkan.tempHandles.emplace_back( Device::EHandleType::Memory, uint64_t(image_mem) ); 122 | 123 | VK_CHECK( vulkan.vkBindImageMemory( vulkan.device, image, image_mem, 0 )); 124 | } 125 | 126 | // create image view 127 | { 128 | VkImageViewCreateInfo info = {}; 129 | info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 130 | info.flags = 0; 131 | info.image = image; 132 | info.viewType = VK_IMAGE_VIEW_TYPE_2D; 133 | info.format = VK_FORMAT_R8G8B8A8_UNORM; 134 | info.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; 135 | info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 136 | 137 | VK_CHECK( vulkan.vkCreateImageView( vulkan.device, &info, nullptr, OUT &image_view )); 138 | vulkan.tempHandles.emplace_back( Device::EHandleType::ImageView, uint64_t(image_view) ); 139 | } 140 | 141 | 142 | // create pipeline 143 | VkShaderModule comp_shader; 144 | CHECK_ERR( CompileShaders( vulkan, OUT comp_shader )); 145 | 146 | VkDescriptorSetLayout ds1_layout, ds2_layout; 147 | VkDescriptorSet desc_set1, desc_set2; 148 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_COMPUTE_BIT, OUT ds2_layout, OUT desc_set2 )); 149 | 150 | // create layout 151 | { 152 | VkDescriptorSetLayoutBinding binding = {}; 153 | binding.binding = 0; 154 | binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 155 | binding.descriptorCount = 1; 156 | binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 157 | 158 | VkDescriptorSetLayoutCreateInfo info = {}; 159 | info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 160 | info.bindingCount = 1; 161 | info.pBindings = &binding; 162 | 163 | VK_CHECK( vulkan.vkCreateDescriptorSetLayout( vulkan.device, &info, nullptr, OUT &ds1_layout )); 164 | vulkan.tempHandles.emplace_back( Device::EHandleType::DescriptorSetLayout, uint64_t(ds1_layout) ); 165 | } 166 | 167 | // allocate descriptor set 168 | { 169 | VkDescriptorSetAllocateInfo info = {}; 170 | info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 171 | info.descriptorPool = vulkan.descPool; 172 | info.descriptorSetCount = 1; 173 | info.pSetLayouts = &ds1_layout; 174 | 175 | VK_CHECK( vulkan.vkAllocateDescriptorSets( vulkan.device, &info, OUT &desc_set1 )); 176 | } 177 | 178 | // update descriptor set 179 | { 180 | VkDescriptorImageInfo desc_image = {}; 181 | desc_image.imageView = image_view; 182 | desc_image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; 183 | 184 | VkWriteDescriptorSet write = {}; 185 | write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 186 | write.dstSet = desc_set1; 187 | write.dstBinding = 0; 188 | write.descriptorCount = 1; 189 | write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 190 | write.pImageInfo = &desc_image; 191 | 192 | vulkan.vkUpdateDescriptorSets( vulkan.device, 1, &write, 0, nullptr ); 193 | } 194 | 195 | VkPipelineLayout ppln_layout; 196 | VkPipeline pipeline; 197 | CHECK_ERR( CreatePipeline( vulkan, comp_shader, {ds1_layout, ds2_layout}, OUT ppln_layout, OUT pipeline )); 198 | 199 | 200 | // build command buffer 201 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 202 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 203 | 204 | // image layout undefined -> general 205 | { 206 | VkImageMemoryBarrier barrier = {}; 207 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 208 | barrier.srcAccessMask = 0; 209 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 210 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 211 | barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; 212 | barrier.image = image; 213 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 214 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 215 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 216 | 217 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 218 | 0, nullptr, 0, nullptr, 1, &barrier ); 219 | } 220 | 221 | // setup storage buffer 222 | { 223 | const uint data[] = { ~0u, ~0u, ~0u }; // don't select anything, trace recording will be enabled by 'dbg_EnableTraceRecording' function in shader 224 | 225 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 226 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 227 | } 228 | 229 | // debug output storage read/write after write 230 | { 231 | VkBufferMemoryBarrier barrier = {}; 232 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 233 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 234 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 235 | barrier.buffer = vulkan.debugOutputBuf; 236 | barrier.offset = 0; 237 | barrier.size = VK_WHOLE_SIZE; 238 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 239 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 240 | 241 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 242 | 0, nullptr, 1, &barrier, 0, nullptr); 243 | } 244 | 245 | // dispatch 246 | { 247 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline ); 248 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, ppln_layout, 0, 1, &desc_set1, 0, nullptr ); 249 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, ppln_layout, 1, 1, &desc_set2, 0, nullptr ); 250 | 251 | vulkan.vkCmdDispatch( vulkan.cmdBuffer, width/4, height/4, 1 ); 252 | } 253 | 254 | // debug output storage read after write 255 | { 256 | VkBufferMemoryBarrier barrier = {}; 257 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 258 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 259 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 260 | barrier.buffer = vulkan.debugOutputBuf; 261 | barrier.offset = 0; 262 | barrier.size = VK_WHOLE_SIZE; 263 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 264 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 265 | 266 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 267 | 0, nullptr, 1, &barrier, 0, nullptr); 268 | } 269 | 270 | // copy shader debug output into host visible memory 271 | { 272 | VkBufferCopy region = {}; 273 | region.srcOffset = 0; 274 | region.dstOffset = 0; 275 | region.size = vulkan.debugOutputSize; 276 | 277 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 278 | } 279 | 280 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 281 | 282 | // submit commands and wait 283 | { 284 | VkSubmitInfo submit = {}; 285 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 286 | submit.commandBufferCount = 1; 287 | submit.pCommandBuffers = &vulkan.cmdBuffer; 288 | 289 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 290 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 291 | } 292 | 293 | CHECK_ERR( vulkan.TestDebugTraceOutput( {comp_shader}, "ShaderTrace_Test11.txt" )); 294 | 295 | vulkan.FreeTempHandles(); 296 | 297 | TEST_PASSED(); 298 | return true; 299 | } 300 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test13.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 17 | {-1.0f, 2.0f}, // primitive 1 - miss 18 | {-2.0f, 0.0f} // primitive 2 - must hit 19 | }; 20 | 21 | layout(location=0) out vec4 out_Position; 22 | 23 | layout(location=2) out VertOutput { 24 | vec2 out_Texcoord; 25 | vec4 out_Color; 26 | }; 27 | 28 | void dbg_EnableTraceRecording (bool b) {} 29 | 30 | void main() 31 | { 32 | dbg_EnableTraceRecording( (gl_VertexIndex & 1) == 0 ); 33 | 34 | out_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 35 | gl_Position = out_Position; 36 | out_Texcoord = g_Positions[gl_VertexIndex].xy * 0.5f + 0.5f; 37 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexIndex) / float(g_Positions.length())); 38 | })#"; 39 | 40 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex, ETraceMode::DebugTrace, 0 )); 41 | } 42 | 43 | // create fragment shader 44 | { 45 | static const char frag_shader_source[] = R"#( 46 | layout(location = 0) out vec4 out_Color; 47 | 48 | layout(location=0) in vec4 in_Position; 49 | 50 | layout(location=2) in VertOutput { 51 | vec2 in_Texcoord; 52 | vec4 in_Color; 53 | }; 54 | 55 | void dbg_EnableTraceRecording (bool b) {} 56 | 57 | float Fn1 (const int i, in float k, out int res) 58 | { 59 | float f = 0.0f; 60 | res = 11; 61 | for (int j = i; j < 10; ++j) { 62 | f += 1.2f * 63 | cos(float(j) + k); 64 | if (f > 15.7f) { 65 | res = j; 66 | return f * 10.0f; 67 | } 68 | } 69 | return fract(f + k); 70 | } 71 | 72 | void main () 73 | { 74 | dbg_EnableTraceRecording( uint(gl_FragCoord.x) == 8 && uint(gl_FragCoord.y) == 8 ); 75 | 76 | ivec2 c1; 77 | float c0 = Fn1( 3, in_Texcoord.x + in_Position.y, c1.x ); 78 | out_Color[1] = c0 + float(c1.x); 79 | return; 80 | })#"; 81 | 82 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::DebugTrace, 0 )); 83 | } 84 | return true; 85 | } 86 | 87 | /* 88 | ================================================= 89 | ShaderTrace_Test13 90 | ================================================= 91 | */ 92 | extern bool ShaderTrace_Test13 (Device& vulkan) 93 | { 94 | // create renderpass and framebuffer 95 | uint width = 16, height = 16; 96 | VkRenderPass render_pass; 97 | VkImage color_target; 98 | VkFramebuffer framebuffer; 99 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 100 | OUT render_pass, OUT color_target, OUT framebuffer )); 101 | 102 | 103 | // create pipeline 104 | VkShaderModule vert_shader, frag_shader; 105 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 106 | 107 | VkDescriptorSetLayout ds_layout; 108 | VkDescriptorSet desc_set; 109 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 110 | 111 | VkPipelineLayout ppln_layout; 112 | VkPipeline pipeline; 113 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 114 | 115 | 116 | // build command buffer 117 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 118 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 119 | 120 | // image layout undefined -> color_attachment 121 | { 122 | VkImageMemoryBarrier barrier = {}; 123 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 124 | barrier.srcAccessMask = 0; 125 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 126 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 127 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 128 | barrier.image = color_target; 129 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 130 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 131 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 132 | 133 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 134 | 0, nullptr, 0, nullptr, 1, &barrier); 135 | } 136 | 137 | // setup storage buffer 138 | { 139 | const int data[] = { -1, -1 }; // selected pixel outside of the screen 140 | 141 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 142 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 143 | } 144 | 145 | // debug output storage read/write after write 146 | { 147 | VkBufferMemoryBarrier barrier = {}; 148 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 149 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 150 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 151 | barrier.buffer = vulkan.debugOutputBuf; 152 | barrier.offset = 0; 153 | barrier.size = VK_WHOLE_SIZE; 154 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 155 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 156 | 157 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 158 | 0, nullptr, 1, &barrier, 0, nullptr); 159 | } 160 | 161 | // begin render pass 162 | { 163 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 164 | VkRenderPassBeginInfo begin_rp = {}; 165 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 166 | begin_rp.framebuffer = framebuffer; 167 | begin_rp.renderPass = render_pass; 168 | begin_rp.renderArea = { {0,0}, {width, height} }; 169 | begin_rp.clearValueCount = 1; 170 | begin_rp.pClearValues = &clear_value; 171 | 172 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 173 | } 174 | 175 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 176 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 177 | 178 | // set dynamic states 179 | { 180 | VkViewport viewport = {}; 181 | viewport.x = 0.0f; 182 | viewport.y = 0.0f; 183 | viewport.width = float(width); 184 | viewport.height = float(height); 185 | viewport.minDepth = 0.0f; 186 | viewport.maxDepth = 1.0f; 187 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 188 | 189 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 190 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 191 | } 192 | 193 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 5, 1, 0, 0 ); 194 | 195 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 196 | 197 | // debug output storage read after write 198 | { 199 | VkBufferMemoryBarrier barrier = {}; 200 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 201 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 202 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 203 | barrier.buffer = vulkan.debugOutputBuf; 204 | barrier.offset = 0; 205 | barrier.size = VK_WHOLE_SIZE; 206 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 207 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 208 | 209 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 210 | 0, nullptr, 1, &barrier, 0, nullptr); 211 | } 212 | 213 | // copy shader debug output into host visible memory 214 | { 215 | VkBufferCopy region = {}; 216 | region.srcOffset = 0; 217 | region.dstOffset = 0; 218 | region.size = VkDeviceSize(vulkan.debugOutputSize); 219 | 220 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 221 | } 222 | 223 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 224 | 225 | 226 | // submit commands and wait 227 | { 228 | VkSubmitInfo submit = {}; 229 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 230 | submit.commandBufferCount = 1; 231 | submit.pCommandBuffers = &vulkan.cmdBuffer; 232 | 233 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 234 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 235 | } 236 | 237 | CHECK_ERR( vulkan.TestDebugTraceOutput( {vert_shader, frag_shader}, "ShaderTrace_Test13.txt" )); 238 | 239 | vulkan.FreeTempHandles(); 240 | 241 | TEST_PASSED(); 242 | return true; 243 | } 244 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &compShader) 11 | { 12 | // create compute shader 13 | { 14 | static const char comp_shader_source[] = R"#( 15 | layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 16 | 17 | layout(binding = 0) writeonly uniform image2D un_OutImage; 18 | 19 | void Test1 (out vec4 color) 20 | { 21 | vec2 point = (vec3(gl_GlobalInvocationID) / vec3(gl_NumWorkGroups * gl_WorkGroupSize - 1)).xy; 22 | 23 | if ( (gl_GlobalInvocationID.x & 1) == 1 ) 24 | { 25 | color = vec4(1.0f); 26 | return; 27 | } 28 | 29 | color = point.xyyx; 30 | color.x = cos(color.y) * color.z; 31 | } 32 | 33 | void main() 34 | { 35 | vec4 color; 36 | Test1( color ); 37 | imageStore( un_OutImage, ivec2(gl_GlobalInvocationID.xy), color ); 38 | } 39 | )#"; 40 | CHECK_ERR( vulkan.Compile( OUT compShader, {comp_shader_source}, EShLangCompute, ETraceMode::DebugTrace, 1 )); 41 | } 42 | return true; 43 | } 44 | 45 | /* 46 | ================================================= 47 | CreatePipeline 48 | ================================================= 49 | */ 50 | static bool CreatePipeline (Device &vulkan, VkShaderModule compShader, vector dsLayouts, 51 | OUT VkPipelineLayout &outPipelineLayout, OUT VkPipeline &outPipeline) 52 | { 53 | // create pipeline layout 54 | { 55 | VkPipelineLayoutCreateInfo info = {}; 56 | info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 57 | info.setLayoutCount = uint(dsLayouts.size()); 58 | info.pSetLayouts = dsLayouts.data(); 59 | info.pushConstantRangeCount = 0; 60 | info.pPushConstantRanges = nullptr; 61 | 62 | VK_CHECK( vulkan.vkCreatePipelineLayout( vulkan.device, &info, nullptr, OUT &outPipelineLayout )); 63 | vulkan.tempHandles.emplace_back( Device::EHandleType::PipelineLayout, uint64_t(outPipelineLayout) ); 64 | } 65 | 66 | VkComputePipelineCreateInfo info = {}; 67 | info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; 68 | info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 69 | info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; 70 | info.stage.module = compShader; 71 | info.stage.pName = "main"; 72 | info.layout = outPipelineLayout; 73 | 74 | VK_CHECK( vulkan.vkCreateComputePipelines( vulkan.device, VK_NULL_HANDLE, 1, &info, nullptr, OUT &outPipeline )); 75 | vulkan.tempHandles.emplace_back( Device::EHandleType::Pipeline, uint64_t(outPipeline) ); 76 | 77 | return true; 78 | } 79 | 80 | /* 81 | ================================================= 82 | ShaderTrace_Test2 83 | ================================================= 84 | */ 85 | extern bool ShaderTrace_Test2 (Device& vulkan) 86 | { 87 | // create image 88 | VkImage image; 89 | VkImageView image_view; 90 | uint width = 16, height = 16; 91 | { 92 | VkImageCreateInfo info = {}; 93 | info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 94 | info.flags = 0; 95 | info.imageType = VK_IMAGE_TYPE_2D; 96 | info.format = VK_FORMAT_R8G8B8A8_UNORM; 97 | info.extent = { width, height, 1 }; 98 | info.mipLevels = 1; 99 | info.arrayLayers = 1; 100 | info.samples = VK_SAMPLE_COUNT_1_BIT; 101 | info.tiling = VK_IMAGE_TILING_OPTIMAL; 102 | info.usage = VK_IMAGE_USAGE_STORAGE_BIT; 103 | info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 104 | info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 105 | 106 | VK_CHECK( vulkan.vkCreateImage( vulkan.device, &info, nullptr, OUT &image )); 107 | vulkan.tempHandles.emplace_back( Device::EHandleType::Image, uint64_t(image) ); 108 | 109 | VkMemoryRequirements mem_req; 110 | vulkan.vkGetImageMemoryRequirements( vulkan.device, image, OUT &mem_req ); 111 | 112 | // allocate device local memory 113 | VkMemoryAllocateInfo alloc_info = {}; 114 | alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 115 | alloc_info.allocationSize = mem_req.size; 116 | CHECK_ERR( vulkan.GetMemoryTypeIndex( mem_req.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, OUT alloc_info.memoryTypeIndex )); 117 | 118 | VkDeviceMemory image_mem; 119 | VK_CHECK( vulkan.vkAllocateMemory( vulkan.device, &alloc_info, nullptr, OUT &image_mem )); 120 | vulkan.tempHandles.emplace_back( Device::EHandleType::Memory, uint64_t(image_mem) ); 121 | 122 | VK_CHECK( vulkan.vkBindImageMemory( vulkan.device, image, image_mem, 0 )); 123 | } 124 | 125 | // create image view 126 | { 127 | VkImageViewCreateInfo info = {}; 128 | info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 129 | info.flags = 0; 130 | info.image = image; 131 | info.viewType = VK_IMAGE_VIEW_TYPE_2D; 132 | info.format = VK_FORMAT_R8G8B8A8_UNORM; 133 | info.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; 134 | info.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; 135 | 136 | VK_CHECK( vulkan.vkCreateImageView( vulkan.device, &info, nullptr, OUT &image_view )); 137 | vulkan.tempHandles.emplace_back( Device::EHandleType::ImageView, uint64_t(image_view) ); 138 | } 139 | 140 | 141 | // create pipeline 142 | VkShaderModule comp_shader; 143 | CHECK_ERR( CompileShaders( vulkan, OUT comp_shader )); 144 | 145 | VkDescriptorSetLayout ds1_layout, ds2_layout; 146 | VkDescriptorSet desc_set1, desc_set2; 147 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_COMPUTE_BIT, OUT ds2_layout, OUT desc_set2 )); 148 | 149 | // create layout 150 | { 151 | VkDescriptorSetLayoutBinding binding = {}; 152 | binding.binding = 0; 153 | binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 154 | binding.descriptorCount = 1; 155 | binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 156 | 157 | VkDescriptorSetLayoutCreateInfo info = {}; 158 | info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; 159 | info.bindingCount = 1; 160 | info.pBindings = &binding; 161 | 162 | VK_CHECK( vulkan.vkCreateDescriptorSetLayout( vulkan.device, &info, nullptr, OUT &ds1_layout )); 163 | vulkan.tempHandles.emplace_back( Device::EHandleType::DescriptorSetLayout, uint64_t(ds1_layout) ); 164 | } 165 | 166 | // allocate descriptor set 167 | { 168 | VkDescriptorSetAllocateInfo info = {}; 169 | info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; 170 | info.descriptorPool = vulkan.descPool; 171 | info.descriptorSetCount = 1; 172 | info.pSetLayouts = &ds1_layout; 173 | 174 | VK_CHECK( vulkan.vkAllocateDescriptorSets( vulkan.device, &info, OUT &desc_set1 )); 175 | } 176 | 177 | // update descriptor set 178 | { 179 | VkDescriptorImageInfo desc_image = {}; 180 | desc_image.imageView = image_view; 181 | desc_image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; 182 | 183 | VkWriteDescriptorSet write = {}; 184 | write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 185 | write.dstSet = desc_set1; 186 | write.dstBinding = 0; 187 | write.descriptorCount = 1; 188 | write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 189 | write.pImageInfo = &desc_image; 190 | 191 | vulkan.vkUpdateDescriptorSets( vulkan.device, 1, &write, 0, nullptr ); 192 | } 193 | 194 | VkPipelineLayout ppln_layout; 195 | VkPipeline pipeline; 196 | CHECK_ERR( CreatePipeline( vulkan, comp_shader, {ds1_layout, ds2_layout}, OUT ppln_layout, OUT pipeline )); 197 | 198 | 199 | // build command buffer 200 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 201 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 202 | 203 | // image layout undefined -> general 204 | { 205 | VkImageMemoryBarrier barrier = {}; 206 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 207 | barrier.srcAccessMask = 0; 208 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 209 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 210 | barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; 211 | barrier.image = image; 212 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 213 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 214 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 215 | 216 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 217 | 0, nullptr, 0, nullptr, 1, &barrier); 218 | } 219 | 220 | // setup storage buffer 221 | { 222 | const uint data[] = { 223 | width/2, height/2, 0, // selected invocation 224 | }; 225 | 226 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 227 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 228 | } 229 | 230 | // debug output storage read/write after write 231 | { 232 | VkBufferMemoryBarrier barrier = {}; 233 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 234 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 235 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 236 | barrier.buffer = vulkan.debugOutputBuf; 237 | barrier.offset = 0; 238 | barrier.size = VK_WHOLE_SIZE; 239 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 240 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 241 | 242 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 243 | 0, nullptr, 1, &barrier, 0, nullptr); 244 | } 245 | 246 | // dispatch 247 | { 248 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline ); 249 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, ppln_layout, 0, 1, &desc_set1, 0, nullptr ); 250 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, ppln_layout, 1, 1, &desc_set2, 0, nullptr ); 251 | 252 | vulkan.vkCmdDispatch( vulkan.cmdBuffer, width, height, 1 ); 253 | } 254 | 255 | // debug output storage read after write 256 | { 257 | VkBufferMemoryBarrier barrier = {}; 258 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 259 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 260 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 261 | barrier.buffer = vulkan.debugOutputBuf; 262 | barrier.offset = 0; 263 | barrier.size = VK_WHOLE_SIZE; 264 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 265 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 266 | 267 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 268 | 0, nullptr, 1, &barrier, 0, nullptr); 269 | } 270 | 271 | // copy shader debug output into host visible memory 272 | { 273 | VkBufferCopy region = {}; 274 | region.srcOffset = 0; 275 | region.dstOffset = 0; 276 | region.size = vulkan.debugOutputSize; 277 | 278 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 279 | } 280 | 281 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 282 | 283 | // submit commands and wait 284 | { 285 | VkSubmitInfo submit = {}; 286 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 287 | submit.commandBufferCount = 1; 288 | submit.pCommandBuffers = &vulkan.cmdBuffer; 289 | 290 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 291 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 292 | } 293 | 294 | CHECK_ERR( vulkan.TestDebugTraceOutput( {comp_shader}, "ShaderTrace_Test2.txt" )); 295 | 296 | vulkan.FreeTempHandles(); 297 | 298 | TEST_PASSED(); 299 | return true; 300 | } 301 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test3.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 17 | }; 18 | 19 | void main() 20 | { 21 | gl_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.02f, 1.0f ); 22 | })#"; 23 | 24 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 25 | } 26 | 27 | // create fragment shader 28 | { 29 | static const char frag_shader_source[] = R"#( 30 | layout(location = 0) out vec4 out_Color; 31 | 32 | void main () 33 | { 34 | mat4x4 m1; 35 | m1[0] = vec4(1.0f); m1[1] = vec4(2.0f); m1[2] = vec4(3.0f); m1[3] = vec4(4.0f); 36 | 37 | mat2x3 m2; 38 | m2[0] = vec3(11.1f); m2[1] = vec3(12.2f); 39 | 40 | mat4x4 m3; 41 | m3[0] = vec4(6.0f); m3[1] = vec4(7.0f); m3[2] = vec4(8.0f); m3[3] = vec4(9.0f); 42 | 43 | m3[0][1] = 44.0f; 44 | 45 | mat4x4 m4 = m1 * m3; 46 | 47 | out_Color = (m4 * vec4(8.0f)) + vec4(m2 * vec2(9.0f), 1.0f); 48 | })#"; 49 | 50 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::DebugTrace, 0 )); 51 | } 52 | return true; 53 | } 54 | 55 | /* 56 | ================================================= 57 | ShaderTrace_Test3 58 | ================================================= 59 | */ 60 | extern bool ShaderTrace_Test3 (Device& vulkan) 61 | { 62 | // create renderpass and framebuffer 63 | uint width = 16, height = 16; 64 | VkRenderPass render_pass; 65 | VkImage color_target; 66 | VkFramebuffer framebuffer; 67 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 68 | OUT render_pass, OUT color_target, OUT framebuffer )); 69 | 70 | 71 | // create pipeline 72 | VkShaderModule vert_shader, frag_shader; 73 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 74 | 75 | VkDescriptorSetLayout ds_layout; 76 | VkDescriptorSet desc_set; 77 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 78 | 79 | VkPipelineLayout ppln_layout; 80 | VkPipeline pipeline; 81 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 82 | 83 | 84 | // build command buffer 85 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 86 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 87 | 88 | // image layout undefined -> color_attachment 89 | { 90 | VkImageMemoryBarrier barrier = {}; 91 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 92 | barrier.srcAccessMask = 0; 93 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 94 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 95 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 96 | barrier.image = color_target; 97 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 98 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 99 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 100 | 101 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 102 | 0, nullptr, 0, nullptr, 1, &barrier); 103 | } 104 | 105 | // setup storage buffer 106 | { 107 | const uint data[] = { width/2, height/2 }; // selected pixel 108 | 109 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 110 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 111 | } 112 | 113 | // debug output storage read/write after write 114 | { 115 | VkBufferMemoryBarrier barrier = {}; 116 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 117 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 118 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 119 | barrier.buffer = vulkan.debugOutputBuf; 120 | barrier.offset = 0; 121 | barrier.size = VK_WHOLE_SIZE; 122 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 124 | 125 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 126 | 0, nullptr, 1, &barrier, 0, nullptr); 127 | } 128 | 129 | // begin render pass 130 | { 131 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 132 | VkRenderPassBeginInfo begin_rp = {}; 133 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 134 | begin_rp.framebuffer = framebuffer; 135 | begin_rp.renderPass = render_pass; 136 | begin_rp.renderArea = { {0,0}, {width, height} }; 137 | begin_rp.clearValueCount = 1; 138 | begin_rp.pClearValues = &clear_value; 139 | 140 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 141 | } 142 | 143 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 144 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 145 | 146 | // set dynamic states 147 | { 148 | VkViewport viewport = {}; 149 | viewport.x = 0.0f; 150 | viewport.y = 0.0f; 151 | viewport.width = float(width); 152 | viewport.height = float(height); 153 | viewport.minDepth = 0.0f; 154 | viewport.maxDepth = 1.0f; 155 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 156 | 157 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 158 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 159 | } 160 | 161 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 3, 1, 0, 0 ); 162 | 163 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 164 | 165 | // debug output storage read after write 166 | { 167 | VkBufferMemoryBarrier barrier = {}; 168 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 169 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 170 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 171 | barrier.buffer = vulkan.debugOutputBuf; 172 | barrier.offset = 0; 173 | barrier.size = VK_WHOLE_SIZE; 174 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 175 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 176 | 177 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 178 | 0, nullptr, 1, &barrier, 0, nullptr); 179 | } 180 | 181 | // copy shader debug output into host visible memory 182 | { 183 | VkBufferCopy region = {}; 184 | region.srcOffset = 0; 185 | region.dstOffset = 0; 186 | region.size = VkDeviceSize(vulkan.debugOutputSize); 187 | 188 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 189 | } 190 | 191 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 192 | 193 | 194 | // submit commands and wait 195 | { 196 | VkSubmitInfo submit = {}; 197 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 198 | submit.commandBufferCount = 1; 199 | submit.pCommandBuffers = &vulkan.cmdBuffer; 200 | 201 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 202 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 203 | } 204 | 205 | CHECK_ERR( vulkan.TestDebugTraceOutput( {frag_shader}, "ShaderTrace_Test3.txt" )); 206 | 207 | vulkan.FreeTempHandles(); 208 | 209 | TEST_PASSED(); 210 | return true; 211 | } 212 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test4.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 - must hit 17 | }; 18 | 19 | void main() 20 | { 21 | gl_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.02f, 1.0f ); 22 | })#"; 23 | 24 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 25 | } 26 | 27 | // create fragment shader 28 | { 29 | static const char frag_shader_source[] = R"#( 30 | #extension GL_ARB_gpu_shader_int64 : require 31 | 32 | layout(location = 0) out vec4 out_Color; 33 | 34 | void main () 35 | { 36 | uint64_t i = 0xFFFFFFFF00000000ul; 37 | dvec2 d = dvec2(1.234e+50LF, 3.875732LF); 38 | 39 | i |= 0xFFFFFFFFul; 40 | d *= 2.0; 41 | 42 | out_Color[0] = float(i); 43 | out_Color[1] = float(d.x); 44 | out_Color[2] = float(d.y); 45 | })#"; 46 | 47 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment, ETraceMode::DebugTrace, 0 )); 48 | } 49 | return true; 50 | } 51 | 52 | /* 53 | ================================================= 54 | ShaderTrace_Test4 55 | ================================================= 56 | */ 57 | extern bool ShaderTrace_Test4 (Device& vulkan) 58 | { 59 | if ( not (vulkan.deviceFeat.shaderFloat64 and vulkan.deviceFeat.shaderInt64) ) 60 | return true; 61 | 62 | // create renderpass and framebuffer 63 | uint width = 16, height = 16; 64 | VkRenderPass render_pass; 65 | VkImage color_target; 66 | VkFramebuffer framebuffer; 67 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 68 | OUT render_pass, OUT color_target, OUT framebuffer )); 69 | 70 | 71 | // create pipeline 72 | VkShaderModule vert_shader, frag_shader; 73 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 74 | 75 | VkDescriptorSetLayout ds_layout; 76 | VkDescriptorSet desc_set; 77 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_FRAGMENT_BIT, OUT ds_layout, OUT desc_set )); 78 | 79 | VkPipelineLayout ppln_layout; 80 | VkPipeline pipeline; 81 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 82 | 83 | 84 | // build command buffer 85 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 86 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 87 | 88 | // image layout undefined -> color_attachment 89 | { 90 | VkImageMemoryBarrier barrier = {}; 91 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 92 | barrier.srcAccessMask = 0; 93 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 94 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 95 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 96 | barrier.image = color_target; 97 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 98 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 99 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 100 | 101 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 102 | 0, nullptr, 0, nullptr, 1, &barrier); 103 | } 104 | 105 | // setup storage buffer 106 | { 107 | const uint data[] = { width/2, height/2 }; // selected pixel 108 | 109 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, sizeof(data), VK_WHOLE_SIZE, 0 ); 110 | vulkan.vkCmdUpdateBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, sizeof(data), data ); 111 | } 112 | 113 | // debug output storage read/write after write 114 | { 115 | VkBufferMemoryBarrier barrier = {}; 116 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 117 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 118 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 119 | barrier.buffer = vulkan.debugOutputBuf; 120 | barrier.offset = 0; 121 | barrier.size = VK_WHOLE_SIZE; 122 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 124 | 125 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 126 | 0, nullptr, 1, &barrier, 0, nullptr); 127 | } 128 | 129 | // begin render pass 130 | { 131 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 132 | VkRenderPassBeginInfo begin_rp = {}; 133 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 134 | begin_rp.framebuffer = framebuffer; 135 | begin_rp.renderPass = render_pass; 136 | begin_rp.renderArea = { {0,0}, {width, height} }; 137 | begin_rp.clearValueCount = 1; 138 | begin_rp.pClearValues = &clear_value; 139 | 140 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 141 | } 142 | 143 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 144 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 145 | 146 | // set dynamic states 147 | { 148 | VkViewport viewport = {}; 149 | viewport.x = 0.0f; 150 | viewport.y = 0.0f; 151 | viewport.width = float(width); 152 | viewport.height = float(height); 153 | viewport.minDepth = 0.0f; 154 | viewport.maxDepth = 1.0f; 155 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 156 | 157 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 158 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 159 | } 160 | 161 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 3, 1, 0, 0 ); 162 | 163 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 164 | 165 | // debug output storage read after write 166 | { 167 | VkBufferMemoryBarrier barrier = {}; 168 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 169 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 170 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 171 | barrier.buffer = vulkan.debugOutputBuf; 172 | barrier.offset = 0; 173 | barrier.size = VK_WHOLE_SIZE; 174 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 175 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 176 | 177 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 178 | 0, nullptr, 1, &barrier, 0, nullptr); 179 | } 180 | 181 | // copy shader debug output into host visible memory 182 | { 183 | VkBufferCopy region = {}; 184 | region.srcOffset = 0; 185 | region.dstOffset = 0; 186 | region.size = vulkan.debugOutputSize; 187 | 188 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 189 | } 190 | 191 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 192 | 193 | 194 | // submit commands and wait 195 | { 196 | VkSubmitInfo submit = {}; 197 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 198 | submit.commandBufferCount = 1; 199 | submit.pCommandBuffers = &vulkan.cmdBuffer; 200 | 201 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 202 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 203 | } 204 | 205 | CHECK_ERR( vulkan.TestDebugTraceOutput( {frag_shader}, "ShaderTrace_Test4.txt" )); 206 | 207 | vulkan.FreeTempHandles(); 208 | 209 | TEST_PASSED(); 210 | return true; 211 | } 212 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test5.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f}, // primitive 0 17 | {-1.0f, 2.0f}, // primitive 1 18 | {-2.0f, 0.0f} // primitive 2 19 | }; 20 | 21 | layout(location=0) out vec4 out_Position; 22 | 23 | layout(location=2) out VertOutput { 24 | vec2 out_Texcoord; 25 | vec4 out_Color; 26 | }; 27 | 28 | void dbg_EnableTraceRecording (bool b) {} 29 | 30 | void main() 31 | { 32 | dbg_EnableTraceRecording( gl_VertexIndex == 4 ); 33 | 34 | out_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 35 | gl_Position = out_Position; 36 | out_Texcoord = g_Positions[gl_VertexIndex].xy * 0.5f + 0.5f; 37 | out_Color = mix(vec4(1.0, 0.3, 0.0, 0.8), vec4(0.6, 0.9, 0.1, 1.0), float(gl_VertexIndex) / float(g_Positions.length())); 38 | })#"; 39 | 40 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex, ETraceMode::DebugTrace, 0 )); 41 | } 42 | 43 | // create fragment shader 44 | { 45 | static const char frag_shader_source[] = R"#( 46 | layout(location = 0) out vec4 out_Color; 47 | 48 | void main () 49 | { 50 | out_Color = gl_FragCoord; 51 | })#"; 52 | 53 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment )); 54 | } 55 | return true; 56 | } 57 | 58 | /* 59 | ================================================= 60 | ShaderTrace_Test5 61 | ================================================= 62 | */ 63 | extern bool ShaderTrace_Test5 (Device& vulkan) 64 | { 65 | // create renderpass and framebuffer 66 | uint width = 16, height = 16; 67 | VkRenderPass render_pass; 68 | VkImage color_target; 69 | VkFramebuffer framebuffer; 70 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 71 | OUT render_pass, OUT color_target, OUT framebuffer )); 72 | 73 | 74 | // create pipeline 75 | VkShaderModule vert_shader, frag_shader; 76 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT frag_shader )); 77 | 78 | VkDescriptorSetLayout ds_layout; 79 | VkDescriptorSet desc_set; 80 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_VERTEX_BIT, OUT ds_layout, OUT desc_set )); 81 | 82 | VkPipelineLayout ppln_layout; 83 | VkPipeline pipeline; 84 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar1( vert_shader, frag_shader, ds_layout, render_pass, OUT ppln_layout, OUT pipeline )); 85 | 86 | 87 | // build command buffer 88 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 89 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 90 | 91 | // image layout undefined -> color_attachment 92 | { 93 | VkImageMemoryBarrier barrier = {}; 94 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 95 | barrier.srcAccessMask = 0; 96 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 97 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 98 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 99 | barrier.image = color_target; 100 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 101 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 102 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 103 | 104 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 105 | 0, nullptr, 0, nullptr, 1, &barrier); 106 | } 107 | 108 | // setup storage buffer 109 | { 110 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, VK_WHOLE_SIZE, 0 ); 111 | } 112 | 113 | // debug output storage read/write after write 114 | { 115 | VkBufferMemoryBarrier barrier = {}; 116 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 117 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 118 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 119 | barrier.buffer = vulkan.debugOutputBuf; 120 | barrier.offset = 0; 121 | barrier.size = VK_WHOLE_SIZE; 122 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 123 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 124 | 125 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 126 | 0, nullptr, 1, &barrier, 0, nullptr); 127 | } 128 | 129 | // begin render pass 130 | { 131 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 132 | VkRenderPassBeginInfo begin_rp = {}; 133 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 134 | begin_rp.framebuffer = framebuffer; 135 | begin_rp.renderPass = render_pass; 136 | begin_rp.renderArea = { {0,0}, {width, height} }; 137 | begin_rp.clearValueCount = 1; 138 | begin_rp.pClearValues = &clear_value; 139 | 140 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 141 | } 142 | 143 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 144 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 145 | 146 | // set dynamic states 147 | { 148 | VkViewport viewport = {}; 149 | viewport.x = 0.0f; 150 | viewport.y = 0.0f; 151 | viewport.width = float(width); 152 | viewport.height = float(height); 153 | viewport.minDepth = 0.0f; 154 | viewport.maxDepth = 1.0f; 155 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 156 | 157 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 158 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 159 | } 160 | 161 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 5, 1, 0, 0 ); 162 | 163 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 164 | 165 | // debug output storage read after write 166 | { 167 | VkBufferMemoryBarrier barrier = {}; 168 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 169 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 170 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 171 | barrier.buffer = vulkan.debugOutputBuf; 172 | barrier.offset = 0; 173 | barrier.size = VK_WHOLE_SIZE; 174 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 175 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 176 | 177 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 178 | 0, nullptr, 1, &barrier, 0, nullptr); 179 | } 180 | 181 | // copy shader debug output into host visible memory 182 | { 183 | VkBufferCopy region = {}; 184 | region.srcOffset = 0; 185 | region.dstOffset = 0; 186 | region.size = vulkan.debugOutputSize; 187 | 188 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 189 | } 190 | 191 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 192 | 193 | 194 | // submit commands and wait 195 | { 196 | VkSubmitInfo submit = {}; 197 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 198 | submit.commandBufferCount = 1; 199 | submit.pCommandBuffers = &vulkan.cmdBuffer; 200 | 201 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 202 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 203 | } 204 | 205 | CHECK_ERR( vulkan.TestDebugTraceOutput( {vert_shader}, "ShaderTrace_Test5.txt" )); 206 | 207 | vulkan.FreeTempHandles(); 208 | 209 | TEST_PASSED(); 210 | return true; 211 | } 212 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test7.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, OUT VkShaderModule &tessContShader, OUT VkShaderModule &tessEvalShader, OUT VkShaderModule &fragShader) 11 | { 12 | // create vertex shader 13 | { 14 | static const char vert_shader_source[] = R"#( 15 | const vec2 g_Positions[] = { 16 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f} 17 | }; 18 | 19 | layout(location=0) out float out_Level; 20 | 21 | void main() 22 | { 23 | gl_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 24 | out_Level = float(gl_VertexIndex) * 2.5f; 25 | })#"; 26 | 27 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 28 | } 29 | 30 | // create tessellation control shader 31 | { 32 | static const char cont_shader_source[] = R"#( 33 | layout(vertices = 3) out; 34 | 35 | layout(location=0) in float in_Level[]; 36 | layout(location=0) out float out_Level[]; 37 | 38 | void dbg_EnableTraceRecording (bool b) {} 39 | 40 | void main () 41 | { 42 | # define I gl_InvocationID 43 | 44 | dbg_EnableTraceRecording( I == 2 && gl_PrimitiveID == 0 ); 45 | 46 | if ( I == 0 ) { 47 | gl_TessLevelInner[0] = max( max(in_Level[0], in_Level[1]), in_Level[2] ); 48 | gl_TessLevelOuter[0] = max( in_Level[1], in_Level[2] ); 49 | gl_TessLevelOuter[1] = max( in_Level[0], in_Level[1] ); 50 | gl_TessLevelOuter[2] = max( in_Level[0], in_Level[2] ); 51 | } 52 | gl_out[I].gl_Position = gl_in[I].gl_Position; 53 | out_Level[I] = in_Level[I]; 54 | })#"; 55 | 56 | CHECK_ERR( vulkan.Compile( OUT tessContShader, {cont_shader_source}, EShLangTessControl, ETraceMode::DebugTrace, 0 )); 57 | } 58 | 59 | // create fragment shader 60 | { 61 | static const char eval_shader_source[] = R"#( 62 | layout(triangles, equal_spacing, ccw) in; 63 | 64 | layout(location=0) in float in_Level[]; 65 | layout(location=0) out vec4 out_Color; 66 | 67 | #define Interpolate( _arr, _field ) \ 68 | ( gl_TessCoord.x * _arr[0] _field + \ 69 | gl_TessCoord.y * _arr[1] _field + \ 70 | gl_TessCoord.z * _arr[2] _field ) 71 | 72 | void main () 73 | { 74 | vec4 pos = Interpolate( gl_in, .gl_Position ); 75 | gl_Position = pos; 76 | out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 77 | })#"; 78 | 79 | CHECK_ERR( vulkan.Compile( OUT tessEvalShader, {eval_shader_source}, EShLangTessEvaluation )); 80 | } 81 | 82 | // create fragment shader 83 | { 84 | static const char frag_shader_source[] = R"#( 85 | layout(location = 0) in vec4 in_Color; 86 | layout(location = 0) out vec4 out_Color; 87 | 88 | void main () 89 | { 90 | out_Color = in_Color; 91 | })#"; 92 | 93 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment )); 94 | } 95 | return true; 96 | } 97 | 98 | /* 99 | ================================================= 100 | ShaderTrace_Test7 101 | ================================================= 102 | */ 103 | extern bool ShaderTrace_Test7 (Device& vulkan) 104 | { 105 | // create renderpass and framebuffer 106 | uint width = 16, height = 16; 107 | VkRenderPass render_pass; 108 | VkImage color_target; 109 | VkFramebuffer framebuffer; 110 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 111 | OUT render_pass, OUT color_target, OUT framebuffer )); 112 | 113 | 114 | // create pipeline 115 | VkShaderModule vert_shader, cont_shader, eval_shader, frag_shader; 116 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT cont_shader, OUT eval_shader, OUT frag_shader )); 117 | 118 | VkDescriptorSetLayout ds_layout; 119 | VkDescriptorSet desc_set; 120 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, OUT ds_layout, OUT desc_set )); 121 | 122 | VkPipelineLayout ppln_layout; 123 | VkPipeline pipeline; 124 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar2( vert_shader, cont_shader, eval_shader, frag_shader, ds_layout, render_pass, 3, OUT ppln_layout, OUT pipeline )); 125 | 126 | 127 | // build command buffer 128 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 129 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 130 | 131 | // image layout undefined -> color_attachment 132 | { 133 | VkImageMemoryBarrier barrier = {}; 134 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 135 | barrier.srcAccessMask = 0; 136 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 137 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 138 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 139 | barrier.image = color_target; 140 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 141 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 142 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 143 | 144 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 145 | 0, nullptr, 0, nullptr, 1, &barrier); 146 | } 147 | 148 | // setup storage buffer 149 | { 150 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, VK_WHOLE_SIZE, 0 ); 151 | } 152 | 153 | // debug output storage read/write after write 154 | { 155 | VkBufferMemoryBarrier barrier = {}; 156 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 157 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 158 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 159 | barrier.buffer = vulkan.debugOutputBuf; 160 | barrier.offset = 0; 161 | barrier.size = VK_WHOLE_SIZE; 162 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 163 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 164 | 165 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 0, 166 | 0, nullptr, 1, &barrier, 0, nullptr); 167 | } 168 | 169 | // begin render pass 170 | { 171 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 172 | VkRenderPassBeginInfo begin_rp = {}; 173 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 174 | begin_rp.framebuffer = framebuffer; 175 | begin_rp.renderPass = render_pass; 176 | begin_rp.renderArea = { {0,0}, {width, height} }; 177 | begin_rp.clearValueCount = 1; 178 | begin_rp.pClearValues = &clear_value; 179 | 180 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 181 | } 182 | 183 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 184 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 185 | 186 | // set dynamic states 187 | { 188 | VkViewport viewport = {}; 189 | viewport.x = 0.0f; 190 | viewport.y = 0.0f; 191 | viewport.width = float(width); 192 | viewport.height = float(height); 193 | viewport.minDepth = 0.0f; 194 | viewport.maxDepth = 1.0f; 195 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 196 | 197 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 198 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 199 | } 200 | 201 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 3, 1, 0, 0 ); 202 | 203 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 204 | 205 | // debug output storage read after write 206 | { 207 | VkBufferMemoryBarrier barrier = {}; 208 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 209 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 210 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 211 | barrier.buffer = vulkan.debugOutputBuf; 212 | barrier.offset = 0; 213 | barrier.size = VK_WHOLE_SIZE; 214 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 215 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 216 | 217 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 218 | 0, nullptr, 1, &barrier, 0, nullptr); 219 | } 220 | 221 | // copy shader debug output into host visible memory 222 | { 223 | VkBufferCopy region = {}; 224 | region.srcOffset = 0; 225 | region.dstOffset = 0; 226 | region.size = vulkan.debugOutputSize; 227 | 228 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 229 | } 230 | 231 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 232 | 233 | 234 | // submit commands and wait 235 | { 236 | VkSubmitInfo submit = {}; 237 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 238 | submit.commandBufferCount = 1; 239 | submit.pCommandBuffers = &vulkan.cmdBuffer; 240 | 241 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 242 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 243 | } 244 | 245 | CHECK_ERR( vulkan.TestDebugTraceOutput( {cont_shader}, "ShaderTrace_Test7.txt" )); 246 | 247 | vulkan.FreeTempHandles(); 248 | 249 | TEST_PASSED(); 250 | return true; 251 | } 252 | -------------------------------------------------------------------------------- /tests/vulkan/ShaderTrace_Test8.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | 5 | /* 6 | ================================================= 7 | CompileShaders 8 | ================================================= 9 | */ 10 | static bool CompileShaders (Device &vulkan, OUT VkShaderModule &vertShader, 11 | OUT VkShaderModule &tessContShader, OUT VkShaderModule &tessEvalShader, OUT VkShaderModule &fragShader) 12 | { 13 | // create vertex shader 14 | { 15 | static const char vert_shader_source[] = R"#( 16 | const vec2 g_Positions[] = { 17 | {-1.0f, -1.0f}, {-1.0f, 2.0f}, {2.0f, -1.0f} 18 | }; 19 | 20 | layout(location=0) out float out_Level; 21 | 22 | void main() 23 | { 24 | gl_Position = vec4( g_Positions[gl_VertexIndex], float(gl_VertexIndex) * 0.01f, 1.0f ); 25 | out_Level = float(gl_VertexIndex) * 1.5f; 26 | })#"; 27 | 28 | CHECK_ERR( vulkan.Compile( OUT vertShader, {vert_shader_source}, EShLangVertex )); 29 | } 30 | 31 | // create tessellation control shader 32 | { 33 | static const char cont_shader_source[] = R"#( 34 | layout(vertices = 3) out; 35 | 36 | layout(location=0) in float in_Level[]; 37 | layout(location=0) out float out_Level[]; 38 | 39 | void main () 40 | { 41 | # define I gl_InvocationID 42 | 43 | if ( I == 0 ) { 44 | gl_TessLevelInner[0] = max( max(in_Level[0], in_Level[1]), in_Level[2] ); 45 | gl_TessLevelOuter[0] = 1.1f; 46 | gl_TessLevelOuter[1] = 1.2f; 47 | gl_TessLevelOuter[2] = 1.3f; 48 | } 49 | gl_out[I].gl_Position = gl_in[I].gl_Position; 50 | out_Level[I] = in_Level[I]; 51 | })#"; 52 | 53 | CHECK_ERR( vulkan.Compile( OUT tessContShader, {cont_shader_source}, EShLangTessControl )); 54 | } 55 | 56 | // create tessellation evaluation shader 57 | { 58 | static const char eval_shader_source[] = R"#( 59 | layout(triangles, equal_spacing, ccw) in; 60 | 61 | layout(location=0) in float in_Level[]; 62 | layout(location=0) out vec4 out_Color; 63 | 64 | #define Interpolate( _arr, _field ) \ 65 | ( gl_TessCoord.x * _arr[0] _field + \ 66 | gl_TessCoord.y * _arr[1] _field + \ 67 | gl_TessCoord.z * _arr[2] _field ) 68 | 69 | void dbg_EnableTraceRecording (bool b) {} 70 | 71 | void main () 72 | { 73 | dbg_EnableTraceRecording( gl_PrimitiveID == 0 ); 74 | 75 | vec4 pos = Interpolate( gl_in, .gl_Position ); 76 | gl_Position = pos; 77 | out_Color = vec4( in_Level[0], in_Level[1], in_Level[2], 1.0f ); 78 | })#"; 79 | 80 | CHECK_ERR( vulkan.Compile( OUT tessEvalShader, {eval_shader_source}, EShLangTessEvaluation, ETraceMode::DebugTrace, 0 )); 81 | } 82 | 83 | // create fragment shader 84 | { 85 | static const char frag_shader_source[] = R"#( 86 | layout(location = 0) in vec4 in_Color; 87 | layout(location = 0) out vec4 out_Color; 88 | 89 | void main () 90 | { 91 | out_Color = in_Color; 92 | })#"; 93 | 94 | CHECK_ERR( vulkan.Compile( OUT fragShader, {frag_shader_source}, EShLangFragment )); 95 | } 96 | return true; 97 | } 98 | 99 | /* 100 | ================================================= 101 | ShaderTrace_Test8 102 | ================================================= 103 | */ 104 | extern bool ShaderTrace_Test8 (Device& vulkan) 105 | { 106 | // create renderpass and framebuffer 107 | uint width = 16, height = 16; 108 | VkRenderPass render_pass; 109 | VkImage color_target; 110 | VkFramebuffer framebuffer; 111 | CHECK_ERR( vulkan.CreateRenderTarget( VK_FORMAT_R8G8B8A8_UNORM, width, height, 0, 112 | OUT render_pass, OUT color_target, OUT framebuffer )); 113 | 114 | 115 | // create pipeline 116 | VkShaderModule vert_shader, cont_shader, eval_shader, frag_shader; 117 | CHECK_ERR( CompileShaders( vulkan, OUT vert_shader, OUT cont_shader, OUT eval_shader, OUT frag_shader )); 118 | 119 | VkDescriptorSetLayout ds_layout; 120 | VkDescriptorSet desc_set; 121 | CHECK_ERR( vulkan.CreateDebugDescriptorSet( VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, OUT ds_layout, OUT desc_set )); 122 | 123 | VkPipelineLayout ppln_layout; 124 | VkPipeline pipeline; 125 | CHECK_ERR( vulkan.CreateGraphicsPipelineVar2( vert_shader, cont_shader, eval_shader, frag_shader, ds_layout, render_pass, 3, OUT ppln_layout, OUT pipeline )); 126 | 127 | 128 | // build command buffer 129 | VkCommandBufferBeginInfo begin = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, nullptr }; 130 | VK_CHECK( vulkan.vkBeginCommandBuffer( vulkan.cmdBuffer, &begin )); 131 | 132 | // image layout undefined -> color_attachment 133 | { 134 | VkImageMemoryBarrier barrier = {}; 135 | barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 136 | barrier.srcAccessMask = 0; 137 | barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 138 | barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 139 | barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 140 | barrier.image = color_target; 141 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 142 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 143 | barrier.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 144 | 145 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 146 | 0, nullptr, 0, nullptr, 1, &barrier); 147 | } 148 | 149 | // setup storage buffer 150 | { 151 | vulkan.vkCmdFillBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, 0, VK_WHOLE_SIZE, 0 ); 152 | } 153 | 154 | // debug output storage read/write after write 155 | { 156 | VkBufferMemoryBarrier barrier = {}; 157 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 158 | barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 159 | barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 160 | barrier.buffer = vulkan.debugOutputBuf; 161 | barrier.offset = 0; 162 | barrier.size = VK_WHOLE_SIZE; 163 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 164 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 165 | 166 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 0, 167 | 0, nullptr, 1, &barrier, 0, nullptr); 168 | } 169 | 170 | // begin render pass 171 | { 172 | VkClearValue clear_value = {{{ 0.0f, 0.0f, 0.0f, 1.0f }}}; 173 | VkRenderPassBeginInfo begin_rp = {}; 174 | begin_rp.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 175 | begin_rp.framebuffer = framebuffer; 176 | begin_rp.renderPass = render_pass; 177 | begin_rp.renderArea = { {0,0}, {width, height} }; 178 | begin_rp.clearValueCount = 1; 179 | begin_rp.pClearValues = &clear_value; 180 | 181 | vulkan.vkCmdBeginRenderPass( vulkan.cmdBuffer, &begin_rp, VK_SUBPASS_CONTENTS_INLINE ); 182 | } 183 | 184 | vulkan.vkCmdBindPipeline( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline ); 185 | vulkan.vkCmdBindDescriptorSets( vulkan.cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ppln_layout, 0, 1, &desc_set, 0, nullptr ); 186 | 187 | // set dynamic states 188 | { 189 | VkViewport viewport = {}; 190 | viewport.x = 0.0f; 191 | viewport.y = 0.0f; 192 | viewport.width = float(width); 193 | viewport.height = float(height); 194 | viewport.minDepth = 0.0f; 195 | viewport.maxDepth = 1.0f; 196 | vulkan.vkCmdSetViewport( vulkan.cmdBuffer, 0, 1, &viewport ); 197 | 198 | VkRect2D scissor_rect = { {0,0}, {width, height} }; 199 | vulkan.vkCmdSetScissor( vulkan.cmdBuffer, 0, 1, &scissor_rect ); 200 | } 201 | 202 | vulkan.vkCmdDraw( vulkan.cmdBuffer, 3, 1, 0, 0 ); 203 | 204 | vulkan.vkCmdEndRenderPass( vulkan.cmdBuffer ); 205 | 206 | // debug output storage read after write 207 | { 208 | VkBufferMemoryBarrier barrier = {}; 209 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 210 | barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; 211 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 212 | barrier.buffer = vulkan.debugOutputBuf; 213 | barrier.offset = 0; 214 | barrier.size = VK_WHOLE_SIZE; 215 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 216 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 217 | 218 | vulkan.vkCmdPipelineBarrier( vulkan.cmdBuffer, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 219 | 0, nullptr, 1, &barrier, 0, nullptr); 220 | } 221 | 222 | // copy shader debug output into host visible memory 223 | { 224 | VkBufferCopy region = {}; 225 | region.srcOffset = 0; 226 | region.dstOffset = 0; 227 | region.size = vulkan.debugOutputSize; 228 | 229 | vulkan.vkCmdCopyBuffer( vulkan.cmdBuffer, vulkan.debugOutputBuf, vulkan.readBackBuf, 1, ®ion ); 230 | } 231 | 232 | VK_CHECK( vulkan.vkEndCommandBuffer( vulkan.cmdBuffer )); 233 | 234 | 235 | // submit commands and wait 236 | { 237 | VkSubmitInfo submit = {}; 238 | submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 239 | submit.commandBufferCount = 1; 240 | submit.pCommandBuffers = &vulkan.cmdBuffer; 241 | 242 | VK_CHECK( vulkan.vkQueueSubmit( vulkan.queue, 1, &submit, VK_NULL_HANDLE )); 243 | VK_CHECK( vulkan.vkQueueWaitIdle( vulkan.queue )); 244 | } 245 | 246 | CHECK_ERR( vulkan.TestDebugTraceOutput( {eval_shader}, "ShaderTrace_Test8.txt" )); 247 | 248 | vulkan.FreeTempHandles(); 249 | 250 | TEST_PASSED(); 251 | return true; 252 | } 253 | -------------------------------------------------------------------------------- /tests/vulkan/VulkanLoader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "VulkanLoader.h" 4 | #include 5 | 6 | #ifdef WIN32 7 | 8 | # include 9 | 10 | using SharedLib_t = HMODULE; 11 | 12 | #else 13 | # include 14 | # include 15 | 16 | using SharedLib_t = void*; 17 | #endif 18 | 19 | #define VK_LOG( _msg_ ) std::cout << _msg_ << std::endl 20 | 21 | #define VKLOADER_STAGE_FNPOINTER 22 | # include "fn_vulkan_lib.h" 23 | # include "fn_vulkan_inst.h" 24 | #undef VKLOADER_STAGE_FNPOINTER 25 | 26 | #define VKLOADER_STAGE_DUMMYFN 27 | # include "fn_vulkan_lib.h" 28 | # include "fn_vulkan_inst.h" 29 | # include "fn_vulkan_dev.h" 30 | #undef VKLOADER_STAGE_DUMMYFN 31 | 32 | /* 33 | ================================================= 34 | VulkanLib 35 | ================================================= 36 | */ 37 | namespace { 38 | struct VulkanLib 39 | { 40 | SharedLib_t module = nullptr; 41 | VkInstance instance = VK_NULL_HANDLE; 42 | int refCounter = 0; 43 | }; 44 | 45 | static VulkanLib* VulkanLibSingleton () 46 | { 47 | static VulkanLib inst; 48 | return &inst; 49 | } 50 | } 51 | /* 52 | ================================================= 53 | Initialize 54 | ---- 55 | must be externally synchronized! 56 | ================================================= 57 | */ 58 | bool VulkanLoader::Initialize (string libName) 59 | { 60 | VulkanLib * lib = VulkanLibSingleton(); 61 | 62 | if ( lib->module and lib->refCounter > 0 ) 63 | { 64 | ++lib->refCounter; 65 | return true; 66 | } 67 | 68 | #ifdef WIN32 69 | if ( not libName.empty() ) 70 | lib->module = ::LoadLibraryA( libName.c_str() ); 71 | 72 | if ( lib->module == nullptr ) 73 | lib->module = ::LoadLibraryA( "vulkan-1.dll" ); 74 | 75 | if ( lib->module == nullptr ) 76 | return false; 77 | 78 | // write library path to log 79 | { 80 | char buf[MAX_PATH] = ""; 81 | CHECK( ::GetModuleFileNameA( lib->module, buf, DWORD(std::size(buf)) ) != FALSE ); 82 | 83 | std::cout << "Vulkan library path: \"" << buf << '"' << std::endl; 84 | } 85 | 86 | const auto Load = [module = lib->module] (OUT auto& outResult, const char *procName, auto dummy) 87 | { 88 | using FN = decltype(dummy); 89 | FN result = reinterpret_cast( ::GetProcAddress( module, procName )); 90 | outResult = result ? result : dummy; 91 | }; 92 | 93 | #else 94 | if ( not libName.empty() ) 95 | lib->module = ::dlopen( libName.c_str(), RTLD_NOW | RTLD_LOCAL ); 96 | 97 | if ( lib->module == nullptr ) 98 | lib->module = ::dlopen( "libvulkan.so", RTLD_NOW | RTLD_LOCAL ); 99 | 100 | if ( lib->module == nullptr ) 101 | lib->module = ::dlopen( "libvulkan.so.1", RTLD_NOW | RTLD_LOCAL ); 102 | 103 | if ( lib->module == nullptr ) 104 | return false; 105 | 106 | // write library path to log 107 | # ifndef PLATFORM_ANDROID 108 | { 109 | char buf[PATH_MAX] = ""; 110 | CHECK( dlinfo( lib->module, RTLD_DI_ORIGIN, buf ) == 0 ); 111 | 112 | std::cout << "Vulkan library path: \"" << buf << '"' << std::endl; 113 | } 114 | # endif 115 | 116 | const auto Load = [module = lib->module] (OUT auto& outResult, const char *procName, auto dummy) 117 | { 118 | using FN = decltype(dummy); 119 | FN result = reinterpret_cast( ::dlsym( module, procName )); 120 | outResult = result ? result : dummy; 121 | }; 122 | #endif 123 | 124 | ++lib->refCounter; 125 | 126 | 127 | # define VKLOADER_STAGE_GETADDRESS 128 | # include "fn_vulkan_lib.h" 129 | # undef VKLOADER_STAGE_GETADDRESS 130 | 131 | ASSERT( _var_vkCreateInstance != &Dummy_vkCreateInstance ); 132 | ASSERT( _var_vkGetInstanceProcAddr != &Dummy_vkGetInstanceProcAddr ); 133 | 134 | return true; 135 | } 136 | 137 | /* 138 | ================================================= 139 | LoadInstance 140 | ---- 141 | must be externally synchronized! 142 | ================================================= 143 | */ 144 | void VulkanLoader::LoadInstance (VkInstance instance) 145 | { 146 | VulkanLib * lib = VulkanLibSingleton(); 147 | 148 | ASSERT( instance ); 149 | ASSERT( lib->instance == nullptr or lib->instance == instance ); 150 | ASSERT( _var_vkGetInstanceProcAddr != &Dummy_vkGetInstanceProcAddr ); 151 | 152 | if ( lib->instance == instance ) 153 | return; 154 | 155 | lib->instance = instance; 156 | 157 | const auto Load = [instance] (OUT auto& outResult, const char *procName, auto dummy) 158 | { 159 | using FN = decltype(dummy); 160 | FN result = reinterpret_cast( vkGetInstanceProcAddr( instance, procName )); 161 | outResult = result ? result : dummy; 162 | }; 163 | 164 | # define VKLOADER_STAGE_GETADDRESS 165 | # include "fn_vulkan_inst.h" 166 | # undef VKLOADER_STAGE_GETADDRESS 167 | } 168 | 169 | /* 170 | ================================================= 171 | LoadDevice 172 | ---- 173 | access to the 'vkGetDeviceProcAddr' must be externally synchronized! 174 | ================================================= 175 | */ 176 | void VulkanLoader::LoadDevice (VkDevice device, OUT VulkanDeviceFnTable &table) 177 | { 178 | ASSERT( _var_vkGetDeviceProcAddr != &Dummy_vkGetDeviceProcAddr ); 179 | 180 | const auto Load = [device] (OUT auto& outResult, const char *procName, auto dummy) 181 | { 182 | using FN = decltype(dummy); 183 | FN result = reinterpret_cast( vkGetDeviceProcAddr( device, procName )); 184 | outResult = result ? result : dummy; 185 | }; 186 | 187 | # define VKLOADER_STAGE_GETADDRESS 188 | # include "fn_vulkan_dev.h" 189 | # undef VKLOADER_STAGE_GETADDRESS 190 | } 191 | 192 | /* 193 | ================================================= 194 | ResetDevice 195 | ================================================= 196 | */ 197 | void VulkanLoader::ResetDevice (OUT VulkanDeviceFnTable &table) 198 | { 199 | const auto Load = [] (OUT auto& outResult, const char *, auto dummy) { 200 | outResult = dummy; 201 | }; 202 | 203 | # define VKLOADER_STAGE_GETADDRESS 204 | # include "fn_vulkan_dev.h" 205 | # undef VKLOADER_STAGE_GETADDRESS 206 | } 207 | 208 | /* 209 | ================================================= 210 | Unload 211 | ---- 212 | must be externally synchronized! 213 | ================================================= 214 | */ 215 | void VulkanLoader::Unload () 216 | { 217 | VulkanLib * lib = VulkanLibSingleton(); 218 | 219 | ASSERT( lib->refCounter > 0 ); 220 | 221 | if ( (--lib->refCounter) != 0 ) 222 | return; 223 | 224 | # ifdef WIN32 225 | if ( lib->module != nullptr ) 226 | { 227 | ::FreeLibrary( lib->module ); 228 | } 229 | # else 230 | if ( lib->module != nullptr ) 231 | { 232 | ::dlclose( lib->module ); 233 | } 234 | # endif 235 | 236 | lib->instance = nullptr; 237 | lib->module = nullptr; 238 | 239 | const auto Load = [] (OUT auto& outResult, const char *, auto dummy) { 240 | outResult = dummy; 241 | }; 242 | 243 | # define VKLOADER_STAGE_GETADDRESS 244 | # include "fn_vulkan_lib.h" 245 | # include "fn_vulkan_inst.h" 246 | # undef VKLOADER_STAGE_GETADDRESS 247 | } 248 | 249 | /* 250 | ================================================= 251 | VulkanDeviceFn_Init 252 | ================================================= 253 | */ 254 | void VulkanDeviceFn::VulkanDeviceFn_Init (const VulkanDeviceFn &other) 255 | { 256 | _table = other._table; 257 | } 258 | 259 | /* 260 | ================================================= 261 | VulkanDeviceFn_Init 262 | ================================================= 263 | */ 264 | void VulkanDeviceFn::VulkanDeviceFn_Init (VulkanDeviceFnTable *table) 265 | { 266 | _table = table; 267 | } 268 | -------------------------------------------------------------------------------- /tests/vulkan/VulkanLoader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #pragma once 4 | 5 | #include "../source/Common.h" 6 | 7 | #ifdef _MSC_VER 8 | # pragma warning (push, 0) 9 | # include 10 | # pragma warning (pop) 11 | #else 12 | # include 13 | #endif 14 | 15 | 16 | #define VKLOADER_STAGE_DECLFNPOINTER 17 | # include "fn_vulkan_lib.h" 18 | # include "fn_vulkan_inst.h" 19 | #undef VKLOADER_STAGE_DECLFNPOINTER 20 | 21 | #define VKLOADER_STAGE_INLINEFN 22 | # include "fn_vulkan_lib.h" 23 | # include "fn_vulkan_inst.h" 24 | #undef VKLOADER_STAGE_INLINEFN 25 | 26 | 27 | 28 | // 29 | // Vulkan Device Functions Table 30 | // 31 | struct VulkanDeviceFnTable final 32 | { 33 | friend struct VulkanLoader; 34 | friend class VulkanDeviceFn; 35 | 36 | // variables 37 | private: 38 | # define VKLOADER_STAGE_FNPOINTER 39 | # include "fn_vulkan_dev.h" 40 | # undef VKLOADER_STAGE_FNPOINTER 41 | 42 | 43 | // methods 44 | public: 45 | VulkanDeviceFnTable () {} 46 | 47 | VulkanDeviceFnTable (const VulkanDeviceFnTable &) = delete; 48 | VulkanDeviceFnTable (VulkanDeviceFnTable &&) = delete; 49 | 50 | VulkanDeviceFnTable& operator = (const VulkanDeviceFnTable &) = delete; 51 | VulkanDeviceFnTable& operator = (VulkanDeviceFnTable &&) = delete; 52 | }; 53 | 54 | 55 | 56 | // 57 | // Vulkan Device Functions 58 | // 59 | class VulkanDeviceFn 60 | { 61 | // variables 62 | private: 63 | VulkanDeviceFnTable * _table; 64 | 65 | // methods 66 | public: 67 | VulkanDeviceFn () : _table{nullptr} {} 68 | explicit VulkanDeviceFn (VulkanDeviceFnTable *table) : _table{table} {} 69 | 70 | void VulkanDeviceFn_Init (const VulkanDeviceFn &other); 71 | void VulkanDeviceFn_Init (VulkanDeviceFnTable *table); 72 | 73 | # define VKLOADER_STAGE_INLINEFN 74 | # include "fn_vulkan_dev.h" 75 | # undef VKLOADER_STAGE_INLINEFN 76 | }; 77 | 78 | 79 | 80 | // 81 | // Vulkan Loader 82 | // 83 | struct VulkanLoader final 84 | { 85 | VulkanLoader () = delete; 86 | 87 | static bool Initialize (std::string libName = {}); 88 | static void LoadInstance (VkInstance instance); 89 | static void Unload (); 90 | 91 | static void LoadDevice (VkDevice device, VulkanDeviceFnTable &table); 92 | static void ResetDevice (VulkanDeviceFnTable &table); 93 | }; 94 | 95 | -------------------------------------------------------------------------------- /tests/vulkan/fn_vulkan_lib.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #ifdef VKLOADER_STAGE_DECLFNPOINTER 4 | extern PFN_vkEnumerateInstanceLayerProperties _var_vkEnumerateInstanceLayerProperties; 5 | extern PFN_vkGetInstanceProcAddr _var_vkGetInstanceProcAddr; 6 | extern PFN_vkDeviceMemoryReportCallbackEXT _var_vkDeviceMemoryReportCallbackEXT; 7 | extern PFN_vkCreateInstance _var_vkCreateInstance; 8 | extern PFN_vkDebugUtilsMessengerCallbackEXT _var_vkDebugUtilsMessengerCallbackEXT; 9 | extern PFN_vkDebugReportCallbackEXT _var_vkDebugReportCallbackEXT; 10 | extern PFN_vkEnumerateInstanceVersion _var_vkEnumerateInstanceVersion; 11 | extern PFN_vkEnumerateInstanceExtensionProperties _var_vkEnumerateInstanceExtensionProperties; 12 | #endif // VKLOADER_STAGE_DECLFNPOINTER 13 | 14 | 15 | #ifdef VKLOADER_STAGE_FNPOINTER 16 | PFN_vkEnumerateInstanceLayerProperties _var_vkEnumerateInstanceLayerProperties = nullptr; 17 | PFN_vkGetInstanceProcAddr _var_vkGetInstanceProcAddr = nullptr; 18 | PFN_vkDeviceMemoryReportCallbackEXT _var_vkDeviceMemoryReportCallbackEXT = nullptr; 19 | PFN_vkCreateInstance _var_vkCreateInstance = nullptr; 20 | PFN_vkDebugUtilsMessengerCallbackEXT _var_vkDebugUtilsMessengerCallbackEXT = nullptr; 21 | PFN_vkDebugReportCallbackEXT _var_vkDebugReportCallbackEXT = nullptr; 22 | PFN_vkEnumerateInstanceVersion _var_vkEnumerateInstanceVersion = nullptr; 23 | PFN_vkEnumerateInstanceExtensionProperties _var_vkEnumerateInstanceExtensionProperties = nullptr; 24 | #endif // VKLOADER_STAGE_FNPOINTER 25 | 26 | 27 | #ifdef VKLOADER_STAGE_INLINEFN 28 | ND_ VKAPI_ATTR inline VkResult vkEnumerateInstanceLayerProperties (uint32_t * pPropertyCount, VkLayerProperties * pProperties) { return _var_vkEnumerateInstanceLayerProperties( pPropertyCount, pProperties ); } 29 | ND_ VKAPI_ATTR inline PFN_vkVoidFunction vkGetInstanceProcAddr (VkInstance instance, const char * pName) { return _var_vkGetInstanceProcAddr( instance, pName ); } 30 | VKAPI_ATTR inline void vkDeviceMemoryReportCallbackEXT (const VkDeviceMemoryReportCallbackDataEXT * pCallbackData, void * pUserData) { return _var_vkDeviceMemoryReportCallbackEXT( pCallbackData, pUserData ); } 31 | ND_ VKAPI_ATTR inline VkResult vkCreateInstance (const VkInstanceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkInstance * pInstance) { return _var_vkCreateInstance( pCreateInfo, pAllocator, pInstance ); } 32 | ND_ VKAPI_ATTR inline VkBool32 vkDebugUtilsMessengerCallbackEXT (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData, void * pUserData) { return _var_vkDebugUtilsMessengerCallbackEXT( messageSeverity, messageTypes, pCallbackData, pUserData ); } 33 | ND_ VKAPI_ATTR inline VkBool32 vkDebugReportCallbackEXT (VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char * pLayerPrefix, const char * pMessage, void * pUserData) { return _var_vkDebugReportCallbackEXT( flags, objectType, object, location, messageCode, pLayerPrefix, pMessage, pUserData ); } 34 | ND_ VKAPI_ATTR inline VkResult vkEnumerateInstanceVersion (uint32_t * pApiVersion) { return _var_vkEnumerateInstanceVersion( pApiVersion ); } 35 | ND_ VKAPI_ATTR inline VkResult vkEnumerateInstanceExtensionProperties (const char * pLayerName, uint32_t * pPropertyCount, VkExtensionProperties * pProperties) { return _var_vkEnumerateInstanceExtensionProperties( pLayerName, pPropertyCount, pProperties ); } 36 | #endif // VKLOADER_STAGE_INLINEFN 37 | 38 | 39 | #ifdef VKLOADER_STAGE_DUMMYFN 40 | VKAPI_ATTR VkResult VKAPI_CALL Dummy_vkEnumerateInstanceLayerProperties (uint32_t * , VkLayerProperties * ) { VK_LOG( "used dummy function 'vkEnumerateInstanceLayerProperties'" ); return VK_RESULT_MAX_ENUM; } 41 | VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL Dummy_vkGetInstanceProcAddr (VkInstance , const char * ) { VK_LOG( "used dummy function 'vkGetInstanceProcAddr'" ); return nullptr; } 42 | VKAPI_ATTR void VKAPI_CALL Dummy_vkDeviceMemoryReportCallbackEXT (const VkDeviceMemoryReportCallbackDataEXT * , void * ) { VK_LOG( "used dummy function 'vkDeviceMemoryReportCallbackEXT'" ); return; } 43 | VKAPI_ATTR VkResult VKAPI_CALL Dummy_vkCreateInstance (const VkInstanceCreateInfo * , const VkAllocationCallbacks * , VkInstance * ) { VK_LOG( "used dummy function 'vkCreateInstance'" ); return VK_RESULT_MAX_ENUM; } 44 | VKAPI_ATTR VkBool32 VKAPI_CALL Dummy_vkDebugUtilsMessengerCallbackEXT (VkDebugUtilsMessageSeverityFlagBitsEXT , VkDebugUtilsMessageTypeFlagsEXT , const VkDebugUtilsMessengerCallbackDataEXT * , void * ) { VK_LOG( "used dummy function 'vkDebugUtilsMessengerCallbackEXT'" ); return VkBool32(0); } 45 | VKAPI_ATTR VkBool32 VKAPI_CALL Dummy_vkDebugReportCallbackEXT (VkDebugReportFlagsEXT , VkDebugReportObjectTypeEXT , uint64_t , size_t , int32_t , const char * , const char * , void * ) { VK_LOG( "used dummy function 'vkDebugReportCallbackEXT'" ); return VkBool32(0); } 46 | VKAPI_ATTR VkResult VKAPI_CALL Dummy_vkEnumerateInstanceVersion (uint32_t * ) { VK_LOG( "used dummy function 'vkEnumerateInstanceVersion'" ); return VK_RESULT_MAX_ENUM; } 47 | VKAPI_ATTR VkResult VKAPI_CALL Dummy_vkEnumerateInstanceExtensionProperties (const char * , uint32_t * , VkExtensionProperties * ) { VK_LOG( "used dummy function 'vkEnumerateInstanceExtensionProperties'" ); return VK_RESULT_MAX_ENUM; } 48 | #endif // VKLOADER_STAGE_DUMMYFN 49 | 50 | 51 | #ifdef VKLOADER_STAGE_GETADDRESS 52 | Load( OUT _var_vkEnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties", Dummy_vkEnumerateInstanceLayerProperties ); 53 | Load( OUT _var_vkGetInstanceProcAddr, "vkGetInstanceProcAddr", Dummy_vkGetInstanceProcAddr ); 54 | Load( OUT _var_vkDeviceMemoryReportCallbackEXT, "vkDeviceMemoryReportCallbackEXT", Dummy_vkDeviceMemoryReportCallbackEXT ); 55 | Load( OUT _var_vkCreateInstance, "vkCreateInstance", Dummy_vkCreateInstance ); 56 | Load( OUT _var_vkDebugUtilsMessengerCallbackEXT, "vkDebugUtilsMessengerCallbackEXT", Dummy_vkDebugUtilsMessengerCallbackEXT ); 57 | Load( OUT _var_vkDebugReportCallbackEXT, "vkDebugReportCallbackEXT", Dummy_vkDebugReportCallbackEXT ); 58 | Load( OUT _var_vkEnumerateInstanceVersion, "vkEnumerateInstanceVersion", Dummy_vkEnumerateInstanceVersion ); 59 | Load( OUT _var_vkEnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties", Dummy_vkEnumerateInstanceExtensionProperties ); 60 | #endif // VKLOADER_STAGE_GETADDRESS 61 | 62 | -------------------------------------------------------------------------------- /tests/vulkan/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018-2020, Zhirnov Andrey. For more information see 'LICENSE' 2 | 3 | #include "Device.h" 4 | #include 5 | 6 | extern bool ShaderTrace_Test1 (Device& vulkan); 7 | extern bool ShaderTrace_Test2 (Device& vulkan); 8 | extern bool ShaderTrace_Test3 (Device& vulkan); 9 | extern bool ShaderTrace_Test4 (Device& vulkan); 10 | extern bool ShaderTrace_Test5 (Device& vulkan); 11 | extern bool ShaderTrace_Test6 (Device& vulkan); 12 | extern bool ShaderTrace_Test7 (Device& vulkan); 13 | extern bool ShaderTrace_Test8 (Device& vulkan); 14 | extern bool ShaderTrace_Test9 (Device& vulkan); 15 | extern bool ShaderTrace_Test10 (Device& vulkan); 16 | extern bool ShaderTrace_Test11 (Device& vulkan); 17 | extern bool ShaderTrace_Test12 (Device& vulkan); 18 | extern bool ShaderTrace_Test13 (Device& vulkan); 19 | extern bool ShaderTrace_Test14 (Device& vulkan); 20 | 21 | extern bool ShaderPerf_Test1 (Device& vulkan); 22 | 23 | extern bool ClockMap_Test1 (Device& vulkan); 24 | extern bool ClockMap_Test2 (Device& vulkan); 25 | 26 | 27 | int main () 28 | { 29 | Device vulkan; 30 | CHECK_ERR( vulkan.Create(), 1 ); 31 | 32 | // run tests 33 | bool passed = true; 34 | { 35 | passed &= ShaderTrace_Test1( vulkan ); 36 | passed &= ShaderTrace_Test2( vulkan ); 37 | //passed &= ShaderTrace_Test3( vulkan ); 38 | passed &= ShaderTrace_Test4( vulkan ); 39 | passed &= ShaderTrace_Test5( vulkan ); 40 | passed &= ShaderTrace_Test6( vulkan ); 41 | passed &= ShaderTrace_Test7( vulkan ); 42 | passed &= ShaderTrace_Test8( vulkan ); 43 | passed &= ShaderTrace_Test9( vulkan ); 44 | passed &= ShaderTrace_Test10( vulkan ); 45 | passed &= ShaderTrace_Test11( vulkan ); 46 | passed &= ShaderTrace_Test12( vulkan ); 47 | passed &= ShaderTrace_Test13( vulkan ); 48 | passed &= ShaderTrace_Test14( vulkan ); 49 | } 50 | 51 | # ifdef VK_KHR_shader_clock 52 | if ( vulkan.hasShaderClock ) 53 | { 54 | passed &= ShaderPerf_Test1( vulkan ); 55 | passed &= ClockMap_Test1( vulkan ); 56 | passed &= ClockMap_Test2( vulkan ); 57 | } 58 | # endif // VK_KHR_shader_clock 59 | 60 | 61 | vulkan.Destroy(); 62 | 63 | return 0; 64 | } 65 | --------------------------------------------------------------------------------