Integrated SPIRV-Tools-opt to conformance test
authorJari Komppa <jari.komppa@siru.fi>
Tue, 17 Apr 2018 09:51:08 +0000 (12:51 +0300)
committerJari Komppa <jari.komppa@siru.fi>
Tue, 29 May 2018 10:02:31 +0000 (13:02 +0300)
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
external/vulkancts/framework/vulkan/CMakeLists.txt
external/vulkancts/framework/vulkan/vkPrograms.cpp
framework/common/tcuCommandLine.cpp
framework/common/tcuCommandLine.hpp

index cbcdbb7..e5d0b71 100644 (file)
@@ -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=<number>
+
+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.
index 556d1aa..d30654b 100644 (file)
@@ -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})
index f92f28d..7e8f21b 100644 (file)
  * \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<deUint32>& 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<deUint32>        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<deUint32>        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<deUint32>        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());
index 4b81271..7a9a73a 100644 (file)
@@ -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<int>* dst)
 {
@@ -181,7 +183,9 @@ void registerOptions (de::cmdline::Parser& parser)
                << Option<LogFlush>                             (DE_NULL,       "deqp-log-flush",                               "Enable or disable log file fflush",                            s_enableNames,          "enable")
                << Option<Validation>                   (DE_NULL,       "deqp-validation",                              "Enable or disable test case validation",                       s_enableNames,          "disable")
                << Option<ShaderCache>                  (DE_NULL,       "deqp-shadercache",                             "Enable or disable shader cache",                                       s_enableNames,          "disable")
-               << Option<ShaderCacheFilename>  (DE_NULL,       "deqp-shadercache-filename",    "Write shader cache to given file",                                                                             "shadercache.bin");
+               << Option<ShaderCacheFilename>  (DE_NULL,       "deqp-shadercache-filename",    "Write shader cache to given file",                                                                             "shadercache.bin")
+               << Option<Optimization>                 (DE_NULL,       "deqp-optimization-recipe",             "Shader optimization recipe (0=disabled)",                                                              "0")
+               << Option<OptimizeSpirv>                (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<opt::TestOOM>();                                           }
 bool                                   CommandLine::isShadercacheEnabled               (void) const    { return m_cmdLine.getOption<opt::ShaderCache>();                                       }
 const char*                            CommandLine::getShaderCacheFilename             (void) const    { return m_cmdLine.getOption<opt::ShaderCacheFilename>().c_str();       }
+int                                            CommandLine::getOptimizationRecipe              (void) const    { return m_cmdLine.getOption<opt::Optimization>();                                      }
+bool                                   CommandLine::isSpirvOptimizationEnabled (void) const    { return m_cmdLine.getOption<opt::OptimizeSpirv>();                                     }
 
 const char* CommandLine::getGLContextType (void) const
 {
index 063f69f..7cefa51 100644 (file)
@@ -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