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.

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