• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "GLSLANG/ShaderLang.h"
2 
3 #include "angle_gl.h"
4 #include "ShaderTranslator.h"
5 
6 #include <assert.h>
7 #include <math.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sstream>
12 #include <vector>
13 #include <map>
14 #include <string>
15 
16 namespace {
17 
boolToUint(bool b)18 unsigned int boolToUint(bool b) {
19     return b ? 1 : 0;
20 }
21 
22 template<class S, class T>
toAllocedCArray(const S & xs)23 static T* toAllocedCArray(const S& xs) {
24     size_t bytes = sizeof(T) * xs.size();
25     T* res = (T *)malloc(bytes);
26     memset(res, 0, bytes);
27     memcpy(res, xs.data(), bytes);
28     return res;
29 }
30 
toAllocedCString(const std::string & str)31 static const char* toAllocedCString(const std::string& str) {
32     size_t bytes = sizeof(char) * str.size() + 1;
33     char* res = (char *)malloc(bytes);
34     memset(res, 0, bytes);
35     memcpy(res, str.data(), bytes);
36     return res;
37 }
38 
39 template <class T>
dupCArray(unsigned int count,const T * pItems)40 T* dupCArray(unsigned int count, const T* pItems) {
41     if (0 == count) return nullptr;
42 
43     size_t bytes = count * sizeof(T);
44     T* res = (T*)malloc(count * bytes);
45     memcpy(res, pItems, bytes);
46     return res;
47 }
48 
49 static void fillShaderVariable(const sh::ShaderVariable& var, ST_ShaderVariable* out);
50 static void fillInterfaceBlock(const sh::InterfaceBlock& ib, ST_InterfaceBlock* out);
51 
52 static ST_NameHashingMap* createNameHashingMap(const std::map<std::string, std::string>& inputMap);
53 static ST_ShaderVariable* createShaderVariableArray(const std::vector<sh::ShaderVariable>& inputVars);
54 static ST_InterfaceBlock* createInterfaceBlockArray(const std::vector<sh::InterfaceBlock>& inputBlocks);
55 
56 static void initShaderVariableInfo(
57     const std::vector<sh::ShaderVariable>* pInputs,
58     unsigned int* pCount,
59     ST_ShaderVariable** pOutputs);
60 
61 static void initInterfaceBlockInfo(
62     const std::vector<sh::InterfaceBlock>* pInputs,
63     unsigned int* pCount,
64     ST_InterfaceBlock** pOutputs);
65 
66 static std::vector<sh::ShaderVariable> getActiveVariables(
67     const std::vector<sh::ShaderVariable>* pInputs);
68 
69 static void freeNameHashingMap(ST_NameHashingMap* nameHashingMap);
70 static void destroyShaderVariable(ST_ShaderVariable* var);
71 static void freeShaderVariableArray(uint32_t count, ST_ShaderVariable* vars);
72 static void destroyInterfaceBlock(ST_InterfaceBlock* ib);
73 static void freeInterfaceBlockArray(uint32_t count, ST_InterfaceBlock* ibs);
74 
fillShaderVariable(const sh::ShaderVariable & var,ST_ShaderVariable * out)75 static void fillShaderVariable(const sh::ShaderVariable& var, ST_ShaderVariable* out) {
76     out->type = var.type;
77     out->precision = var.precision;
78 
79     out->name = toAllocedCString(var.name);
80     out->mappedName = toAllocedCString(var.mappedName);
81 
82     out->arraySizeCount = (uint32_t)var.arraySizes.size();
83     out->pArraySizes = toAllocedCArray<std::vector<unsigned int>, unsigned int>(var.arraySizes);
84 
85     out->staticUse = boolToUint(var.staticUse);
86     out->active = boolToUint(var.active);
87 
88     out->fieldsCount = (uint32_t)var.fields.size();
89     out->pFields = toAllocedCArray<std::vector<sh::ShaderVariable>, ST_ShaderVariable>(var.fields);
90     for (uint32_t i = 0; i < out->fieldsCount; ++i) {
91         fillShaderVariable(var.fields[i], out->pFields + i);
92     }
93 
94     out->structName = toAllocedCString(var.structName);
95 
96     out->isRowMajorLayout = boolToUint(var.isRowMajorLayout);
97 
98     out->location = var.location;
99 
100     out->binding = var.binding;
101 
102     out->imageUnitFormat = var.imageUnitFormat;
103     out->offset = var.offset;
104     out->readonly = boolToUint(var.readonly);
105     out->writeonly = boolToUint(var.writeonly);
106 
107     out->index = var.index;
108 
109     out->interpolation = (ST_InterpolationType)(var.interpolation);
110     out->isInvariant = boolToUint(var.isInvariant);
111 
112     out->flattenedOffsetInParentArrays = var.parentArrayIndex();
113 }
114 
fillInterfaceBlock(const sh::InterfaceBlock & ib,ST_InterfaceBlock * out)115 static void fillInterfaceBlock(const sh::InterfaceBlock& ib, ST_InterfaceBlock* out) {
116     out->name = toAllocedCString(ib.name);
117     out->mappedName = toAllocedCString(ib.mappedName);
118     out->instanceName = toAllocedCString(ib.mappedName);
119 
120     out->arraySize = ib.arraySize;
121     out->layout = (ST_BlockLayoutType)ib.layout;
122 
123     out->isRowMajorLayout = boolToUint(ib.isRowMajorLayout);
124 
125     out->binding = ib.binding;
126     out->staticUse = boolToUint(ib.staticUse);
127     out->active = boolToUint(ib.active);
128     out->blockType = (ST_BlockType)ib.blockType;
129 
130     out->fieldsCount = (uint32_t)ib.fields.size();
131     out->pFields = toAllocedCArray<std::vector<sh::ShaderVariable>, ST_ShaderVariable>(ib.fields);
132     for (uint32_t i = 0; i < out->fieldsCount; ++i) {
133         fillShaderVariable(ib.fields[i], out->pFields + i);
134     }
135 }
136 
createNameHashingMap(const std::map<std::string,std::string> & inputMap)137 static ST_NameHashingMap* createNameHashingMap(const std::map<std::string, std::string>& inputMap) {
138     size_t elements = inputMap.size();
139 
140     const char** ppUserNames = (const char**)malloc(elements * sizeof(const char*));
141     const char** ppCompiledNames = (const char**)malloc(elements * sizeof(const char* const*));
142     size_t i = 0;
143 
144     for (auto it : inputMap) {
145         ppUserNames[i] = toAllocedCString(it.first);
146         ppCompiledNames[i] = toAllocedCString(it.second);
147         ++i;
148     }
149 
150     ST_NameHashingMap* res = (ST_NameHashingMap*)(malloc(sizeof(ST_NameHashingMap)));
151 
152     res->entryCount = (uint32_t)elements;
153     res->ppUserNames = ppUserNames;
154     res->ppCompiledNames = ppCompiledNames;
155 
156     return res;
157 }
158 
159 
createShaderVariableArray(const std::vector<sh::ShaderVariable> & inputVars)160 static ST_ShaderVariable* createShaderVariableArray(const std::vector<sh::ShaderVariable>& inputVars) {
161     ST_ShaderVariable* res =
162         toAllocedCArray<std::vector<sh::ShaderVariable>, ST_ShaderVariable>(inputVars);
163     for (size_t i = 0; i < inputVars.size(); ++i) {
164         fillShaderVariable(inputVars[i], res + i);
165     }
166     return res;
167 }
168 
createInterfaceBlockArray(const std::vector<sh::InterfaceBlock> & inputBlocks)169 static ST_InterfaceBlock* createInterfaceBlockArray(const std::vector<sh::InterfaceBlock>& inputBlocks) {
170     ST_InterfaceBlock* res =
171         toAllocedCArray<std::vector<sh::InterfaceBlock>, ST_InterfaceBlock>(inputBlocks);
172     for (size_t i = 0; i < inputBlocks.size(); ++i) {
173         fillInterfaceBlock(inputBlocks[i], res + i);
174     }
175     return res;
176 }
177 
initShaderVariableInfo(const std::vector<sh::ShaderVariable> * pInputs,unsigned int * pCount,ST_ShaderVariable ** pOutputs)178 static void initShaderVariableInfo(
179     const std::vector<sh::ShaderVariable>* pInputs,
180     unsigned int* pCount,
181     ST_ShaderVariable** pOutputs) {
182     *pCount = pInputs->size();
183     *pOutputs = createShaderVariableArray(*pInputs);
184 }
185 
initInterfaceBlockInfo(const std::vector<sh::InterfaceBlock> * pInputs,unsigned int * pCount,ST_InterfaceBlock ** pOutputs)186 static void initInterfaceBlockInfo(
187     const std::vector<sh::InterfaceBlock>* pInputs,
188     unsigned int* pCount,
189     ST_InterfaceBlock** pOutputs) {
190     *pCount = pInputs->size();
191     *pOutputs = createInterfaceBlockArray(*pInputs);
192 }
193 
getActiveVariables(const std::vector<sh::ShaderVariable> * pInputs)194 static std::vector<sh::ShaderVariable> getActiveVariables(
195     const std::vector<sh::ShaderVariable>* pInputs) {
196     std::vector<sh::ShaderVariable> activeVars;
197     for (const auto& var: *pInputs) {
198         if (var.active) {
199             activeVars.push_back(var);
200         }
201     }
202     return activeVars;
203 }
204 
freeShaderVariableArray(uint32_t count,ST_ShaderVariable * vars)205 static void freeShaderVariableArray(uint32_t count, ST_ShaderVariable* vars) {
206     for (uint32_t i = 0; i < count; ++i) {
207         destroyShaderVariable(vars + i);
208     }
209     free(vars);
210 }
211 
freeInterfaceBlockArray(uint32_t count,ST_InterfaceBlock * ibs)212 static void freeInterfaceBlockArray(uint32_t count, ST_InterfaceBlock* ibs) {
213     for (uint32_t i = 0; i < count; ++i) {
214         destroyInterfaceBlock(ibs + i);
215     }
216     free(ibs);
217 }
218 
freeNameHashingMap(ST_NameHashingMap * nameHashingMap)219 static void freeNameHashingMap(ST_NameHashingMap* nameHashingMap) {
220     for (uint32_t i = 0; i < nameHashingMap->entryCount; ++i) {
221         free((void*)nameHashingMap->ppUserNames[i]);
222         free((void*)nameHashingMap->ppCompiledNames[i]);
223     }
224 
225     free((void*)nameHashingMap->ppUserNames);
226     free((void*)nameHashingMap->ppCompiledNames);
227 
228     free((void*)nameHashingMap);
229 }
230 
destroyShaderVariable(ST_ShaderVariable * var)231 static void destroyShaderVariable(ST_ShaderVariable* var) {
232     free((void*)var->name);
233     free((void*)var->mappedName);
234 
235     free((void*)var->pArraySizes);
236     freeShaderVariableArray(var->fieldsCount, var->pFields);
237 
238     free((void*)var->structName);
239 }
240 
destroyInterfaceBlock(ST_InterfaceBlock * ib)241 static void destroyInterfaceBlock(ST_InterfaceBlock* ib) {
242     free((void*)ib->name);
243     free((void*)ib->mappedName);
244     free((void*)ib->instanceName);
245 
246     freeShaderVariableArray(ib->fieldsCount, ib->pFields);
247 }
248 
249 } // namespace
250 
251 extern "C" {
252 
STInitialize()253 ANGLE_EXPORT void STInitialize() {
254     sh::Initialize();
255 }
256 
STFinalize()257 ANGLE_EXPORT void STFinalize() {
258     sh::Finalize();
259 }
260 
261 ANGLE_EXPORT ST_BuiltInResources*
STGenerateResources(ST_BuiltInResources * pResources)262 STGenerateResources(ST_BuiltInResources *pResources) {
263     static_assert(sizeof(ST_BuiltInResources) == sizeof(ShBuiltInResources),
264         "mismatch in ST_BuiltInResources versus ShBuiltInResources");
265     sh::InitBuiltInResources(reinterpret_cast<ShBuiltInResources*>(pResources));
266     return pResources;
267 }
268 
STCompileAndResolve(const ST_ShaderCompileInfo * pInfo,ST_ShaderCompileResult ** ppResult)269 ANGLE_EXPORT void STCompileAndResolve(
270     const ST_ShaderCompileInfo* pInfo,
271     ST_ShaderCompileResult** ppResult) {
272 
273     ShHandle handle = reinterpret_cast<ShHandle>(pInfo->inputHandle);
274 
275     GLenum type = pInfo->type;
276     ST_ShaderSpec spec = pInfo->spec;
277     ST_ShaderOutput output = pInfo->output;
278     const ST_BuiltInResources* resources = pInfo->pResources;
279     const char* shaderString = pInfo->pShaderString;
280     ST_CompileOptions compileOptions = pInfo->compileOptions;
281 
282     if (!handle) {
283         handle =
284             sh::ConstructCompiler(
285                     type,
286                     static_cast<ShShaderSpec>(spec),
287                     static_cast<ShShaderOutput>(output),
288                     reinterpret_cast<const ShBuiltInResources*>(resources));
289     }
290 
291     (void)createNameHashingMap;
292     (void)createShaderVariableArray;
293     (void)createInterfaceBlockArray;
294 
295     bool compileResult =
296         sh::Compile(
297             static_cast<ShHandle>(handle),
298             &shaderString, 1,
299             static_cast<ST_CompileOptions>(compileOptions));
300 
301     ST_ShaderCompileResult* res =
302         (ST_ShaderCompileResult*)(malloc(sizeof(ST_ShaderCompileResult)));
303     memset(res, 0, sizeof(ST_ShaderCompileResult));
304 
305     res->outputHandle = handle;
306 
307     res->originalSource = strdup(shaderString);
308     res->translatedSource = toAllocedCString(sh::GetObjectCode(handle));
309     res->infoLog = toAllocedCString(sh::GetInfoLog(handle));
310 
311     res->version = sh::GetShaderVersion(handle);
312 
313     res->nameHashingMap = createNameHashingMap(*(sh::GetNameHashingMap(handle)));
314 
315     initShaderVariableInfo(
316         sh::GetUniforms(handle), &res->uniformsCount,
317         (ST_ShaderVariable**)&res->pUniforms);
318     initInterfaceBlockInfo(
319         sh::GetUniformBlocks(handle), &res->uniformBlocksCount,
320         (ST_InterfaceBlock**)&res->pUniformBlocks);
321     initInterfaceBlockInfo(
322         sh::GetShaderStorageBlocks(handle), &res->shaderStorageBlocksCount,
323         (ST_InterfaceBlock**)&res->pShaderStorageBlocks);
324 
325     const GLenum kShaderTypeVertex = 0x8b31;
326     const GLenum kShaderTypeFragment = 0x8b30;
327     const GLenum kShaderTypeCompute = 0x91b9;
328     const GLenum kShaderTypeGeometry = 0x8dd9;
329     const GLenum kShaderTypeTessControl = 0x8e88;
330     const GLenum kShaderTypeTessEval = 0x8e87;
331 
332     switch (type) {
333         case kShaderTypeVertex: {
334 
335             initShaderVariableInfo(
336                 sh::GetOutputVaryings(handle), &res->outputVaryingsCount,
337                 (ST_ShaderVariable**)&res->pOutputVaryings);
338             initShaderVariableInfo(
339                 sh::GetAttributes(handle), &res->allAttributesCount,
340                 (ST_ShaderVariable**)&res->pAllAttributes);
341 
342             std::vector<sh::ShaderVariable> activeAttribs =
343                 getActiveVariables(sh::GetAttributes(handle));
344             initShaderVariableInfo(
345                 &activeAttribs, &res->activeAttributesCount,
346                 (ST_ShaderVariable**)&res->pActiveAttributes);
347 
348             res->numViews = sh::GetVertexShaderNumViews(handle);
349             break;
350         }
351         case kShaderTypeFragment: {
352             initShaderVariableInfo(
353                 sh::GetAttributes(handle), &res->allAttributesCount,
354                 (ST_ShaderVariable**)&res->pAllAttributes);
355 
356             std::vector<sh::ShaderVariable> activeAttribs =
357                 getActiveVariables(sh::GetAttributes(handle));
358             initShaderVariableInfo(
359                 &activeAttribs, &res->activeAttributesCount,
360                 (ST_ShaderVariable**)&res->pActiveAttributes);
361 
362             // TODO(jmadill): These aren't sorted. Hope it works out?
363             initShaderVariableInfo(
364                 sh::GetInputVaryings(handle),
365                 &res->inputVaryingsCount,
366                 (ST_ShaderVariable**)&res->pInputVaryings);
367 
368             std::vector<sh::ShaderVariable> activeOutputVariables =
369                 getActiveVariables(sh::GetOutputVariables(handle));
370             initShaderVariableInfo(
371                 &activeOutputVariables, &res->activeOutputVariablesCount,
372                 (ST_ShaderVariable**)&res->pActiveOutputVariables);
373 
374             res->earlyFragmentTestsOptimization =
375                 boolToUint(sh::HasEarlyFragmentTestsOptimization(handle));
376             break;
377         }
378         case kShaderTypeCompute: {
379             initShaderVariableInfo(
380                 sh::GetAttributes(handle), &res->allAttributesCount,
381                 (ST_ShaderVariable**)&res->pAllAttributes);
382             std::vector<sh::ShaderVariable> activeAttribs =
383                 getActiveVariables(sh::GetAttributes(handle));
384             initShaderVariableInfo(
385                 &activeAttribs, &res->activeAttributesCount,
386                 (ST_ShaderVariable**)&res->pActiveAttributes);
387 
388             sh::WorkGroupSize size = sh::GetComputeShaderLocalGroupSize(handle);
389             res->workGroupSize.localSizeQualifiers[0] = size[0];
390             res->workGroupSize.localSizeQualifiers[1] = size[1];
391             res->workGroupSize.localSizeQualifiers[2] = size[2];
392 
393             res->sharedMemSize = sh::GetShaderSharedMemorySize(handle);
394             break;
395         }
396         case kShaderTypeGeometry: {
397             initShaderVariableInfo(
398                 sh::GetInputVaryings(handle),
399                 &res->inputVaryingsCount,
400                 (ST_ShaderVariable**)&res->pInputVaryings);
401             initShaderVariableInfo(
402                 sh::GetOutputVaryings(handle),
403                 &res->outputVaryingsCount,
404                 (ST_ShaderVariable**)&res->pOutputVaryings);
405 
406             if (sh::HasValidGeometryShaderInputPrimitiveType(handle)) {
407                 res->geometryShaderInputPrimitiveType =
408                     sh::GetGeometryShaderInputPrimitiveType(handle);
409             }
410 
411             if (sh::HasValidGeometryShaderOutputPrimitiveType(handle)) {
412                 res->geometryShaderOutputPrimitiveType =
413                     sh::GetGeometryShaderOutputPrimitiveType(handle);
414             }
415 
416             if (sh::HasValidGeometryShaderMaxVertices(handle)) {
417                 res->geometryShaderMaxVertices =
418                     sh::GetGeometryShaderMaxVertices(handle);
419             }
420 
421             res->geometryShaderInvocations =
422                 sh::GetGeometryShaderInvocations(handle);
423             break;
424         }
425         case kShaderTypeTessControl: { // TODO
426             break;
427         }
428         case kShaderTypeTessEval: { // TODO
429             break;
430         }
431         default:
432             fprintf(stderr, "%s: unknown shader type: 0x%x\n", __func__, type);
433             abort();
434             break;
435     }
436 
437     res->compileStatus = boolToUint(compileResult);
438     *ppResult = res;
439 
440     sh::ClearResults(handle);
441 }
442 
STFreeShaderResolveState(ST_ShaderCompileResult * state)443 ANGLE_EXPORT void STFreeShaderResolveState(
444     ST_ShaderCompileResult* state) {
445 
446     free((void*)state->originalSource);
447     free((void*)state->translatedSource);
448     free((void*)state->infoLog);
449 
450     freeNameHashingMap(state->nameHashingMap);
451 
452     freeShaderVariableArray(state->inputVaryingsCount, (ST_ShaderVariable*)state->pInputVaryings);
453     freeShaderVariableArray(state->outputVaryingsCount, (ST_ShaderVariable*)state->pOutputVaryings);
454     freeShaderVariableArray(state->uniformsCount, (ST_ShaderVariable*)state->pUniforms);
455 
456     freeInterfaceBlockArray(state->uniformBlocksCount, (ST_InterfaceBlock*)state->pUniformBlocks);
457     freeInterfaceBlockArray(state->shaderStorageBlocksCount, (ST_InterfaceBlock*)state->pShaderStorageBlocks);
458 
459     freeShaderVariableArray(state->activeAttributesCount, (ST_ShaderVariable*)state->pActiveAttributes);
460     freeShaderVariableArray(state->allAttributesCount, (ST_ShaderVariable*)state->pAllAttributes);
461 
462     freeShaderVariableArray(state->activeOutputVariablesCount, (ST_ShaderVariable*)state->pActiveOutputVariables);
463 
464     free((void*)state);
465 }
466 
STCopyVariable(const ST_ShaderVariable * pInput)467 ANGLE_EXPORT ST_ShaderVariable STCopyVariable(const ST_ShaderVariable* pInput) {
468     ST_ShaderVariable res = *pInput;
469 
470     if (pInput->name) res.name = strdup(pInput->name);
471     if (pInput->mappedName) res.mappedName = strdup(pInput->mappedName);
472 
473     res.pArraySizes = dupCArray(pInput->arraySizeCount, pInput->pArraySizes);
474     res.pFields = dupCArray(pInput->fieldsCount, pInput->pFields);
475 
476     for (unsigned int i = 0; i < res.fieldsCount; ++i) {
477         res.pFields[i] = STCopyVariable(pInput->pFields + i);
478     }
479 
480     if (pInput->structName) res.structName = strdup(pInput->structName);
481 
482     return res;
483 }
484 
STCopyInterfaceBlock(const ST_InterfaceBlock * pInput)485 ANGLE_EXPORT ST_InterfaceBlock STCopyInterfaceBlock(const ST_InterfaceBlock* pInput) {
486     ST_InterfaceBlock res = *pInput;
487 
488     if (pInput->name) res.name = strdup(pInput->name);
489     if (pInput->mappedName) res.mappedName = strdup(pInput->mappedName);
490     if (pInput->instanceName) res.instanceName = strdup(pInput->instanceName);
491 
492     res.pFields = dupCArray(pInput->fieldsCount, pInput->pFields);
493 
494     for (unsigned int i = 0; i < res.fieldsCount; ++i) {
495         res.pFields[i] = STCopyVariable(pInput->pFields + i);
496     }
497 
498     return res;
499 }
500 
STDestroyVariable(ST_ShaderVariable * pInput)501 ANGLE_EXPORT void STDestroyVariable(ST_ShaderVariable* pInput) {
502     destroyShaderVariable(pInput);
503 }
504 
STDestroyInterfaceBlock(ST_InterfaceBlock * pInput)505 ANGLE_EXPORT void STDestroyInterfaceBlock(ST_InterfaceBlock* pInput) {
506     destroyInterfaceBlock(pInput);
507 }
508 
509 } // extern "C"
510