From 4b722da4ebdcd2bcad5136958a6d510b89ea94a4 Mon Sep 17 00:00:00 2001 From: Jari Komppa Date: Tue, 17 Apr 2018 12:51:08 +0300 Subject: [PATCH] Integrated SPIRV-Tools-opt to conformance test Added optional shader optimization pass to all shaders in the conformance test. The optimizer is disabled by default, but can be enabled through a command-line parameter. Due to the nature of optimizations and certain hand-crafted SPIR-V tests, the optimizer MUST NOT be enabled by default, because it will alter the tests and possibly eliminate the things that are being tested. Running with the optimizer for testing is, however, recommended since it can expose bugs in drivers. Only some optimization recipes are currently supported, but adding new ones is relatively simple. Affects: None by default, most tests if enabled. Components: Framework, Vulkan VK-GL-CTS issue: 92 Change-Id: I74996448fda1f4e11a9b16bba8c44561723a1e4e --- external/vulkancts/README.md | 45 ++++ external/vulkancts/framework/vulkan/CMakeLists.txt | 10 +- external/vulkancts/framework/vulkan/vkPrograms.cpp | 270 ++++++++++++++++++++- framework/common/tcuCommandLine.cpp | 8 +- framework/common/tcuCommandLine.hpp | 6 + 5 files changed, 328 insertions(+), 11 deletions(-) diff --git a/external/vulkancts/README.md b/external/vulkancts/README.md index cbcdbb7..e5d0b71 100644 --- a/external/vulkancts/README.md +++ b/external/vulkancts/README.md @@ -370,3 +370,48 @@ case list must be refreshed by running: python scripts/build_caselists.py path/to/cherry/data Cherry must be restarted for the case list update to take effect. + + +Shader Optimizer +---------------- + +Vulkan CTS can be optionally run with the shader optimizer enabled. This +is an experimental feature which can be used to further stress both the +drivers as well as the optimizer itself. The shader optimizer is disabled +by default. + +The following command line options can be used to configure the shader +optimizer: + + --deqp-optimization-recipe= + +The list of the optimization recipes can be found and customized in the +`optimizeCompiledBinary()` function in `vkPrograms.cpp`. + +As of this writing, there are 8 recipes to choose from: + + 0. Disabled (default) + 1. The example recipe from spir-v opt 1.0 whitepaper + 2. RegisterPerformancePasses from commandline optimizer tool october 2017 + 3. RegisterSizePasses from commandline optimizer tool october 2017 + 4. RegisterLegalizationPasses from commandline optimizer tool April 2018 + 5. RegisterPerformancePasses from commandline optimizer tool April 2018 + 6. RegisterPerformancePasses from commandline optimizer tool April 2018 with CreateCommonUniformElimPass + 7. RegisterSizePasses from commandline optimizer tool April 2018 + 8. RegisterSizePasses from commandline optimizer tool April 2018 with CreateCommonUniformElimPass + +The `Register...Passes()` calls change in the SPIR-V optimizer tool from +time to time. Since different sets of passes may result in different +shaders, having several fixed sets is useful for issue discovery. + + --deqp-optimize-spirv=enable + +This option is not required to run the optimizer. By default, the shader +optimizer only optimizes shaders generated from GLSL or HLSL, and leaves +hand-written SPIR-V shaders alone. + +Many of the hand-written SPIR-V tests stress specific features of the +SPIR-V which might get optimized out. Using this option will enable the +optimizer on the hand-written SPIR-V as well, which may be useful in +finding new bugs in drivers or the optimizer itself, but will likely +invalidate the tests themselves. diff --git a/external/vulkancts/framework/vulkan/CMakeLists.txt b/external/vulkancts/framework/vulkan/CMakeLists.txt index 556d1aa..d30654b 100644 --- a/external/vulkancts/framework/vulkan/CMakeLists.txt +++ b/external/vulkancts/framework/vulkan/CMakeLists.txt @@ -87,8 +87,16 @@ if(DEQP_HAVE_SPIRV_TOOLS) include_directories(${spirv-tools_SOURCE_DIR}/include) include_directories(${spirv-tools_SOURCE_DIR}/external/include) + # \note Code interfacing with spirv-opt needs to include third-party headers + # that cause all sorts of warnings to appear. + if (DE_COMPILER_IS_GCC OR DE_COMPILER_IS_CLANG) + set_source_files_properties( + FILES vkPrograms.cpp + PROPERTIES COMPILE_FLAGS "${DE_3RD_PARTY_CXX_FLAGS} -std=c++11") + endif () + add_definitions(-DDEQP_HAVE_SPIRV_TOOLS=1) - set(VKUTIL_LIBS ${VKUTIL_LIBS} SPIRV-Tools) + set(VKUTIL_LIBS ${VKUTIL_LIBS} SPIRV-Tools SPIRV-Tools-opt) endif() add_library(vkutil STATIC ${VKUTIL_SRCS}) diff --git a/external/vulkancts/framework/vulkan/vkPrograms.cpp b/external/vulkancts/framework/vulkan/vkPrograms.cpp index f92f28d..7e8f21b 100644 --- a/external/vulkancts/framework/vulkan/vkPrograms.cpp +++ b/external/vulkancts/framework/vulkan/vkPrograms.cpp @@ -21,6 +21,10 @@ * \brief Program utilities. *//*--------------------------------------------------------------------*/ +#if defined(DEQP_HAVE_SPIRV_TOOLS) +#include "spirv-tools/optimizer.hpp" +#endif + #include "qpInfo.h" #include "vkPrograms.hpp" @@ -66,6 +70,230 @@ ProgramBinary::ProgramBinary (ProgramFormat format, size_t binarySize, const deU namespace { +#if defined(DEQP_HAVE_SPIRV_TOOLS) + +void optimizeCompiledBinary (vector& binary, int optimizationRecipe, const SpirvVersion spirvVersion) +{ + spv_target_env targetEnv = SPV_ENV_VULKAN_1_0; + + // Map SpirvVersion with spv_target_env: + switch (spirvVersion) + { + case SPIRV_VERSION_1_0: targetEnv = SPV_ENV_VULKAN_1_0; break; + case SPIRV_VERSION_1_1: + case SPIRV_VERSION_1_2: + case SPIRV_VERSION_1_3: targetEnv = SPV_ENV_VULKAN_1_1; break; + default: + TCU_THROW(InternalError, "Unexpected SPIR-V version requested"); + } + + spvtools::Optimizer optimizer(targetEnv); + + switch (optimizationRecipe) + { + case 1: + // The example recipe from: + // https://www.lunarg.com/wp-content/uploads/2017/08/SPIR-V-Shader-Size-Reduction-Using-spirv-opt_v1.0.pdf + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); // --inline-entry-points-exhaustive + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); // --convert-local-access-chains + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass());// --eliminate-local-single-block + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); // --eliminate-local-single-store + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); // --eliminate-insert-extract + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); // --eliminate-dead-code-aggressive + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); // --eliminate-dead-branches + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); // --merge-blocks + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass());// --eliminate-local-single-block + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); // --eliminate-local-single-store + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); // --eliminate-local-multi-store + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); // --eliminate-insert-extract + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); // --eliminate-dead-code-aggressive + optimizer.RegisterPass(spvtools::CreateCommonUniformElimPass()); // --eliminate-common-uniform + break; + case 2: // RegisterPerformancePasses from commandline optimizer tool october 2017 + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateCommonUniformElimPass()); + break; + case 3: // RegisterSizePasses from commandline optimizer tool october 2017 + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateCommonUniformElimPass()); + break; + case 4: // RegisterLegalizationPasses from commandline optimizer tool April 2018 + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass()); + optimizer.RegisterPass(spvtools::CreatePrivateToLocalPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCCPPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateSimplificationPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCopyPropagateArraysPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + break; + case 5: // RegisterPerformancePasses from commandline optimizer tool April 2018 + optimizer.RegisterPass(spvtools::CreateRemoveDuplicatesPass()); + optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCCPPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateSimplificationPass()); + optimizer.RegisterPass(spvtools::CreateIfConversionPass()); + optimizer.RegisterPass(spvtools::CreateCopyPropagateArraysPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + // comment from tool: + // Currently exposing driver bugs resulting in crashes (#946) + // .RegisterPass(CreateCommonUniformElimPass()) + break; + case 6: // RegisterPerformancePasses from commandline optimizer tool April 2018 with CreateCommonUniformElimPass + optimizer.RegisterPass(spvtools::CreateRemoveDuplicatesPass()); + optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCCPPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateSimplificationPass()); + optimizer.RegisterPass(spvtools::CreateIfConversionPass()); + optimizer.RegisterPass(spvtools::CreateCopyPropagateArraysPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateCommonUniformElimPass()); + break; + case 7: // RegisterSizePasses from commandline optimizer tool April 2018 + optimizer.RegisterPass(spvtools::CreateRemoveDuplicatesPass()); + optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCCPPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateIfConversionPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); + // comment from tool: + // Currently exposing driver bugs resulting in crashes (#946) + // .RegisterPass(CreateCommonUniformElimPass()) + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + break; + case 8: // RegisterSizePasses from commandline optimizer tool April 2018 with CreateCommonUniformElimPass + optimizer.RegisterPass(spvtools::CreateRemoveDuplicatesPass()); + optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); + optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); + optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateCCPPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); + optimizer.RegisterPass(spvtools::CreateIfConversionPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + optimizer.RegisterPass(spvtools::CreateBlockMergePass()); + optimizer.RegisterPass(spvtools::CreateInsertExtractElimPass()); + optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); + optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); + optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); + optimizer.RegisterPass(spvtools::CreateCommonUniformElimPass()); + optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); + break; + default: + TCU_THROW(InternalError, "Unknown optimization recipe requested"); + } + + const bool ok = optimizer.Run(binary.data(), binary.size(), &binary); + + if (!ok) + TCU_THROW(InternalError, "Optimizer call failed"); +} + +#endif // defined(DEQP_HAVE_SPIRV_TOOLS) + + bool isNativeSpirVBinaryEndianness (void) { #if (DE_ENDIANNESS == SPIRV_BINARY_ENDIANNESS) @@ -275,7 +503,7 @@ void getCompileEnvironment (std::string& shaderstring) } // Insert compilation options into the shader string. -void getBuildOptions (std::string& shaderstring, const ShaderBuildOptions& buildOptions) +void getBuildOptions (std::string& shaderstring, const ShaderBuildOptions& buildOptions, int optimizationRecipe) { shaderstring += "Target Spir-V "; shaderstring += getSpirvVersionName(buildOptions.targetVersion); @@ -284,20 +512,27 @@ void getBuildOptions (std::string& shaderstring, const ShaderBuildOptions& build shaderstring += "Flag:Allow relaxed offsets\n"; if (buildOptions.flags & ShaderBuildOptions::FLAG_USE_STORAGE_BUFFER_STORAGE_CLASS) shaderstring += "Flag:Use storage buffer storage class\n"; + if (optimizationRecipe != 0) + { + shaderstring += "Optimization recipe "; + shaderstring += optimizationRecipe; + shaderstring += "\n"; + } } ProgramBinary* buildProgram (const GlslSource& program, glu::ShaderProgramInfo* buildInfo, const tcu::CommandLine& commandLine) { - const SpirvVersion spirvVersion = program.buildOptions.targetVersion; - const bool validateBinary = VALIDATE_BINARIES; + const SpirvVersion spirvVersion = program.buildOptions.targetVersion; + const bool validateBinary = VALIDATE_BINARIES; vector binary; std::string shaderstring; - vk::ProgramBinary* res = 0; + vk::ProgramBinary* res = 0; + const int optimizationRecipe = commandLine.getOptimizationRecipe(); if (commandLine.isShadercacheEnabled()) { getCompileEnvironment(shaderstring); - getBuildOptions(shaderstring, program.buildOptions); + getBuildOptions(shaderstring, program.buildOptions, optimizationRecipe); for (int i = 0; i < glu::SHADERTYPE_LAST; i++) { @@ -351,6 +586,9 @@ ProgramBinary* buildProgram (const GlslSource& program, glu::ShaderProgramInfo* if (validateBinary) validateCompiledBinary(binary, buildInfo, spirvVersion); + if (optimizationRecipe != 0) + optimizeCompiledBinary(binary, optimizationRecipe, spirvVersion); + res = createProgramBinaryFromSpirV(binary); if (commandLine.isShadercacheEnabled()) shadercacheSave(res, shaderstring, commandLine.getShaderCacheFilename()); @@ -360,16 +598,17 @@ ProgramBinary* buildProgram (const GlslSource& program, glu::ShaderProgramInfo* ProgramBinary* buildProgram (const HlslSource& program, glu::ShaderProgramInfo* buildInfo, const tcu::CommandLine& commandLine) { - const SpirvVersion spirvVersion = program.buildOptions.targetVersion; - const bool validateBinary = VALIDATE_BINARIES; + const SpirvVersion spirvVersion = program.buildOptions.targetVersion; + const bool validateBinary = VALIDATE_BINARIES; vector binary; std::string shaderstring; - vk::ProgramBinary* res = 0; + vk::ProgramBinary* res = 0; + const int optimizationRecipe = commandLine.getOptimizationRecipe(); if (commandLine.isShadercacheEnabled()) { getCompileEnvironment(shaderstring); - getBuildOptions(shaderstring, program.buildOptions); + getBuildOptions(shaderstring, program.buildOptions, optimizationRecipe); for (int i = 0; i < glu::SHADERTYPE_LAST; i++) { @@ -423,6 +662,9 @@ ProgramBinary* buildProgram (const HlslSource& program, glu::ShaderProgramInfo* if (validateBinary) validateCompiledBinary(binary, buildInfo, spirvVersion); + if (optimizationRecipe != 0) + optimizeCompiledBinary(binary, optimizationRecipe, spirvVersion); + res = createProgramBinaryFromSpirV(binary); if (commandLine.isShadercacheEnabled()) shadercacheSave(res, shaderstring, commandLine.getShaderCacheFilename()); @@ -437,6 +679,7 @@ ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* vector binary; vk::ProgramBinary* res = 0; std::string shaderstring; + const int optimizationRecipe = commandLine.isSpirvOptimizationEnabled() ? commandLine.getOptimizationRecipe() : 0; if (commandLine.isShadercacheEnabled()) { @@ -444,6 +687,12 @@ ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* shaderstring += "Target Spir-V "; shaderstring += getSpirvVersionName(spirvVersion); shaderstring += "\n"; + if (optimizationRecipe != 0) + { + shaderstring += "Optimization recipe "; + shaderstring += optimizationRecipe; + shaderstring += "\n"; + } shaderstring += program.source; @@ -477,6 +726,9 @@ ProgramBinary* assembleProgram (const SpirVAsmSource& program, SpirVProgramInfo* } } + if (optimizationRecipe != 0) + optimizeCompiledBinary(binary, optimizationRecipe, spirvVersion); + res = createProgramBinaryFromSpirV(binary); if (commandLine.isShadercacheEnabled()) shadercacheSave(res, shaderstring, commandLine.getShaderCacheFilename()); diff --git a/framework/common/tcuCommandLine.cpp b/framework/common/tcuCommandLine.cpp index 4b81271..7a9a73a 100644 --- a/framework/common/tcuCommandLine.cpp +++ b/framework/common/tcuCommandLine.cpp @@ -91,6 +91,8 @@ DE_DECLARE_COMMAND_LINE_OPT(LogFlush, bool); DE_DECLARE_COMMAND_LINE_OPT(Validation, bool); DE_DECLARE_COMMAND_LINE_OPT(ShaderCache, bool); DE_DECLARE_COMMAND_LINE_OPT(ShaderCacheFilename, std::string); +DE_DECLARE_COMMAND_LINE_OPT(Optimization, int); +DE_DECLARE_COMMAND_LINE_OPT(OptimizeSpirv, bool); static void parseIntList (const char* src, std::vector* dst) { @@ -181,7 +183,9 @@ void registerOptions (de::cmdline::Parser& parser) << Option (DE_NULL, "deqp-log-flush", "Enable or disable log file fflush", s_enableNames, "enable") << Option (DE_NULL, "deqp-validation", "Enable or disable test case validation", s_enableNames, "disable") << Option (DE_NULL, "deqp-shadercache", "Enable or disable shader cache", s_enableNames, "disable") - << Option (DE_NULL, "deqp-shadercache-filename", "Write shader cache to given file", "shadercache.bin"); + << Option (DE_NULL, "deqp-shadercache-filename", "Write shader cache to given file", "shadercache.bin") + << Option (DE_NULL, "deqp-optimization-recipe", "Shader optimization recipe (0=disabled)", "0") + << Option (DE_NULL, "deqp-optimize-spirv", "Apply optimization to spir-v shaders as well", s_enableNames, "disable"); } void registerLegacyOptions (de::cmdline::Parser& parser) @@ -797,6 +801,8 @@ bool CommandLine::isValidationEnabled (void) const { return m_cmdLine.getOp bool CommandLine::isOutOfMemoryTestEnabled (void) const { return m_cmdLine.getOption(); } bool CommandLine::isShadercacheEnabled (void) const { return m_cmdLine.getOption(); } const char* CommandLine::getShaderCacheFilename (void) const { return m_cmdLine.getOption().c_str(); } +int CommandLine::getOptimizationRecipe (void) const { return m_cmdLine.getOption(); } +bool CommandLine::isSpirvOptimizationEnabled (void) const { return m_cmdLine.getOption(); } const char* CommandLine::getGLContextType (void) const { diff --git a/framework/common/tcuCommandLine.hpp b/framework/common/tcuCommandLine.hpp index 063f69f..7cefa51 100644 --- a/framework/common/tcuCommandLine.hpp +++ b/framework/common/tcuCommandLine.hpp @@ -217,6 +217,12 @@ public: //! Get the filename for shader cache (--deqp-shadercache-filename) const char* getShaderCacheFilename (void) const; + //! Get shader optimization recipe (--deqp-optimization-recipe) + int getOptimizationRecipe (void) const; + + //! Enable optimizing of spir-v (--deqp-optimize-spirv) + bool isSpirvOptimizationEnabled (void) const; + /*--------------------------------------------------------------------*//*! * \brief Creates case list filter * \param archive Resources -- 2.7.4