1 //
2 // Copyright 2020 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "pxr/imaging/hgiGL/shaderGenerator.h"
26 #include "pxr/imaging/hgi/tokens.h"
27
28 PXR_NAMESPACE_OPEN_SCOPE
29
30 static const std::string &
_GetMacroBlob()31 _GetMacroBlob()
32 {
33 // Allows metal and GL to both handle out function params.
34 // On the metal side, the ref(space,type) parameter defines
35 // if items are in device or thread domain.
36 const static std::string header =
37 "#define REF(space,type) inout type\n";
38 return header;
39 }
40
HgiGLShaderGenerator(const HgiShaderFunctionDesc & descriptor)41 HgiGLShaderGenerator::HgiGLShaderGenerator(
42 const HgiShaderFunctionDesc &descriptor)
43 : HgiShaderGenerator(descriptor)
44 {
45 //Write out all GL shaders and add to shader sections
46 GetShaderSections()->push_back(
47 std::make_unique<HgiGLMacroShaderSection>(
48 _GetMacroBlob(), ""));
49
50 _WriteTextures(descriptor.textures);
51 _WriteBuffers(descriptor.buffers);
52 _WriteInOuts(descriptor.stageInputs, "in");
53 _WriteConstantParams(descriptor.constantParams);
54 _WriteInOuts(descriptor.stageOutputs, "out");
55 }
56
57 void
_WriteTextures(const HgiShaderFunctionTextureDescVector & textures)58 HgiGLShaderGenerator::_WriteTextures(
59 const HgiShaderFunctionTextureDescVector &textures)
60 {
61 //Extract texture descriptors and add appropriate texture sections
62 for(size_t i=0; i<textures.size(); i++) {
63 const HgiShaderFunctionTextureDesc &textureDescription = textures[i];
64 const HgiShaderSectionAttributeVector attrs = {
65 HgiShaderSectionAttribute{"binding", std::to_string(i)}};
66
67 GetShaderSections()->push_back(
68 std::make_unique<HgiGLTextureShaderSection>(
69 textureDescription.nameInShader,
70 i,
71 textureDescription.dimensions,
72 textureDescription.format,
73 attrs));
74 }
75 }
76
77 void
_WriteBuffers(const HgiShaderFunctionBufferDescVector & buffers)78 HgiGLShaderGenerator::_WriteBuffers(
79 const HgiShaderFunctionBufferDescVector &buffers)
80 {
81 //Extract buffer descriptors and add appropriate buffer sections
82 for(size_t i=0; i<buffers.size(); i++) {
83 const HgiShaderFunctionBufferDesc &bufferDescription = buffers[i];
84 const HgiShaderSectionAttributeVector attrs = {
85 HgiShaderSectionAttribute{"std430", ""},
86 HgiShaderSectionAttribute{"binding", std::to_string(i + 1)}};
87
88 GetShaderSections()->push_back(
89 std::make_unique<HgiGLBufferShaderSection>(
90 bufferDescription.nameInShader,
91 i + 1,
92 bufferDescription.type,
93 attrs));
94 }
95 }
96
97 void
_WriteConstantParams(const HgiShaderFunctionParamDescVector & parameters)98 HgiGLShaderGenerator::_WriteConstantParams(
99 const HgiShaderFunctionParamDescVector ¶meters)
100 {
101 if (parameters.size() < 1) {
102 return;
103 }
104 GetShaderSections()->push_back(
105 std::make_unique<HgiGLBlockShaderSection>(
106 "ParamBuffer",
107 parameters,
108 0));
109 }
110
111 void
_WriteInOuts(const HgiShaderFunctionParamDescVector & parameters,const std::string & qualifier)112 HgiGLShaderGenerator::_WriteInOuts(
113 const HgiShaderFunctionParamDescVector ¶meters,
114 const std::string &qualifier)
115 {
116 uint32_t counter = 0;
117
118 //To unify glslfx across different apis, other apis
119 //may want these to be defined, but since they are
120 //taken in opengl we ignore them
121 const static std::set<std::string> takenOutParams {
122 "gl_Position",
123 "gl_FragColor",
124 "gl_FragDepth"
125 };
126 const static std::map<std::string, std::string> takenInParams {
127 { HgiShaderKeywordTokens->hdPosition, "gl_Position"},
128 { HgiShaderKeywordTokens->hdGlobalInvocationID, "gl_GlobalInvocationID"}
129 };
130
131 const bool in_qualifier = qualifier == "in";
132 const bool out_qualifier = qualifier == "out";
133 for(const HgiShaderFunctionParamDesc ¶m : parameters) {
134 //Skip writing out taken parameter names
135 const std::string ¶mName = param.nameInShader;
136 if (out_qualifier &&
137 takenOutParams.find(paramName) != takenOutParams.end()) {
138 continue;
139 }
140 if (in_qualifier) {
141 const std::string &role = param.role;
142 auto const& keyword = takenInParams.find(role);
143 if (keyword != takenInParams.end()) {
144 GetShaderSections()->push_back(
145 std::make_unique<HgiGLKeywordShaderSection>(
146 paramName,
147 param.type,
148 keyword->second));
149 continue;
150 }
151 }
152
153 const HgiShaderSectionAttributeVector attrs {
154 HgiShaderSectionAttribute{"location", std::to_string(counter)}
155 };
156
157 GetShaderSections()->push_back(
158 std::make_unique<HgiGLMemberShaderSection>(
159 paramName,
160 param.type,
161 attrs,
162 qualifier));
163 counter++;
164 }
165 }
166
167 void
_Execute(std::ostream & ss,const std::string & originalShaderShader)168 HgiGLShaderGenerator::_Execute(
169 std::ostream &ss,
170 const std::string &originalShaderShader)
171 {
172 ss << _GetVersion() << " \n";
173
174 HgiGLShaderSectionUniquePtrVector* shaderSections = GetShaderSections();
175 //For all shader sections, visit the areas defined for all
176 //shader apis. We assume all shader apis have a global space
177 //section, capabilities to define macros in global space,
178 //and abilities to declare some members or functions there
179
180 for (const std::unique_ptr<HgiGLShaderSection>
181 &shaderSection : *shaderSections) {
182 shaderSection->VisitGlobalIncludes(ss);
183 ss << "\n";
184 }
185
186 for (const std::unique_ptr<HgiGLShaderSection>
187 &shaderSection : *shaderSections) {
188 shaderSection->VisitGlobalMacros(ss);
189 ss << "\n";
190 }
191
192 for (const std::unique_ptr<HgiGLShaderSection>
193 &shaderSection : *shaderSections) {
194 shaderSection->VisitGlobalStructs(ss);
195 ss << "\n";
196 }
197
198 for (const std::unique_ptr<HgiGLShaderSection>
199 &shaderSection : *shaderSections) {
200 shaderSection->VisitGlobalMemberDeclarations(ss);
201 ss << "\n";
202 }
203
204 for (const std::unique_ptr<HgiGLShaderSection>
205 &shaderSection : *shaderSections) {
206 shaderSection->VisitGlobalFunctionDefinitions(ss);
207 ss << "\n";
208 }
209
210 ss << "\n";
211 const char* cstr = originalShaderShader.c_str();
212
213 //write all the original shader except the version string
214 ss.write(
215 cstr + _GetVersion().length(),
216 originalShaderShader.length() - _GetVersion().length());
217 }
218
219 HgiGLShaderSectionUniquePtrVector*
GetShaderSections()220 HgiGLShaderGenerator::GetShaderSections()
221 {
222 return &_shaderSections;
223 }
224
225 PXR_NAMESPACE_CLOSE_SCOPE
226