yum-mirror/glslang
git clone https://git.yummers.dev/yum-mirror/glslang
6a0d48e4
main
1// 2// Copyright (C) 2014-2016 LunarG, Inc. 3// Copyright (C) 2018-2020 Google, Inc. 4// 5// All rights reserved. 6// 7// Redistribution and use in source and binary forms, with or without 8// modification, are permitted provided that the following conditions 9// are met: 10// 11// Redistributions of source code must retain the above copyright 12// notice, this list of conditions and the following disclaimer. 13// 14// Redistributions in binary form must reproduce the above 15// copyright notice, this list of conditions and the following 16// disclaimer in the documentation and/or other materials provided 17// with the distribution. 18// 19// Neither the name of 3Dlabs Inc. Ltd. nor the names of its 20// contributors may be used to endorse or promote products derived 21// from this software without specific prior written permission. 22// 23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34// POSSIBILITY OF SUCH DAMAGE. 35 36// 37// Call into SPIRV-Tools to disassemble, validate, and optimize. 38// 39 40#if ENABLE_OPT 41 42#include <cstdio> 43#include <iostream> 44 45#include "SpvTools.h" 46#include "spirv-tools/optimizer.hpp" 47#include "glslang/MachineIndependent/localintermediate.h" 48 49namespace glslang { 50 51// Translate glslang's view of target versioning to what SPIRV-Tools uses. 52spv_target_env MapToSpirvToolsEnv (const SpvVersion & spvVersion , spv::SpvBuildLogger * logger ) 53{ 54switch (spvVersion .vulkan ) { 55case glslang::EShTargetVulkan_1_0 : 56return spv_target_env::SPV_ENV_VULKAN_1_0 ; 57case glslang::EShTargetVulkan_1_1 : 58switch (spvVersion .spv ) { 59case EShTargetSpv_1_0 : 60case EShTargetSpv_1_1 : 61case EShTargetSpv_1_2 : 62case EShTargetSpv_1_3 : 63return spv_target_env::SPV_ENV_VULKAN_1_1 ; 64case EShTargetSpv_1_4 : 65return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4 ; 66default : 67logger -> missingFunctionality ("Target version for SPIRV-Tools validator" ); 68return spv_target_env::SPV_ENV_VULKAN_1_1 ; 69 } 70case glslang::EShTargetVulkan_1_2 : 71return spv_target_env::SPV_ENV_VULKAN_1_2 ; 72case glslang::EShTargetVulkan_1_3 : 73return spv_target_env::SPV_ENV_VULKAN_1_3 ; 74case glslang::EShTargetVulkan_1_4 : 75return spv_target_env::SPV_ENV_VULKAN_1_4 ; 76default : 77break ; 78 } 79 80if (spvVersion .openGl > 0 ) 81return spv_target_env::SPV_ENV_OPENGL_4_5 ; 82 83logger -> missingFunctionality ("Target version for SPIRV-Tools validator" ); 84return spv_target_env::SPV_ENV_UNIVERSAL_1_0 ; 85} 86 87spv_target_env MapToSpirvToolsEnv (const glslang::TIntermediate & intermediate , spv::SpvBuildLogger * logger ) 88{ 89return MapToSpirvToolsEnv (intermediate .getSpv (),logger ); 90} 91 92// Callback passed to spvtools::Optimizer::SetMessageConsumer 93void OptimizerMesssageConsumer (spv_message_level_t level ,const char * source , 94const spv_position_t & position ,const char * message ) 95{ 96auto & out = std::cerr ; 97switch (level ) 98 { 99case SPV_MSG_FATAL : 100case SPV_MSG_INTERNAL_ERROR : 101case SPV_MSG_ERROR : 102out <<"error: " ; 103break ; 104case SPV_MSG_WARNING : 105out <<"warning: " ; 106break ; 107case SPV_MSG_INFO : 108case SPV_MSG_DEBUG : 109out <<"info: " ; 110break ; 111default : 112break ; 113 } 114if (source ) 115 { 116out <<source <<":" ; 117 } 118out <<position .line <<":" <<position .column <<":" <<position .index <<":" ; 119if (message ) 120 { 121out <<" " <<message ; 122 } 123out << std::endl ; 124} 125 126// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. 127void SpirvToolsDisassemble (std::ostream & out ,const std::vector < unsigned int >& spirv ) 128{ 129SpirvToolsDisassemble (out ,spirv , spv_target_env::SPV_ENV_UNIVERSAL_1_3 ); 130} 131 132// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. 133void SpirvToolsDisassemble (std::ostream & out ,const std::vector < unsigned int >& spirv , 134spv_target_env requested_context ) 135{ 136// disassemble 137spv_context context = spvContextCreate (requested_context ); 138spv_text text ; 139spv_diagnostic diagnostic = nullptr ; 140spvBinaryToText (context ,spirv .data (),spirv .size (), 141SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |SPV_BINARY_TO_TEXT_OPTION_INDENT , 142& text ,& diagnostic ); 143 144// dump 145if (diagnostic == nullptr ) 146out <<text -> str ; 147else 148spvDiagnosticPrint (diagnostic ); 149 150// teardown 151spvDiagnosticDestroy (diagnostic ); 152spvContextDestroy (context ); 153} 154 155// Apply the SPIRV-Tools validator to generated SPIR-V. 156void SpirvToolsValidate (const glslang::TIntermediate & intermediate , std::vector < unsigned int >& spirv , 157 spv::SpvBuildLogger * logger ,bool prelegalization ) 158{ 159// validate 160spv_context context = spvContextCreate (MapToSpirvToolsEnv (intermediate .getSpv (),logger )); 161spv_const_binary_t binary = {spirv .data (),spirv .size () }; 162spv_diagnostic diagnostic = nullptr ; 163spv_validator_options options = spvValidatorOptionsCreate (); 164spvValidatorOptionsSetRelaxBlockLayout (options ,intermediate .usingHlslOffsets ()); 165spvValidatorOptionsSetBeforeHlslLegalization (options ,prelegalization ); 166spvValidatorOptionsSetScalarBlockLayout (options ,intermediate .usingScalarBlockLayout ()); 167spvValidatorOptionsSetWorkgroupScalarBlockLayout (options ,intermediate .usingScalarBlockLayout ()); 168spvValidatorOptionsSetAllowOffsetTextureOperand (options ,intermediate .usingTextureOffsetNonConst ()); 169spvValidatorOptionsSetAllowVulkan32BitBitwise (options , true); 170spvValidateWithOptions (context ,options ,& binary ,& diagnostic ); 171 172// report 173if (diagnostic != nullptr ) { 174logger -> error ("SPIRV-Tools Validation Errors" ); 175logger -> error (diagnostic -> error ); 176 } 177 178// tear down 179spvValidatorOptionsDestroy (options ); 180spvDiagnosticDestroy (diagnostic ); 181spvContextDestroy (context ); 182} 183 184// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. 185void SpirvToolsTransform (const glslang::TIntermediate & intermediate , std::vector < unsigned int >& spirv , 186 spv::SpvBuildLogger * logger ,const SpvOptions * options ,bool prelegalization ) 187{ 188spv_target_env target_env = MapToSpirvToolsEnv (intermediate .getSpv (),logger ); 189 190 spvtools::Optimizer optimizer (target_env ); 191optimizer .SetMessageConsumer (OptimizerMesssageConsumer ); 192 193// If debug (specifically source line info) is being generated, propagate 194// line information into all SPIR-V instructions. This avoids loss of 195// information when instructions are deleted or moved. Later, remove 196// redundant information to minimize final SPRIR-V size. 197if (options -> stripDebugInfo ) { 198optimizer .RegisterPass (spvtools::CreateStripDebugInfoPass ()); 199 } 200 201if (prelegalization ) 202optimizer .RegisterLegalizationPasses (); 203if (options -> optimizePerformance ) 204optimizer .RegisterPerformancePasses (); 205if (options -> optimizeSize ) 206optimizer .RegisterSizePasses (); 207 208 spvtools::OptimizerOptions spvOptOptions ; 209if (options -> optimizerAllowExpandedIDBound ) 210spvOptOptions .set_max_id_bound (0x3FFFFFFF ); 211optimizer .SetTargetEnv (MapToSpirvToolsEnv (intermediate .getSpv (),logger )); 212spvOptOptions .set_run_validator (false);// The validator may run as a separate step later on 213optimizer .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 214 215if (options -> optimizerAllowExpandedIDBound ) { 216if (spirv .size ()> 3 && spirv [3 ]> kDefaultMaxIdBound ) { 217 spvtools::Optimizer optimizer2 (target_env ); 218optimizer2 .SetMessageConsumer (OptimizerMesssageConsumer ); 219optimizer2 .RegisterPass (spvtools::CreateCompactIdsPass ()); 220optimizer2 .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 221 } 222 } 223} 224 225bool SpirvToolsAnalyzeDeadOutputStores (spv_target_env target_env , std::vector < unsigned int >& spirv , 226 std::unordered_set < uint32_t >* live_locs , 227 std::unordered_set < uint32_t >* live_builtins , 228 spv::SpvBuildLogger * ) 229{ 230 spvtools::Optimizer optimizer (target_env ); 231optimizer .SetMessageConsumer (OptimizerMesssageConsumer ); 232 233optimizer .RegisterPass (spvtools::CreateAnalyzeLiveInputPass (live_locs ,live_builtins )); 234 235 spvtools::OptimizerOptions spvOptOptions ; 236optimizer .SetTargetEnv (target_env ); 237spvOptOptions .set_run_validator (false); 238return optimizer .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 239} 240 241void SpirvToolsEliminateDeadOutputStores (spv_target_env target_env , std::vector < unsigned int >& spirv , 242 std::unordered_set < uint32_t >* live_locs , 243 std::unordered_set < uint32_t >* live_builtins , 244 spv::SpvBuildLogger * ) 245{ 246 spvtools::Optimizer optimizer (target_env ); 247optimizer .SetMessageConsumer (OptimizerMesssageConsumer ); 248 249optimizer .RegisterPass (spvtools::CreateEliminateDeadOutputStoresPass (live_locs ,live_builtins )); 250optimizer .RegisterPass (spvtools::CreateAggressiveDCEPass (false, true)); 251optimizer .RegisterPass (spvtools::CreateEliminateDeadOutputComponentsPass ()); 252optimizer .RegisterPass (spvtools::CreateAggressiveDCEPass (false, true)); 253 254 spvtools::OptimizerOptions spvOptOptions ; 255optimizer .SetTargetEnv (target_env ); 256spvOptOptions .set_run_validator (false); 257optimizer .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 258} 259 260void SpirvToolsEliminateDeadInputComponents (spv_target_env target_env , std::vector < unsigned int >& spirv , 261 spv::SpvBuildLogger * ) 262{ 263 spvtools::Optimizer optimizer (target_env ); 264optimizer .SetMessageConsumer (OptimizerMesssageConsumer ); 265 266optimizer .RegisterPass (spvtools::CreateEliminateDeadInputComponentsPass ()); 267optimizer .RegisterPass (spvtools::CreateAggressiveDCEPass ()); 268 269 spvtools::OptimizerOptions spvOptOptions ; 270optimizer .SetTargetEnv (target_env ); 271spvOptOptions .set_run_validator (false); 272optimizer .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 273} 274 275// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by 276// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if 277// optimization is disabled. 278void SpirvToolsStripDebugInfo (const glslang::TIntermediate & intermediate , 279 std::vector < unsigned int >& spirv , spv::SpvBuildLogger * logger ) 280{ 281spv_target_env target_env = MapToSpirvToolsEnv (intermediate .getSpv (),logger ); 282 283 spvtools::Optimizer optimizer (target_env ); 284optimizer .SetMessageConsumer (OptimizerMesssageConsumer ); 285 286optimizer .RegisterPass (spvtools::CreateStripDebugInfoPass ()); 287 288 spvtools::OptimizerOptions spvOptOptions ; 289optimizer .SetTargetEnv (MapToSpirvToolsEnv (intermediate .getSpv (),logger )); 290spvOptOptions .set_run_validator (false);// The validator may run as a separate step later on 291optimizer .Run (spirv .data (),spirv .size (),& spirv ,spvOptOptions ); 292} 293 294}// end namespace glslang 295 296#endif