BsVulkanGpuProgram.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanGpuProgram.h"
  4. #include "BsVulkanRenderAPI.h"
  5. #include "BsVulkanDevice.h"
  6. #include "BsVulkanUtility.h"
  7. #include "BsGpuParams.h"
  8. #include "BsGpuParamDesc.h"
  9. #include "BsGpuProgramManager.h"
  10. #include "BsVertexDeclaration.h"
  11. #include "BsHardwareBufferManager.h"
  12. #include "BsRenderStats.h"
  13. #include "Public/ShaderLang.h"
  14. #include "Include/Types.h"
  15. #include "vulkan/icd-spv.h"
  16. namespace bs
  17. {
  18. const TBuiltInResource DefaultTBuiltInResource = {
  19. /* .MaxLights = */ 32,
  20. /* .MaxClipPlanes = */ 6,
  21. /* .MaxTextureUnits = */ 32,
  22. /* .MaxTextureCoords = */ 32,
  23. /* .MaxVertexAttribs = */ 64,
  24. /* .MaxVertexUniformComponents = */ 4096,
  25. /* .MaxVaryingFloats = */ 64,
  26. /* .MaxVertexTextureImageUnits = */ 32,
  27. /* .MaxCombinedTextureImageUnits = */ 80,
  28. /* .MaxTextureImageUnits = */ 32,
  29. /* .MaxFragmentUniformComponents = */ 4096,
  30. /* .MaxDrawBuffers = */ 32,
  31. /* .MaxVertexUniformVectors = */ 128,
  32. /* .MaxVaryingVectors = */ 8,
  33. /* .MaxFragmentUniformVectors = */ 16,
  34. /* .MaxVertexOutputVectors = */ 16,
  35. /* .MaxFragmentInputVectors = */ 15,
  36. /* .MinProgramTexelOffset = */ -8,
  37. /* .MaxProgramTexelOffset = */ 7,
  38. /* .MaxClipDistances = */ 8,
  39. /* .MaxComputeWorkGroupCountX = */ 65535,
  40. /* .MaxComputeWorkGroupCountY = */ 65535,
  41. /* .MaxComputeWorkGroupCountZ = */ 65535,
  42. /* .MaxComputeWorkGroupSizeX = */ 1024,
  43. /* .MaxComputeWorkGroupSizeY = */ 1024,
  44. /* .MaxComputeWorkGroupSizeZ = */ 64,
  45. /* .MaxComputeUniformComponents = */ 1024,
  46. /* .MaxComputeTextureImageUnits = */ 16,
  47. /* .MaxComputeImageUniforms = */ 8,
  48. /* .MaxComputeAtomicCounters = */ 8,
  49. /* .MaxComputeAtomicCounterBuffers = */ 1,
  50. /* .MaxVaryingComponents = */ 60,
  51. /* .MaxVertexOutputComponents = */ 64,
  52. /* .MaxGeometryInputComponents = */ 64,
  53. /* .MaxGeometryOutputComponents = */ 128,
  54. /* .MaxFragmentInputComponents = */ 128,
  55. /* .MaxImageUnits = */ 8,
  56. /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
  57. /* .MaxCombinedShaderOutputResources = */ 8,
  58. /* .MaxImageSamples = */ 0,
  59. /* .MaxVertexImageUniforms = */ 0,
  60. /* .MaxTessControlImageUniforms = */ 0,
  61. /* .MaxTessEvaluationImageUniforms = */ 0,
  62. /* .MaxGeometryImageUniforms = */ 0,
  63. /* .MaxFragmentImageUniforms = */ 8,
  64. /* .MaxCombinedImageUniforms = */ 8,
  65. /* .MaxGeometryTextureImageUnits = */ 16,
  66. /* .MaxGeometryOutputVertices = */ 256,
  67. /* .MaxGeometryTotalOutputComponents = */ 1024,
  68. /* .MaxGeometryUniformComponents = */ 1024,
  69. /* .MaxGeometryVaryingComponents = */ 64,
  70. /* .MaxTessControlInputComponents = */ 128,
  71. /* .MaxTessControlOutputComponents = */ 128,
  72. /* .MaxTessControlTextureImageUnits = */ 16,
  73. /* .MaxTessControlUniformComponents = */ 1024,
  74. /* .MaxTessControlTotalOutputComponents = */ 4096,
  75. /* .MaxTessEvaluationInputComponents = */ 128,
  76. /* .MaxTessEvaluationOutputComponents = */ 128,
  77. /* .MaxTessEvaluationTextureImageUnits = */ 16,
  78. /* .MaxTessEvaluationUniformComponents = */ 1024,
  79. /* .MaxTessPatchComponents = */ 120,
  80. /* .MaxPatchVertices = */ 32,
  81. /* .MaxTessGenLevel = */ 64,
  82. /* .MaxViewports = */ 16,
  83. /* .MaxVertexAtomicCounters = */ 0,
  84. /* .MaxTessControlAtomicCounters = */ 0,
  85. /* .MaxTessEvaluationAtomicCounters = */ 0,
  86. /* .MaxGeometryAtomicCounters = */ 0,
  87. /* .MaxFragmentAtomicCounters = */ 8,
  88. /* .MaxCombinedAtomicCounters = */ 8,
  89. /* .MaxAtomicCounterBindings = */ 1,
  90. /* .MaxVertexAtomicCounterBuffers = */ 0,
  91. /* .MaxTessControlAtomicCounterBuffers = */ 0,
  92. /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
  93. /* .MaxGeometryAtomicCounterBuffers = */ 0,
  94. /* .MaxFragmentAtomicCounterBuffers = */ 1,
  95. /* .MaxCombinedAtomicCounterBuffers = */ 1,
  96. /* .MaxAtomicCounterBufferSize = */ 16384,
  97. /* .MaxTransformFeedbackBuffers = */ 4,
  98. /* .MaxTransformFeedbackInterleavedComponents = */ 64,
  99. /* .MaxCullDistances = */ 8,
  100. /* .MaxCombinedClipAndCullDistances = */ 8,
  101. /* .MaxSamples = */ 4,
  102. /* .limits = */{
  103. /* .nonInductiveForLoops = */ 1,
  104. /* .whileLoops = */ 1,
  105. /* .doWhileLoops = */ 1,
  106. /* .generalUniformIndexing = */ 1,
  107. /* .generalAttributeMatrixVectorIndexing = */ 1,
  108. /* .generalVaryingIndexing = */ 1,
  109. /* .generalSamplerIndexing = */ 1,
  110. /* .generalVariableIndexing = */ 1,
  111. /* .generalConstantMatrixVectorIndexing = */ 1,
  112. } };
  113. VertexElementType mapGLSLangToVertexElemType(const glslang::TType& type)
  114. {
  115. if (type.isVector())
  116. {
  117. UINT32 vectorSize = type.getVectorSize();
  118. switch (type.getBasicType())
  119. {
  120. case glslang::EbtFloat:
  121. switch(vectorSize)
  122. {
  123. case 2: return VET_FLOAT2;
  124. case 3: return VET_FLOAT3;
  125. case 4: return VET_FLOAT4;
  126. default: return VET_UNKNOWN;
  127. }
  128. case glslang::EbtInt:
  129. switch (vectorSize)
  130. {
  131. case 2: return VET_INT2;
  132. case 3: return VET_INT3;
  133. case 4: return VET_INT4;
  134. default: return VET_UNKNOWN;
  135. }
  136. case glslang::EbtUint:
  137. switch (vectorSize)
  138. {
  139. case 2: return VET_UINT2;
  140. case 3: return VET_UINT3;
  141. case 4: return VET_UINT4;
  142. default: return VET_UNKNOWN;
  143. }
  144. default:
  145. return VET_UNKNOWN;
  146. }
  147. }
  148. if (type.getVectorSize() == 1)
  149. {
  150. switch (type.getBasicType())
  151. {
  152. case glslang::EbtFloat: return VET_FLOAT1;
  153. case glslang::EbtInt: return VET_INT1;
  154. case glslang::EbtUint: return VET_UINT1;
  155. default: return VET_UNKNOWN;
  156. }
  157. }
  158. return VET_UNKNOWN;
  159. }
  160. GpuParamDataType mapGLSLangToGpuParamDataType(const glslang::TType& type)
  161. {
  162. if (type.getBasicType() == glslang::EbtStruct)
  163. return GPDT_STRUCT;
  164. if (type.isVector())
  165. {
  166. UINT32 vectorSize = type.getVectorSize();
  167. switch (type.getBasicType())
  168. {
  169. case glslang::EbtFloat:
  170. switch (vectorSize)
  171. {
  172. case 2: return GPDT_FLOAT2;
  173. case 3: return GPDT_FLOAT3;
  174. case 4: return GPDT_FLOAT4;
  175. default: return GPDT_UNKNOWN;
  176. }
  177. case glslang::EbtInt:
  178. switch (vectorSize)
  179. {
  180. case 2: return GPDT_INT2;
  181. case 3: return GPDT_INT3;
  182. case 4: return GPDT_INT4;
  183. default: return GPDT_UNKNOWN;
  184. }
  185. default:
  186. return GPDT_UNKNOWN;
  187. }
  188. }
  189. if (type.isMatrix())
  190. {
  191. switch (type.getBasicType())
  192. {
  193. case glslang::EbtFloat:
  194. switch (type.getMatrixCols())
  195. {
  196. case 2:
  197. switch (type.getMatrixRows())
  198. {
  199. case 2: return GPDT_MATRIX_2X2;
  200. case 3: return GPDT_MATRIX_3X2;
  201. case 4: return GPDT_MATRIX_4X2;
  202. default: return GPDT_UNKNOWN;
  203. }
  204. case 3:
  205. switch (type.getMatrixRows())
  206. {
  207. case 2: return GPDT_MATRIX_2X3;
  208. case 3: return GPDT_MATRIX_3X3;
  209. case 4: return GPDT_MATRIX_4X3;
  210. default: return GPDT_UNKNOWN;
  211. }
  212. case 4:
  213. switch (type.getMatrixRows())
  214. {
  215. case 2: return GPDT_MATRIX_2X4;
  216. case 3: return GPDT_MATRIX_3X4;
  217. case 4: return GPDT_MATRIX_4X4;
  218. default: return GPDT_UNKNOWN;
  219. }
  220. }
  221. default:
  222. return GPDT_UNKNOWN;
  223. }
  224. }
  225. if (type.getVectorSize() == 1)
  226. {
  227. switch (type.getBasicType())
  228. {
  229. case glslang::EbtFloat: return GPDT_FLOAT1;
  230. case glslang::EbtInt: return GPDT_INT1;
  231. case glslang::EbtBool: return GPDT_BOOL;
  232. default: return GPDT_UNKNOWN;
  233. }
  234. }
  235. return GPDT_UNKNOWN;
  236. }
  237. /** Holds a GLSL program input attribute used in vertex programs. */
  238. struct GLSLAttribute
  239. {
  240. /** Constructs a new attribute from a name and a semantic that represents in which way is the attribute used. */
  241. GLSLAttribute(const String& name, VertexElementSemantic semantic)
  242. :mName(name), mSemantic(semantic)
  243. { }
  244. /**
  245. * Return true if attribute name matches the specified name and returns optional semantic index if it exists. Start
  246. * of the two compared strings must match, and the remaining non-matching bit will be assumed to be the semantic
  247. * index. Returns -1 if no match is made.
  248. */
  249. INT32 matchesName(const String& name);
  250. /** Returns the semantic of this attribute. */
  251. VertexElementSemantic getSemantic() const { return mSemantic; }
  252. private:
  253. String mName;
  254. VertexElementSemantic mSemantic;
  255. };
  256. bool attribNameToElementSemantic(const String& name, VertexElementSemantic& semantic, UINT16& index)
  257. {
  258. static GLSLAttribute attributes[] =
  259. {
  260. GLSLAttribute("bs_position", VES_POSITION),
  261. GLSLAttribute("bs_normal", VES_NORMAL),
  262. GLSLAttribute("bs_tangent", VES_TANGENT),
  263. GLSLAttribute("bs_bitangent", VES_BITANGENT),
  264. GLSLAttribute("bs_texcoord", VES_TEXCOORD),
  265. GLSLAttribute("bs_color", VES_COLOR),
  266. GLSLAttribute("bs_blendweights", VES_BLEND_WEIGHTS),
  267. GLSLAttribute("bs_blendindices", VES_BLEND_INDICES)
  268. };
  269. static const UINT32 numAttribs = sizeof(attributes) / sizeof(attributes[0]);
  270. for (UINT32 i = 0; i < numAttribs; i++)
  271. {
  272. INT32 attribIndex = attributes[i].matchesName(name);
  273. if (attribIndex != -1)
  274. {
  275. index = attribIndex;
  276. semantic = attributes[i].getSemantic();
  277. return true;
  278. }
  279. }
  280. return false;
  281. }
  282. bool parseVertexAttributes(const glslang::TProgram* program, List<VertexElement>& elementList, String& log)
  283. {
  284. int numAttributes = program->getNumLiveAttributes();
  285. for (int i = 0; i < numAttributes; i++)
  286. {
  287. const glslang::TType* ttype = program->getAttributeTType(i);
  288. UINT32 location = ttype->getQualifier().layoutLocation;
  289. if (location == -1)
  290. {
  291. log = "Vertex attribute parsing error: Found a vertex attribute without a location "
  292. "qualifier. Each attribute must have an explicitly defined location number.";
  293. return false;
  294. }
  295. const char* attribName = program->getAttributeName(i);
  296. VertexElementSemantic semantic = VES_POSITION;
  297. UINT16 index = 0;
  298. if (attribNameToElementSemantic(attribName, semantic, index))
  299. {
  300. VertexElementType type = mapGLSLangToVertexElemType(*ttype);
  301. if (type == VET_UNKNOWN)
  302. LOGERR("Cannot determine vertex input attribute type for attribute: " + String(attribName));
  303. elementList.push_back(VertexElement(0, location, type, semantic, index));
  304. }
  305. else
  306. {
  307. // Ignore built-in attributes
  308. if (memcmp(attribName, "gl_", 3) != 0)
  309. LOGERR("Cannot determine vertex input attribute semantic for attribute: " + String(attribName));
  310. }
  311. }
  312. return true;
  313. }
  314. bool parseUniforms(const glslang::TProgram* program, GpuParamDesc& desc, String& log)
  315. {
  316. // Parse uniform blocks
  317. UnorderedMap<UINT32, String> uniformBlockMap;
  318. int numBlocks = program->getNumLiveUniformBlocks();
  319. for (int i = 0; i < numBlocks; i++)
  320. {
  321. const glslang::TType* ttype = program->getUniformBlockTType(i);
  322. const char* name = program->getUniformBlockName(i);
  323. int size = program->getUniformBlockSize(i);
  324. int index = program->getUniformBlockIndex(i);
  325. GpuParamBlockDesc param;
  326. param.name = name;
  327. param.blockSize = size;
  328. param.isShareable = true;
  329. param.slot = ttype->getQualifier().layoutBinding;
  330. param.set = ttype->getQualifier().layoutSet;
  331. desc.paramBlocks[name] = param;
  332. uniformBlockMap[index] = name;
  333. }
  334. // Parse individual uniforms
  335. int numUniforms = program->getNumLiveUniformVariables();
  336. for (int i = 0; i < numUniforms; i++)
  337. {
  338. const glslang::TType* ttype = program->getUniformTType(i);
  339. const char* name = program->getUniformName(i);
  340. if(!ttype->getQualifier().hasBinding())
  341. {
  342. log = "Uniform parsing error: Found an uniform without a binding qualifier. Each uniform must have an "
  343. "explicitly defined binding number.";
  344. return false;
  345. }
  346. if (ttype->getBasicType() == glslang::EbtSampler) // Object type
  347. {
  348. // Note: Even though the type is named EbtSampler, all object types are categorized under it (including non
  349. // sampled images and buffers)
  350. const glslang::TSampler& sampler = ttype->getSampler();
  351. GpuParamObjectDesc param;
  352. param.name = name;
  353. param.slot = ttype->getQualifier().layoutBinding;
  354. param.set = ttype->getQualifier().layoutSet;
  355. if (sampler.isImage())
  356. {
  357. switch (sampler.dim)
  358. {
  359. case glslang::Esd1D: param.type = GPOT_RWTEXTURE1D; break;
  360. case glslang::Esd2D: param.type = sampler.isMultiSample() ? GPOT_RWTEXTURE2DMS : GPOT_RWTEXTURE2D; break;
  361. case glslang::Esd3D: param.type = GPOT_RWTEXTURE3D; break;
  362. case glslang::EsdBuffer: param.type = GPOT_RWSTRUCTURED_BUFFER; break;
  363. }
  364. if(sampler.dim != glslang::EsdBuffer)
  365. desc.loadStoreTextures[name] = param;
  366. else
  367. desc.buffers[name] = param;
  368. }
  369. else
  370. {
  371. switch (sampler.dim)
  372. {
  373. case glslang::Esd1D: param.type = GPOT_SAMPLER1D; break;
  374. case glslang::Esd2D: param.type = sampler.isMultiSample() ? GPOT_SAMPLER2DMS : GPOT_SAMPLER2D; break;
  375. case glslang::Esd3D: param.type = GPOT_SAMPLER3D; break;
  376. case glslang::EsdCube: param.type = GPOT_SAMPLERCUBE; break;
  377. }
  378. desc.samplers[name] = param;
  379. if (!sampler.isPureSampler())
  380. {
  381. switch (sampler.dim)
  382. {
  383. case glslang::Esd1D: param.type = GPOT_TEXTURE1D; break;
  384. case glslang::Esd2D: param.type = sampler.isMultiSample() ? GPOT_TEXTURE2DMS : GPOT_TEXTURE2D; break;
  385. case glslang::Esd3D: param.type = GPOT_TEXTURE3D; break;
  386. case glslang::EsdCube: param.type = GPOT_TEXTURECUBE; break;
  387. case glslang::EsdBuffer: param.type = GPOT_STRUCTURED_BUFFER; break;
  388. }
  389. if (sampler.dim != glslang::EsdBuffer)
  390. desc.textures[name] = param;
  391. else
  392. desc.buffers[name] = param;
  393. }
  394. }
  395. if(param.type == GPOT_UNKNOWN)
  396. LOGERR("Cannot determine type for uniform: " + String(name));
  397. }
  398. else
  399. {
  400. if(ttype->getBasicType() == glslang::EbtStruct)
  401. {
  402. // Not handling structs at the moment
  403. }
  404. else
  405. {
  406. GpuParamDataType paramType = mapGLSLangToGpuParamDataType(*ttype);
  407. if (paramType == GPDT_UNKNOWN)
  408. {
  409. LOGWRN("Cannot determine type for uniform: " + String(name));
  410. continue;
  411. }
  412. int blockIdx = program->getUniformBlockIndex(i);
  413. auto iterFind = uniformBlockMap.find(blockIdx);
  414. if (iterFind == uniformBlockMap.end())
  415. LOGERR("Uniform is referencing a uniform block that doesn't exist: " + String(name));
  416. const GpuParamBlockDesc& paramBlockDesc = desc.paramBlocks[iterFind->second];
  417. const GpuParamDataTypeInfo& typeInfo = GpuParams::PARAM_SIZES.lookup[paramType];
  418. int bufferOffset = program->getUniformBufferOffset(i) / 4;
  419. GpuParamDataDesc param;
  420. param.name = name;
  421. param.type = paramType;
  422. param.paramBlockSet = paramBlockDesc.set;
  423. param.paramBlockSlot = paramBlockDesc.slot;
  424. param.elementSize = typeInfo.size / 4;
  425. param.arrayElementStride = param.elementSize;
  426. param.arraySize = program->getUniformArraySize(i);
  427. param.cpuMemOffset = bufferOffset;
  428. param.gpuMemOffset = bufferOffset;
  429. desc.params[name] = param;
  430. }
  431. }
  432. }
  433. return true;
  434. }
  435. VulkanShaderModule::VulkanShaderModule(VulkanResourceManager* owner, VkShaderModule module)
  436. :VulkanResource(owner, true), mModule(module)
  437. { }
  438. VulkanShaderModule::~VulkanShaderModule()
  439. {
  440. vkDestroyShaderModule(mOwner->getDevice().getLogical(), mModule, gVulkanAllocator);
  441. }
  442. VulkanGpuProgramCore::VulkanGpuProgramCore(const GPU_PROGRAM_DESC& desc, GpuDeviceFlags deviceMask)
  443. : GpuProgramCore(desc, deviceMask), mDeviceMask(deviceMask), mModules()
  444. {
  445. }
  446. VulkanGpuProgramCore::~VulkanGpuProgramCore()
  447. {
  448. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  449. {
  450. if (mModules[i] != nullptr)
  451. mModules[i]->destroy();
  452. }
  453. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuProgram);
  454. }
  455. void VulkanGpuProgramCore::initialize()
  456. {
  457. if (!isSupported())
  458. {
  459. mIsCompiled = false;
  460. mCompileError = "Specified program is not supported by the current render system.";
  461. GpuProgramCore::initialize();
  462. return;
  463. }
  464. glslang::InitializeProcess();
  465. TBuiltInResource resources = DefaultTBuiltInResource;
  466. glslang::TProgram* program = new glslang::TProgram;
  467. EShLanguage glslType;
  468. switch(mProperties.getType())
  469. {
  470. case GPT_FRAGMENT_PROGRAM:
  471. glslType = EShLangFragment;
  472. break;
  473. case GPT_HULL_PROGRAM:
  474. glslType = EShLangTessControl;
  475. break;
  476. case GPT_DOMAIN_PROGRAM:
  477. glslType = EShLangTessEvaluation;
  478. break;
  479. case GPT_GEOMETRY_PROGRAM:
  480. glslType = EShLangGeometry;
  481. break;
  482. case GPT_VERTEX_PROGRAM:
  483. glslType = EShLangVertex;
  484. break;
  485. case GPT_COMPUTE_PROGRAM:
  486. glslType = EShLangCompute;
  487. break;
  488. }
  489. const String& source = mProperties.getSource();
  490. const char* sourceBytes = source.c_str();
  491. glslang::TShader* shader = new glslang::TShader(glslType);
  492. shader->setStrings(&sourceBytes, 1);
  493. shader->setEntryPoint("main");
  494. if (!shader->parse(&resources, 450, false, EShMsgDefault))
  495. {
  496. mIsCompiled = false;
  497. mCompileError = "Compile error: " + toString(shader->getInfoLog());
  498. goto cleanup;
  499. }
  500. program->addShader(shader);
  501. if (!program->link(EShMsgDefault))
  502. {
  503. mIsCompiled = false;
  504. mCompileError = "Link error: " + toString(program->getInfoLog());
  505. goto cleanup;
  506. }
  507. // Parse uniforms
  508. program->buildReflection();
  509. if(!parseUniforms(program, *mParametersDesc, mCompileError))
  510. {
  511. mIsCompiled = false;
  512. goto cleanup;
  513. }
  514. // If vertex program, retrieve information about vertex inputs
  515. if (mProperties.getType() == GPT_VERTEX_PROGRAM)
  516. {
  517. List<VertexElement> elementList;
  518. if (parseVertexAttributes(program, elementList, mCompileError))
  519. mInputDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(elementList, mDeviceMask);
  520. else
  521. {
  522. mIsCompiled = false;
  523. goto cleanup;
  524. }
  525. }
  526. // Compile shader and create Vulkan module
  527. // Note: We provide GLSL code to the driver under the hood instead of using SPIR-V, mainly because of
  528. // optimization concerns. Later we can convert to SPIR-V and feed it directly.
  529. UINT32 codeSize = source.size() + 3 * sizeof(UINT32);
  530. UINT32* codeBytes = (UINT32*)bs_stack_alloc(codeSize);
  531. // Add special header so code is recognized as GLSL
  532. UINT32* header = (UINT32*)codeBytes;
  533. header[0] = ICD_SPV_MAGIC;
  534. header[1] = ICD_SPV_VERSION;
  535. header[2] = 0;
  536. UINT32* glslBytes = codeBytes + 3;
  537. memcpy(glslBytes, sourceBytes, source.size());
  538. VkShaderModuleCreateInfo moduleCI;
  539. moduleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  540. moduleCI.pNext = nullptr;
  541. moduleCI.flags = 0;
  542. moduleCI.codeSize = codeSize;
  543. moduleCI.pCode = codeBytes;
  544. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPICore::instance());
  545. VulkanDevice* devices[BS_MAX_DEVICES];
  546. VulkanUtility::getDevices(rapi, mDeviceMask, devices);
  547. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  548. {
  549. if (devices[i] != nullptr)
  550. {
  551. VkDevice vkDevice = devices[i]->getLogical();
  552. VulkanResourceManager& rescManager = devices[i]->getResourceManager();
  553. VkShaderModule shaderModule;
  554. VkResult result = vkCreateShaderModule(vkDevice, &moduleCI, gVulkanAllocator, &shaderModule);
  555. assert(result == VK_SUCCESS);
  556. mModules[i] = rescManager.create<VulkanShaderModule>(shaderModule);
  557. }
  558. }
  559. bs_stack_free(codeBytes);
  560. cleanup:
  561. delete program;
  562. delete shader;
  563. glslang::FinalizeProcess();
  564. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
  565. GpuProgramCore::initialize();
  566. }
  567. }