yum-mirror/glslang

git clone https://git.yummers.dev/yum-mirror/glslang

ifrforspirv: use the lists of optimization passes from spirv-tools6a0d48e4

main
11.5 KiB296 linesraw
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{
54    switch (spvVersion.vulkan) {
55    case glslang::EShTargetVulkan_1_0:
56        return spv_target_env::SPV_ENV_VULKAN_1_0;
57    case glslang::EShTargetVulkan_1_1:
58        switch (spvVersion.spv) {
59        case EShTargetSpv_1_0:
60        case EShTargetSpv_1_1:
61        case EShTargetSpv_1_2:
62        case EShTargetSpv_1_3:
63            return spv_target_env::SPV_ENV_VULKAN_1_1;
64        case EShTargetSpv_1_4:
65            return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4;
66        default:
67            logger->missingFunctionality("Target version for SPIRV-Tools validator");
68            return spv_target_env::SPV_ENV_VULKAN_1_1;
69        }
70    case glslang::EShTargetVulkan_1_2:
71        return spv_target_env::SPV_ENV_VULKAN_1_2;
72    case glslang::EShTargetVulkan_1_3:
73        return spv_target_env::SPV_ENV_VULKAN_1_3;
74    case glslang::EShTargetVulkan_1_4:
75        return spv_target_env::SPV_ENV_VULKAN_1_4;
76    default:
77        break;
78    }
79
80    if (spvVersion.openGl > 0)
81        return spv_target_env::SPV_ENV_OPENGL_4_5;
82
83    logger->missingFunctionality("Target version for SPIRV-Tools validator");
84    return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
85}
86
87spv_target_env MapToSpirvToolsEnv(const glslang::TIntermediate& intermediate, spv::SpvBuildLogger* logger)
88{
89    return MapToSpirvToolsEnv(intermediate.getSpv(), logger);
90}
91
92// Callback passed to spvtools::Optimizer::SetMessageConsumer
93void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
94        const spv_position_t &position, const char *message)
95{
96    auto &out = std::cerr;
97    switch (level)
98    {
99    case SPV_MSG_FATAL:
100    case SPV_MSG_INTERNAL_ERROR:
101    case SPV_MSG_ERROR:
102        out << "error: ";
103        break;
104    case SPV_MSG_WARNING:
105        out << "warning: ";
106        break;
107    case SPV_MSG_INFO:
108    case SPV_MSG_DEBUG:
109        out << "info: ";
110        break;
111    default:
112        break;
113    }
114    if (source)
115    {
116        out << source << ":";
117    }
118    out << position.line << ":" << position.column << ":" << position.index << ":";
119    if (message)
120    {
121        out << " " << message;
122    }
123    out << 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{
129    SpirvToolsDisassemble(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,
134                           spv_target_env requested_context)
135{
136    // disassemble
137    spv_context context = spvContextCreate(requested_context);
138    spv_text text;
139    spv_diagnostic diagnostic = nullptr;
140    spvBinaryToText(context, spirv.data(), spirv.size(),
141        SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
142        &text, &diagnostic);
143
144    // dump
145    if (diagnostic == nullptr)
146        out << text->str;
147    else
148        spvDiagnosticPrint(diagnostic);
149
150    // teardown
151    spvDiagnosticDestroy(diagnostic);
152    spvContextDestroy(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
160    spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
161    spv_const_binary_t binary = { spirv.data(), spirv.size() };
162    spv_diagnostic diagnostic = nullptr;
163    spv_validator_options options = spvValidatorOptionsCreate();
164    spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
165    spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
166    spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
167    spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
168    spvValidatorOptionsSetAllowOffsetTextureOperand(options, intermediate.usingTextureOffsetNonConst());
169    spvValidatorOptionsSetAllowVulkan32BitBitwise(options, true);
170    spvValidateWithOptions(context, options, &binary, &diagnostic);
171
172    // report
173    if (diagnostic != nullptr) {
174        logger->error("SPIRV-Tools Validation Errors");
175        logger->error(diagnostic->error);
176    }
177
178    // tear down
179    spvValidatorOptionsDestroy(options);
180    spvDiagnosticDestroy(diagnostic);
181    spvContextDestroy(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{
188    spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
189
190    spvtools::Optimizer optimizer(target_env);
191    optimizer.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.
197    if (options->stripDebugInfo) {
198        optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
199    }
200
201    if (prelegalization)
202        optimizer.RegisterLegalizationPasses();
203    if (options->optimizePerformance)
204        optimizer.RegisterPerformancePasses();
205    if (options->optimizeSize)
206        optimizer.RegisterSizePasses();
207
208    spvtools::OptimizerOptions spvOptOptions;
209    if (options->optimizerAllowExpandedIDBound)
210        spvOptOptions.set_max_id_bound(0x3FFFFFFF);
211    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
212    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
213    optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
214
215    if (options->optimizerAllowExpandedIDBound) {
216        if (spirv.size() > 3 && spirv[3] > kDefaultMaxIdBound) {
217            spvtools::Optimizer optimizer2(target_env);
218            optimizer2.SetMessageConsumer(OptimizerMesssageConsumer);
219            optimizer2.RegisterPass(spvtools::CreateCompactIdsPass());
220            optimizer2.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);
231  optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
232
233  optimizer.RegisterPass(spvtools::CreateAnalyzeLiveInputPass(live_locs, live_builtins));
234
235  spvtools::OptimizerOptions spvOptOptions;
236  optimizer.SetTargetEnv(target_env);
237  spvOptOptions.set_run_validator(false);
238  return 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);
247  optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
248
249  optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputStoresPass(live_locs, live_builtins));
250  optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true));
251  optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputComponentsPass());
252  optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true));
253
254  spvtools::OptimizerOptions spvOptOptions;
255  optimizer.SetTargetEnv(target_env);
256  spvOptOptions.set_run_validator(false);
257  optimizer.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);
264  optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
265
266  optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass());
267  optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
268
269  spvtools::OptimizerOptions spvOptOptions;
270  optimizer.SetTargetEnv(target_env);
271  spvOptOptions.set_run_validator(false);
272  optimizer.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{
281    spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
282
283    spvtools::Optimizer optimizer(target_env);
284    optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
285
286    optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
287
288    spvtools::OptimizerOptions spvOptOptions;
289    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
290    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
291    optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
292}
293
294} // end namespace glslang
295
296#endif