You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
8.2KB

  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. #include <pthread.h>
  19. extern "C" {
  20. #include "libavutil/mem.h"
  21. #include "libavutil/avassert.h"
  22. }
  23. #include <glslang/Include/ResourceLimits.h>
  24. #include <glslang/Include/revision.h>
  25. #include <glslang/Public/ShaderLang.h>
  26. #include <glslang/SPIRV/GlslangToSpv.h>
  27. #include "glslang.h"
  28. using namespace glslang;
  29. static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER;
  30. static int glslang_refcount = 0;
  31. /* We require Vulkan 1.1 */
  32. #define GLSL_VERSION EShTargetVulkan_1_1
  33. /* Vulkan 1.1 implementations require SPIR-V 1.3 to be implemented */
  34. #define SPIRV_VERSION EShTargetSpv_1_3
  35. // Taken from glslang's examples, which apparently generally bases the choices
  36. // on OpenGL specification limits
  37. static const TBuiltInResource DefaultTBuiltInResource = {
  38. /* .MaxLights = */ 32,
  39. /* .MaxClipPlanes = */ 6,
  40. /* .MaxTextureUnits = */ 32,
  41. /* .MaxTextureCoords = */ 32,
  42. /* .MaxVertexAttribs = */ 64,
  43. /* .MaxVertexUniformComponents = */ 4096,
  44. /* .MaxVaryingFloats = */ 64,
  45. /* .MaxVertexTextureImageUnits = */ 32,
  46. /* .MaxCombinedTextureImageUnits = */ 80,
  47. /* .MaxTextureImageUnits = */ 32,
  48. /* .MaxFragmentUniformComponents = */ 4096,
  49. /* .MaxDrawBuffers = */ 32,
  50. /* .MaxVertexUniformVectors = */ 128,
  51. /* .MaxVaryingVectors = */ 8,
  52. /* .MaxFragmentUniformVectors = */ 16,
  53. /* .MaxVertexOutputVectors = */ 16,
  54. /* .MaxFragmentInputVectors = */ 15,
  55. /* .MinProgramTexelOffset = */ -8,
  56. /* .MaxProgramTexelOffset = */ 7,
  57. /* .MaxClipDistances = */ 8,
  58. /* .MaxComputeWorkGroupCountX = */ 65535,
  59. /* .MaxComputeWorkGroupCountY = */ 65535,
  60. /* .MaxComputeWorkGroupCountZ = */ 65535,
  61. /* .MaxComputeWorkGroupSizeX = */ 1024,
  62. /* .MaxComputeWorkGroupSizeY = */ 1024,
  63. /* .MaxComputeWorkGroupSizeZ = */ 64,
  64. /* .MaxComputeUniformComponents = */ 1024,
  65. /* .MaxComputeTextureImageUnits = */ 16,
  66. /* .MaxComputeImageUniforms = */ 8,
  67. /* .MaxComputeAtomicCounters = */ 8,
  68. /* .MaxComputeAtomicCounterBuffers = */ 1,
  69. /* .MaxVaryingComponents = */ 60,
  70. /* .MaxVertexOutputComponents = */ 64,
  71. /* .MaxGeometryInputComponents = */ 64,
  72. /* .MaxGeometryOutputComponents = */ 128,
  73. /* .MaxFragmentInputComponents = */ 128,
  74. /* .MaxImageUnits = */ 8,
  75. /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
  76. /* .MaxCombinedShaderOutputResources = */ 8,
  77. /* .MaxImageSamples = */ 0,
  78. /* .MaxVertexImageUniforms = */ 0,
  79. /* .MaxTessControlImageUniforms = */ 0,
  80. /* .MaxTessEvaluationImageUniforms = */ 0,
  81. /* .MaxGeometryImageUniforms = */ 0,
  82. /* .MaxFragmentImageUniforms = */ 8,
  83. /* .MaxCombinedImageUniforms = */ 8,
  84. /* .MaxGeometryTextureImageUnits = */ 16,
  85. /* .MaxGeometryOutputVertices = */ 256,
  86. /* .MaxGeometryTotalOutputComponents = */ 1024,
  87. /* .MaxGeometryUniformComponents = */ 1024,
  88. /* .MaxGeometryVaryingComponents = */ 64,
  89. /* .MaxTessControlInputComponents = */ 128,
  90. /* .MaxTessControlOutputComponents = */ 128,
  91. /* .MaxTessControlTextureImageUnits = */ 16,
  92. /* .MaxTessControlUniformComponents = */ 1024,
  93. /* .MaxTessControlTotalOutputComponents = */ 4096,
  94. /* .MaxTessEvaluationInputComponents = */ 128,
  95. /* .MaxTessEvaluationOutputComponents = */ 128,
  96. /* .MaxTessEvaluationTextureImageUnits = */ 16,
  97. /* .MaxTessEvaluationUniformComponents = */ 1024,
  98. /* .MaxTessPatchComponents = */ 120,
  99. /* .MaxPatchVertices = */ 32,
  100. /* .MaxTessGenLevel = */ 64,
  101. /* .MaxViewports = */ 16,
  102. /* .MaxVertexAtomicCounters = */ 0,
  103. /* .MaxTessControlAtomicCounters = */ 0,
  104. /* .MaxTessEvaluationAtomicCounters = */ 0,
  105. /* .MaxGeometryAtomicCounters = */ 0,
  106. /* .MaxFragmentAtomicCounters = */ 8,
  107. /* .MaxCombinedAtomicCounters = */ 8,
  108. /* .MaxAtomicCounterBindings = */ 1,
  109. /* .MaxVertexAtomicCounterBuffers = */ 0,
  110. /* .MaxTessControlAtomicCounterBuffers = */ 0,
  111. /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
  112. /* .MaxGeometryAtomicCounterBuffers = */ 0,
  113. /* .MaxFragmentAtomicCounterBuffers = */ 1,
  114. /* .MaxCombinedAtomicCounterBuffers = */ 1,
  115. /* .MaxAtomicCounterBufferSize = */ 16384,
  116. /* .MaxTransformFeedbackBuffers = */ 4,
  117. /* .MaxTransformFeedbackInterleavedComponents = */ 64,
  118. /* .MaxCullDistances = */ 8,
  119. /* .MaxCombinedClipAndCullDistances = */ 8,
  120. /* .MaxSamples = */ 4,
  121. /* .maxMeshOutputVerticesNV = */ 256,
  122. /* .maxMeshOutputPrimitivesNV = */ 512,
  123. /* .maxMeshWorkGroupSizeX_NV = */ 32,
  124. /* .maxMeshWorkGroupSizeY_NV = */ 1,
  125. /* .maxMeshWorkGroupSizeZ_NV = */ 1,
  126. /* .maxTaskWorkGroupSizeX_NV = */ 32,
  127. /* .maxTaskWorkGroupSizeY_NV = */ 1,
  128. /* .maxTaskWorkGroupSizeZ_NV = */ 1,
  129. /* .maxMeshViewCountNV = */ 4,
  130. .limits = {
  131. /* .nonInductiveForLoops = */ 1,
  132. /* .whileLoops = */ 1,
  133. /* .doWhileLoops = */ 1,
  134. /* .generalUniformIndexing = */ 1,
  135. /* .generalAttributeMatrixVectorIndexing = */ 1,
  136. /* .generalVaryingIndexing = */ 1,
  137. /* .generalSamplerIndexing = */ 1,
  138. /* .generalVariableIndexing = */ 1,
  139. /* .generalConstantMatrixVectorIndexing = */ 1,
  140. }
  141. };
  142. GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage)
  143. {
  144. GLSlangResult *res = (GLSlangResult *)av_mallocz(sizeof(*res));
  145. if (!res)
  146. return NULL;
  147. static const EShLanguage lang[] = {
  148. [GLSLANG_VERTEX] = EShLangVertex,
  149. [GLSLANG_FRAGMENT] = EShLangFragment,
  150. [GLSLANG_COMPUTE] = EShLangCompute,
  151. };
  152. assert(glslang_refcount);
  153. TShader *shader = new TShader(lang[stage]);
  154. if (!shader) {
  155. res->rval = AVERROR(ENOMEM);
  156. return res;
  157. }
  158. shader->setEnvClient(EShClientVulkan, GLSL_VERSION);
  159. shader->setEnvTarget(EShTargetSpv, SPIRV_VERSION);
  160. shader->setStrings(&glsl, 1);
  161. if (!shader->parse(&DefaultTBuiltInResource, GLSL_VERSION, true, EShMsgDefault)) {
  162. res->error_msg = av_strdup(shader->getInfoLog());
  163. res->rval = AVERROR_EXTERNAL;
  164. delete shader;
  165. return res;
  166. }
  167. TProgram *prog = new TProgram();
  168. if (!prog) {
  169. res->rval = AVERROR(ENOMEM);
  170. delete shader;
  171. return res;
  172. }
  173. prog->addShader(shader);
  174. if (!prog->link(EShMsgDefault)) {
  175. res->error_msg = av_strdup(prog->getInfoLog());
  176. res->rval = AVERROR_EXTERNAL;
  177. delete shader;
  178. delete prog;
  179. return res;
  180. }
  181. std::vector<unsigned int> spirv; /* Result */
  182. SpvOptions options; /* Options - by default all optimizations are off */
  183. options.generateDebugInfo = false; /* Makes sense for files but not here */
  184. options.disassemble = false; /* Will print disassembly on compilation */
  185. options.validate = false; /* Validates the generated SPIRV, unneeded */
  186. options.disableOptimizer = false; /* For debugging */
  187. options.optimizeSize = true; /* Its faster */
  188. GlslangToSpv(*prog->getIntermediate(lang[stage]), spirv, NULL, &options);
  189. res->size = spirv.size()*sizeof(unsigned int);
  190. res->data = av_memdup(spirv.data(), res->size);
  191. if (!res->data) {
  192. res->rval = AVERROR(ENOMEM);
  193. delete shader;
  194. delete prog;
  195. return res;
  196. }
  197. delete shader;
  198. delete prog;
  199. return res;
  200. }
  201. int glslang_init(void)
  202. {
  203. int ret = 0;
  204. pthread_mutex_lock(&glslang_mutex);
  205. if (glslang_refcount++ == 0)
  206. ret = !InitializeProcess();
  207. pthread_mutex_unlock(&glslang_mutex);
  208. return ret;
  209. }
  210. void glslang_uninit(void)
  211. {
  212. pthread_mutex_lock(&glslang_mutex);
  213. av_assert0(glslang_refcount > 0);
  214. if (--glslang_refcount == 0)
  215. FinalizeProcess();
  216. pthread_mutex_unlock(&glslang_mutex);
  217. }