2 // Copyright(C) 2021 Advanced Micro Devices, Inc.
4 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
10 // Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
13 // Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following
15 // disclaimer in the documentation and/or other materials provided
16 // with the distribution.
18 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19 // contributors may be used to endorse or promote products derived
20 // from this software without specific prior written permission.
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 // POSSIBILITY OF SUCH DAMAGE.
39 // GL_EXT_spirv_intrinsics
41 #include "../Include/intermediate.h"
42 #include "../Include/SpirvIntrinsics.h"
43 #include "../Include/Types.h"
44 #include "ParseHelper.h"
49 // Handle SPIR-V requirements
51 TSpirvRequirement* TParseContext::makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
52 const TIntermAggregate* extensions,
53 const TIntermAggregate* capabilities)
55 TSpirvRequirement* spirvReq = new TSpirvRequirement;
57 if (name == "extensions") {
59 for (auto extension : extensions->getSequence()) {
60 assert(extension->getAsConstantUnion());
61 spirvReq->extensions.insert(*extension->getAsConstantUnion()->getConstArray()[0].getSConst());
63 } else if (name == "capabilities") {
65 for (auto capability : capabilities->getSequence()) {
66 assert(capability->getAsConstantUnion());
67 spirvReq->capabilities.insert(capability->getAsConstantUnion()->getConstArray()[0].getIConst());
70 error(loc, "unknow SPIR-V requirement", name.c_str(), "");
75 TSpirvRequirement* TParseContext::mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
76 TSpirvRequirement* spirvReq2)
78 // Merge the second SPIR-V requirement to the first one
79 if (!spirvReq2->extensions.empty()) {
80 if (spirvReq1->extensions.empty())
81 spirvReq1->extensions = spirvReq2->extensions;
83 error(loc, "too many SPIR-V requirements", "extensions", "");
86 if (!spirvReq2->capabilities.empty()) {
87 if (spirvReq1->capabilities.empty())
88 spirvReq1->capabilities = spirvReq2->capabilities;
90 error(loc, "too many SPIR-V requirements", "capabilities", "");
96 void TIntermediate::insertSpirvRequirement(const TSpirvRequirement* spirvReq)
98 if (!spirvRequirement)
99 spirvRequirement = new TSpirvRequirement;
101 for (auto extension : spirvReq->extensions)
102 spirvRequirement->extensions.insert(extension);
104 for (auto capability : spirvReq->capabilities)
105 spirvRequirement->capabilities.insert(capability);
109 // Handle SPIR-V execution modes
111 void TIntermediate::insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args)
113 if (!spirvExecutionMode)
114 spirvExecutionMode = new TSpirvExecutionMode;
116 TVector<const TIntermConstantUnion*> extraOperands;
118 for (auto arg : args->getSequence()) {
119 auto extraOperand = arg->getAsConstantUnion();
120 assert(extraOperand != nullptr);
121 extraOperands.push_back(extraOperand);
124 spirvExecutionMode->modes[executionMode] = extraOperands;
127 void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args)
129 if (!spirvExecutionMode)
130 spirvExecutionMode = new TSpirvExecutionMode;
133 TVector<const TIntermConstantUnion*> extraOperands;
135 for (auto arg : args->getSequence()) {
136 auto extraOperand = arg->getAsConstantUnion();
137 assert(extraOperand != nullptr);
138 extraOperands.push_back(extraOperand);
140 spirvExecutionMode->modeIds[executionMode] = extraOperands;
144 // Handle SPIR-V decorate qualifiers
146 void TQualifier::setSpirvDecorate(int decoration, const TIntermAggregate* args)
149 spirvDecorate = new TSpirvDecorate;
151 TVector<const TIntermConstantUnion*> extraOperands;
153 for (auto arg : args->getSequence()) {
154 auto extraOperand = arg->getAsConstantUnion();
155 assert(extraOperand != nullptr);
156 extraOperands.push_back(extraOperand);
159 spirvDecorate->decorates[decoration] = extraOperands;
162 void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args)
165 spirvDecorate = new TSpirvDecorate;
168 TVector<const TIntermConstantUnion*> extraOperands;
169 for (auto arg : args->getSequence()) {
170 auto extraOperand = arg->getAsConstantUnion();
171 assert(extraOperand != nullptr);
172 extraOperands.push_back(extraOperand);
174 spirvDecorate->decorateIds[decoration] = extraOperands;
177 void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args)
180 spirvDecorate = new TSpirvDecorate;
183 TVector<const TIntermConstantUnion*> extraOperands;
184 for (auto arg : args->getSequence()) {
185 auto extraOperand = arg->getAsConstantUnion();
186 assert(extraOperand != nullptr);
187 extraOperands.push_back(extraOperand);
189 spirvDecorate->decorateStrings[decoration] = extraOperands;
192 TString TQualifier::getSpirvDecorateQualifierString() const
194 assert(spirvDecorate);
196 TString qualifierString;
198 const auto appendFloat = [&](float f) { qualifierString.append(std::to_string(f).c_str()); };
199 const auto appendInt = [&](int i) { qualifierString.append(std::to_string(i).c_str()); };
200 const auto appendUint = [&](unsigned int u) { qualifierString.append(std::to_string(u).c_str()); };
201 const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
202 const auto appendStr = [&](const char* s) { qualifierString.append(s); };
204 const auto appendDecorate = [&](const TIntermConstantUnion* constant) {
205 if (constant->getBasicType() == EbtFloat) {
206 float value = static_cast<float>(constant->getConstArray()[0].getDConst());
209 else if (constant->getBasicType() == EbtInt) {
210 int value = constant->getConstArray()[0].getIConst();
213 else if (constant->getBasicType() == EbtUint) {
214 unsigned value = constant->getConstArray()[0].getUConst();
217 else if (constant->getBasicType() == EbtBool) {
218 bool value = constant->getConstArray()[0].getBConst();
221 else if (constant->getBasicType() == EbtString) {
222 const TString* value = constant->getConstArray()[0].getSConst();
223 appendStr(value->c_str());
229 for (auto& decorate : spirvDecorate->decorates) {
230 appendStr("spirv_decorate(");
231 appendInt(decorate.first);
232 for (auto extraOperand : decorate.second) {
234 appendDecorate(extraOperand);
239 for (auto& decorateId : spirvDecorate->decorateIds) {
240 appendStr("spirv_decorate_id(");
241 appendInt(decorateId.first);
242 for (auto extraOperand : decorateId.second) {
244 appendDecorate(extraOperand);
249 for (auto& decorateString : spirvDecorate->decorateStrings) {
250 appendStr("spirv_decorate_string(");
251 appendInt(decorateString.first);
252 for (auto extraOperand : decorateString.second) {
254 appendDecorate(extraOperand);
259 return qualifierString;
263 // Handle SPIR-V type specifiers
265 void TPublicType::setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams)
268 spirvType = new TSpirvType;
270 basicType = EbtSpirvType;
271 spirvType->spirvInst = spirvInst;
273 spirvType->typeParams = *typeParams;
276 TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant)
278 TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
279 if (constant->getBasicType() != EbtFloat &&
280 constant->getBasicType() != EbtInt &&
281 constant->getBasicType() != EbtUint &&
282 constant->getBasicType() != EbtBool &&
283 constant->getBasicType() != EbtString)
284 error(loc, "this type not allowed", constant->getType().getBasicString(), "");
287 spirvTypeParams->push_back(TSpirvTypeParameter(constant));
290 return spirvTypeParams;
293 TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TPublicType& type)
295 TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
296 spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type)));
297 return spirvTypeParams;
300 TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
302 // Merge SPIR-V type parameters of the second one to the first one
303 for (const auto& spirvTypeParam : *spirvTypeParams2)
304 spirvTypeParams1->push_back(spirvTypeParam);
305 return spirvTypeParams1;
309 // Handle SPIR-V instruction qualifiers
311 TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value)
313 TSpirvInstruction* spirvInst = new TSpirvInstruction;
315 spirvInst->set = value;
317 error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
322 TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value)
324 TSpirvInstruction* spirvInstuction = new TSpirvInstruction;
326 spirvInstuction->id = value;
328 error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), "");
330 return spirvInstuction;
333 TSpirvInstruction* TParseContext::mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, TSpirvInstruction* spirvInst2)
335 // Merge qualifiers of the second SPIR-V instruction to those of the first one
336 if (!spirvInst2->set.empty()) {
337 if (spirvInst1->set.empty())
338 spirvInst1->set = spirvInst2->set;
340 error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(set)");
343 if (spirvInst2->id != -1) {
344 if (spirvInst1->id == -1)
345 spirvInst1->id = spirvInst2->id;
347 error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(id)");
353 } // end namespace glslang
355 #endif // GLSLANG_WEB