FFmpeg  4.3.6
glslang.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <pthread.h>
20 
21 extern "C" {
22 #include "libavutil/mem.h"
23 #include "libavutil/avassert.h"
24 }
25 
26 #include <glslang/Include/ResourceLimits.h>
27 #include <glslang/Include/revision.h>
28 #include <glslang/Public/ShaderLang.h>
29 #include <glslang/SPIRV/GlslangToSpv.h>
30 
31 #include "glslang.h"
32 
33 using namespace glslang;
34 
36 static int glslang_refcount = 0;
37 
38 /* We require Vulkan 1.1 */
39 #define GLSL_VERSION EShTargetVulkan_1_1
40 
41 /* Vulkan 1.1 implementations require SPIR-V 1.3 to be implemented */
42 #define SPIRV_VERSION EShTargetSpv_1_3
43 
44 // Taken from glslang's examples, which apparently generally bases the choices
45 // on OpenGL specification limits
46 static const TBuiltInResource DefaultTBuiltInResource = {
47  /* .MaxLights = */ 32,
48  /* .MaxClipPlanes = */ 6,
49  /* .MaxTextureUnits = */ 32,
50  /* .MaxTextureCoords = */ 32,
51  /* .MaxVertexAttribs = */ 64,
52  /* .MaxVertexUniformComponents = */ 4096,
53  /* .MaxVaryingFloats = */ 64,
54  /* .MaxVertexTextureImageUnits = */ 32,
55  /* .MaxCombinedTextureImageUnits = */ 80,
56  /* .MaxTextureImageUnits = */ 32,
57  /* .MaxFragmentUniformComponents = */ 4096,
58  /* .MaxDrawBuffers = */ 32,
59  /* .MaxVertexUniformVectors = */ 128,
60  /* .MaxVaryingVectors = */ 8,
61  /* .MaxFragmentUniformVectors = */ 16,
62  /* .MaxVertexOutputVectors = */ 16,
63  /* .MaxFragmentInputVectors = */ 15,
64  /* .MinProgramTexelOffset = */ -8,
65  /* .MaxProgramTexelOffset = */ 7,
66  /* .MaxClipDistances = */ 8,
67  /* .MaxComputeWorkGroupCountX = */ 65535,
68  /* .MaxComputeWorkGroupCountY = */ 65535,
69  /* .MaxComputeWorkGroupCountZ = */ 65535,
70  /* .MaxComputeWorkGroupSizeX = */ 1024,
71  /* .MaxComputeWorkGroupSizeY = */ 1024,
72  /* .MaxComputeWorkGroupSizeZ = */ 64,
73  /* .MaxComputeUniformComponents = */ 1024,
74  /* .MaxComputeTextureImageUnits = */ 16,
75  /* .MaxComputeImageUniforms = */ 8,
76  /* .MaxComputeAtomicCounters = */ 8,
77  /* .MaxComputeAtomicCounterBuffers = */ 1,
78  /* .MaxVaryingComponents = */ 60,
79  /* .MaxVertexOutputComponents = */ 64,
80  /* .MaxGeometryInputComponents = */ 64,
81  /* .MaxGeometryOutputComponents = */ 128,
82  /* .MaxFragmentInputComponents = */ 128,
83  /* .MaxImageUnits = */ 8,
84  /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
85  /* .MaxCombinedShaderOutputResources = */ 8,
86  /* .MaxImageSamples = */ 0,
87  /* .MaxVertexImageUniforms = */ 0,
88  /* .MaxTessControlImageUniforms = */ 0,
89  /* .MaxTessEvaluationImageUniforms = */ 0,
90  /* .MaxGeometryImageUniforms = */ 0,
91  /* .MaxFragmentImageUniforms = */ 8,
92  /* .MaxCombinedImageUniforms = */ 8,
93  /* .MaxGeometryTextureImageUnits = */ 16,
94  /* .MaxGeometryOutputVertices = */ 256,
95  /* .MaxGeometryTotalOutputComponents = */ 1024,
96  /* .MaxGeometryUniformComponents = */ 1024,
97  /* .MaxGeometryVaryingComponents = */ 64,
98  /* .MaxTessControlInputComponents = */ 128,
99  /* .MaxTessControlOutputComponents = */ 128,
100  /* .MaxTessControlTextureImageUnits = */ 16,
101  /* .MaxTessControlUniformComponents = */ 1024,
102  /* .MaxTessControlTotalOutputComponents = */ 4096,
103  /* .MaxTessEvaluationInputComponents = */ 128,
104  /* .MaxTessEvaluationOutputComponents = */ 128,
105  /* .MaxTessEvaluationTextureImageUnits = */ 16,
106  /* .MaxTessEvaluationUniformComponents = */ 1024,
107  /* .MaxTessPatchComponents = */ 120,
108  /* .MaxPatchVertices = */ 32,
109  /* .MaxTessGenLevel = */ 64,
110  /* .MaxViewports = */ 16,
111  /* .MaxVertexAtomicCounters = */ 0,
112  /* .MaxTessControlAtomicCounters = */ 0,
113  /* .MaxTessEvaluationAtomicCounters = */ 0,
114  /* .MaxGeometryAtomicCounters = */ 0,
115  /* .MaxFragmentAtomicCounters = */ 8,
116  /* .MaxCombinedAtomicCounters = */ 8,
117  /* .MaxAtomicCounterBindings = */ 1,
118  /* .MaxVertexAtomicCounterBuffers = */ 0,
119  /* .MaxTessControlAtomicCounterBuffers = */ 0,
120  /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
121  /* .MaxGeometryAtomicCounterBuffers = */ 0,
122  /* .MaxFragmentAtomicCounterBuffers = */ 1,
123  /* .MaxCombinedAtomicCounterBuffers = */ 1,
124  /* .MaxAtomicCounterBufferSize = */ 16384,
125  /* .MaxTransformFeedbackBuffers = */ 4,
126  /* .MaxTransformFeedbackInterleavedComponents = */ 64,
127  /* .MaxCullDistances = */ 8,
128  /* .MaxCombinedClipAndCullDistances = */ 8,
129  /* .MaxSamples = */ 4,
130  /* .maxMeshOutputVerticesNV = */ 256,
131  /* .maxMeshOutputPrimitivesNV = */ 512,
132  /* .maxMeshWorkGroupSizeX_NV = */ 32,
133  /* .maxMeshWorkGroupSizeY_NV = */ 1,
134  /* .maxMeshWorkGroupSizeZ_NV = */ 1,
135  /* .maxTaskWorkGroupSizeX_NV = */ 32,
136  /* .maxTaskWorkGroupSizeY_NV = */ 1,
137  /* .maxTaskWorkGroupSizeZ_NV = */ 1,
138  /* .maxMeshViewCountNV = */ 4,
139 
140  .limits = {
141  /* .nonInductiveForLoops = */ 1,
142  /* .whileLoops = */ 1,
143  /* .doWhileLoops = */ 1,
144  /* .generalUniformIndexing = */ 1,
145  /* .generalAttributeMatrixVectorIndexing = */ 1,
146  /* .generalVaryingIndexing = */ 1,
147  /* .generalSamplerIndexing = */ 1,
148  /* .generalVariableIndexing = */ 1,
149  /* .generalConstantMatrixVectorIndexing = */ 1,
150  }
151 };
152 
153 GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage)
154 {
155  GLSlangResult *res = (GLSlangResult *)av_mallocz(sizeof(*res));
156  if (!res)
157  return NULL;
158 
159  static const EShLanguage lang[] = {
160  [GLSLANG_VERTEX] = EShLangVertex,
161  [GLSLANG_FRAGMENT] = EShLangFragment,
162  [GLSLANG_COMPUTE] = EShLangCompute,
163  };
164 
165  assert(glslang_refcount);
166  TShader *shader = new TShader(lang[stage]);
167  if (!shader) {
168  res->rval = AVERROR(ENOMEM);
169  return res;
170  }
171 
172  shader->setEnvClient(EShClientVulkan, GLSL_VERSION);
173  shader->setEnvTarget(EShTargetSpv, SPIRV_VERSION);
174  shader->setStrings(&glsl, 1);
175  if (!shader->parse(&DefaultTBuiltInResource, GLSL_VERSION, true, EShMsgDefault)) {
176  res->error_msg = av_strdup(shader->getInfoLog());
177  res->rval = AVERROR_EXTERNAL;
178  delete shader;
179  return res;
180  }
181 
182  TProgram *prog = new TProgram();
183  if (!prog) {
184  res->rval = AVERROR(ENOMEM);
185  delete shader;
186  return res;
187  }
188 
189  prog->addShader(shader);
190  if (!prog->link(EShMsgDefault)) {
191  res->error_msg = av_strdup(prog->getInfoLog());
192  res->rval = AVERROR_EXTERNAL;
193  delete shader;
194  delete prog;
195  return res;
196  }
197 
198  std::vector<unsigned int> spirv; /* Result */
199 
200  SpvOptions options; /* Options - by default all optimizations are off */
201  options.generateDebugInfo = false; /* Makes sense for files but not here */
202  options.disassemble = false; /* Will print disassembly on compilation */
203  options.validate = false; /* Validates the generated SPIRV, unneeded */
204  options.disableOptimizer = false; /* For debugging */
205  options.optimizeSize = true; /* Its faster */
206 
207  GlslangToSpv(*prog->getIntermediate(lang[stage]), spirv, NULL, &options);
208 
209  res->size = spirv.size()*sizeof(unsigned int);
210  res->data = av_memdup(spirv.data(), res->size);
211  if (!res->data) {
212  res->rval = AVERROR(ENOMEM);
213  delete shader;
214  delete prog;
215  return res;
216  }
217 
218  delete shader;
219  delete prog;
220 
221  return res;
222 }
223 
224 int glslang_init(void)
225 {
226  int ret = 0;
227 
229  if (glslang_refcount++ == 0)
230  ret = !InitializeProcess();
232 
233  return ret;
234 }
235 
236 void glslang_uninit(void)
237 {
240  if (--glslang_refcount == 0)
241  FinalizeProcess();
243 }
#define SPIRV_VERSION
Definition: glslang.cpp:42
#define NULL
Definition: coverity.c:32
#define pthread_mutex_lock(a)
Definition: ffprobe.c:62
Memory handling functions.
static const TBuiltInResource DefaultTBuiltInResource
Definition: glslang.cpp:46
#define GLSL_VERSION
Definition: glslang.cpp:39
size_t size
Definition: glslang.h:36
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int glslang_init(void)
Definition: glslang.cpp:224
#define AVERROR(e)
Definition: error.h:43
simple assert() macros that are a bit more flexible than ISO C assert().
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:285
void glslang_uninit(void)
Definition: glslang.cpp:236
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:66
static pthread_mutex_t glslang_mutex
Definition: glslang.cpp:35
#define PTHREAD_MUTEX_INITIALIZER
Definition: os2threads.h:56
GLSlangResult * glslang_compile(const char *glsl, enum GLSlangStage stage)
Definition: glslang.cpp:153
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
static int glslang_refcount
Definition: glslang.cpp:36
void * data
Definition: glslang.h:35
GLSlangStage
Definition: glslang.h:39
int
const OptionDef options[]
Definition: ffmpeg_opt.c:3388
_fmutex pthread_mutex_t
Definition: os2threads.h:53
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
char * error_msg
Definition: glslang.h:33