Shader.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /**
  2. * Copyright (c) 2006-2024 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "graphics/vertex.h"
  21. #include "Shader.h"
  22. #include "Graphics.h"
  23. #include "libraries/glslang/glslang/Public/ShaderLang.h"
  24. #include "libraries/glslang/glslang/Public/ResourceLimits.h"
  25. #include "libraries/glslang/SPIRV/GlslangToSpv.h"
  26. #include <array>
  27. namespace love
  28. {
  29. namespace graphics
  30. {
  31. namespace vulkan
  32. {
  33. static const uint32_t STREAMBUFFER_DEFAULT_SIZE = 16;
  34. static const uint32_t DESCRIPTOR_POOL_SIZE = 1000;
  35. class BindingMapper
  36. {
  37. public:
  38. uint32_t operator()(spirv_cross::CompilerGLSL &comp, std::vector<uint32_t> &spirv, const std::string &name, const spirv_cross::ID &id)
  39. {
  40. auto it = bindingMappings.find(name);
  41. if (it == bindingMappings.end())
  42. {
  43. auto binding = comp.get_decoration(id, spv::DecorationBinding);
  44. if (isFreeBinding(binding))
  45. {
  46. bindingMappings[name] = binding;
  47. return binding;
  48. }
  49. else
  50. {
  51. uint32_t freeBinding = getFreeBinding();
  52. uint32_t binaryBindingOffset;
  53. if (!comp.get_binary_offset_for_decoration(id, spv::DecorationBinding, binaryBindingOffset))
  54. throw love::Exception("could not get binary offset for uniform %s binding", name.c_str());
  55. spirv[binaryBindingOffset] = freeBinding;
  56. bindingMappings[name] = freeBinding;
  57. return freeBinding;
  58. }
  59. }
  60. else
  61. return it->second;
  62. };
  63. private:
  64. uint32_t getFreeBinding()
  65. {
  66. for (uint32_t i = 0;; i++)
  67. {
  68. if (isFreeBinding(i))
  69. return i;
  70. }
  71. }
  72. bool isFreeBinding(uint32_t binding)
  73. {
  74. for (const auto &entry : bindingMappings)
  75. {
  76. if (entry.second == binding)
  77. return false;
  78. }
  79. return true;
  80. }
  81. std::map<std::string, uint32_t> bindingMappings;
  82. };
  83. static VkShaderStageFlagBits getStageBit(ShaderStageType type)
  84. {
  85. switch (type)
  86. {
  87. case SHADERSTAGE_VERTEX:
  88. return VK_SHADER_STAGE_VERTEX_BIT;
  89. case SHADERSTAGE_PIXEL:
  90. return VK_SHADER_STAGE_FRAGMENT_BIT;
  91. case SHADERSTAGE_COMPUTE:
  92. return VK_SHADER_STAGE_COMPUTE_BIT;
  93. default:
  94. throw love::Exception("invalid type");
  95. }
  96. }
  97. static EShLanguage getGlslShaderType(ShaderStageType stage)
  98. {
  99. switch (stage)
  100. {
  101. case SHADERSTAGE_VERTEX:
  102. return EShLangVertex;
  103. case SHADERSTAGE_PIXEL:
  104. return EShLangFragment;
  105. case SHADERSTAGE_COMPUTE:
  106. return EShLangCompute;
  107. default:
  108. throw love::Exception("unkonwn shader stage type");
  109. }
  110. }
  111. static bool usesLocalUniformData(const graphics::Shader::UniformInfo *info)
  112. {
  113. return info->baseType == graphics::Shader::UNIFORM_BOOL ||
  114. info->baseType == graphics::Shader::UNIFORM_FLOAT ||
  115. info->baseType == graphics::Shader::UNIFORM_INT ||
  116. info->baseType == graphics::Shader::UNIFORM_MATRIX ||
  117. info->baseType == graphics::Shader::UNIFORM_UINT;
  118. }
  119. Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[], const CompileOptions &options)
  120. : graphics::Shader(stages, options)
  121. {
  122. auto gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
  123. vgfx = dynamic_cast<Graphics*>(gfx);
  124. loadVolatile();
  125. }
  126. bool Shader::loadVolatile()
  127. {
  128. device = vgfx->getDevice();
  129. computePipeline = VK_NULL_HANDLE;
  130. for (int i = 0; i < BUILTIN_MAX_ENUM; i++)
  131. builtinUniformInfo[i] = nullptr;
  132. compileShaders();
  133. calculateUniformBufferSizeAligned();
  134. createDescriptorSetLayout();
  135. createPipelineLayout();
  136. createDescriptorPoolSizes();
  137. createStreamBuffers();
  138. descriptorPools.resize(MAX_FRAMES_IN_FLIGHT);
  139. currentFrame = 0;
  140. currentUsedUniformStreamBuffersCount = 0;
  141. newFrame();
  142. return true;
  143. }
  144. void Shader::unloadVolatile()
  145. {
  146. if (shaderModules.empty())
  147. return;
  148. vgfx->queueCleanUp([shaderModules = std::move(shaderModules), device = device, descriptorSetLayout = descriptorSetLayout, pipelineLayout = pipelineLayout, descriptorPools = descriptorPools, computePipeline = computePipeline](){
  149. for (const auto &pools : descriptorPools)
  150. {
  151. for (const auto pool : pools)
  152. vkDestroyDescriptorPool(device, pool, nullptr);
  153. }
  154. for (const auto shaderModule : shaderModules)
  155. vkDestroyShaderModule(device, shaderModule, nullptr);
  156. vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
  157. vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
  158. if (computePipeline != VK_NULL_HANDLE)
  159. vkDestroyPipeline(device, computePipeline, nullptr);
  160. });
  161. for (const auto streamBuffer : streamBuffers)
  162. streamBuffer->release();
  163. shaderModules.clear();
  164. shaderStages.clear();
  165. streamBuffers.clear();
  166. descriptorPools.clear();
  167. }
  168. const std::vector<VkPipelineShaderStageCreateInfo> &Shader::getShaderStages() const
  169. {
  170. return shaderStages;
  171. }
  172. const VkPipelineLayout Shader::getGraphicsPipelineLayout() const
  173. {
  174. return pipelineLayout;
  175. }
  176. VkPipeline Shader::getComputePipeline() const
  177. {
  178. return computePipeline;
  179. }
  180. void Shader::newFrame()
  181. {
  182. currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  183. currentUsedUniformStreamBuffersCount = 0;
  184. currentDescriptorPool = 0;
  185. if (streamBuffers.size() > 1)
  186. {
  187. size_t newSize = 0;
  188. for (auto streamBuffer : streamBuffers)
  189. {
  190. newSize += streamBuffer->getSize();
  191. streamBuffer->release();
  192. }
  193. streamBuffers.clear();
  194. streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, newSize));
  195. }
  196. else
  197. streamBuffers.at(0)->nextFrame();
  198. for (VkDescriptorPool pool : descriptorPools[currentFrame])
  199. vkResetDescriptorPool(device, pool, 0);
  200. }
  201. void Shader::cmdPushDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint bindPoint)
  202. {
  203. VkDescriptorSet currentDescriptorSet = allocateDescriptorSet();
  204. std::vector<VkDescriptorBufferInfo> bufferInfos;
  205. bufferInfos.reserve(numBuffers);
  206. std::vector<VkDescriptorImageInfo> imageInfos;
  207. imageInfos.reserve(numTextures);
  208. std::vector<VkBufferView> bufferViews;
  209. bufferViews.reserve(numBufferViews);
  210. std::vector<VkWriteDescriptorSet> descriptorWrites;
  211. if (!localUniformData.empty())
  212. {
  213. auto usedStreamBufferMemory = currentUsedUniformStreamBuffersCount * uniformBufferSizeAligned;
  214. if (usedStreamBufferMemory >= streamBuffers.back()->getSize())
  215. {
  216. streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned));
  217. currentUsedUniformStreamBuffersCount = 0;
  218. }
  219. if (builtinUniformDataOffset.hasValue)
  220. {
  221. auto builtinData = vgfx->getCurrentBuiltinUniformData();
  222. auto dst = localUniformData.data() + builtinUniformDataOffset.value;
  223. memcpy(dst, &builtinData, sizeof(builtinData));
  224. }
  225. auto currentStreamBuffer = streamBuffers.back();
  226. auto mapInfo = currentStreamBuffer->map(uniformBufferSizeAligned);
  227. memcpy(mapInfo.data, localUniformData.data(), localUniformData.size());
  228. auto offset = currentStreamBuffer->unmap(uniformBufferSizeAligned);
  229. currentStreamBuffer->markUsed(uniformBufferSizeAligned);
  230. VkDescriptorBufferInfo bufferInfo{};
  231. bufferInfo.buffer = (VkBuffer)currentStreamBuffer->getHandle();
  232. bufferInfo.offset = offset;
  233. bufferInfo.range = localUniformData.size();
  234. bufferInfos.push_back(bufferInfo);
  235. VkWriteDescriptorSet uniformWrite{};
  236. uniformWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  237. uniformWrite.dstSet = currentDescriptorSet;
  238. uniformWrite.dstBinding = localUniformLocation;
  239. uniformWrite.dstArrayElement = 0;
  240. uniformWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  241. uniformWrite.descriptorCount = 1;
  242. uniformWrite.pBufferInfo = &bufferInfos[bufferInfos.size() - 1];
  243. descriptorWrites.push_back(uniformWrite);
  244. currentUsedUniformStreamBuffersCount++;
  245. }
  246. for (const auto &u : reflection.allUniforms)
  247. {
  248. auto &info = *(u.second);
  249. if (!info.active || usesLocalUniformData(&info))
  250. continue;
  251. if (info.baseType == UNIFORM_SAMPLER || info.baseType == UNIFORM_STORAGETEXTURE)
  252. {
  253. bool isSampler = info.baseType == UNIFORM_SAMPLER;
  254. for (int i = 0; i < info.count; i++)
  255. {
  256. auto vkTexture = dynamic_cast<Texture*>(activeTextures[info.resourceIndex + i]);
  257. if (vkTexture == nullptr)
  258. throw love::Exception("uniform variable %s is not set.", info.name.c_str());
  259. VkDescriptorImageInfo imageInfo{};
  260. imageInfo.imageLayout = vkTexture->getImageLayout();
  261. imageInfo.imageView = (VkImageView)vkTexture->getRenderTargetHandle();
  262. if (isSampler)
  263. imageInfo.sampler = (VkSampler)vkTexture->getSamplerHandle();
  264. imageInfos.push_back(imageInfo);
  265. }
  266. VkWriteDescriptorSet write{};
  267. write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  268. write.dstSet = currentDescriptorSet;
  269. write.dstBinding = info.location;
  270. write.dstArrayElement = 0;
  271. if (isSampler)
  272. write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  273. else
  274. write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
  275. write.descriptorCount = static_cast<uint32_t>(info.count);
  276. write.pImageInfo = &imageInfos[imageInfos.size() - info.count];
  277. descriptorWrites.push_back(write);
  278. }
  279. if (info.baseType == UNIFORM_STORAGEBUFFER)
  280. {
  281. VkWriteDescriptorSet write{};
  282. write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  283. write.dstSet = currentDescriptorSet;
  284. write.dstBinding = info.location;
  285. write.dstArrayElement = 0;
  286. write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
  287. write.descriptorCount = info.count;
  288. for (int i = 0; i < info.count; i++)
  289. {
  290. auto b = activeBuffers[info.resourceIndex + i];
  291. if (b == nullptr)
  292. throw love::Exception("uniform variable %s is not set.", info.name.c_str());
  293. VkDescriptorBufferInfo bufferInfo{};
  294. bufferInfo.buffer = (VkBuffer)b->getHandle();
  295. bufferInfo.offset = 0;
  296. bufferInfo.range = b->getSize();
  297. bufferInfos.push_back(bufferInfo);
  298. }
  299. write.pBufferInfo = &bufferInfos[bufferInfos.size() - info.count];
  300. descriptorWrites.push_back(write);
  301. }
  302. if (info.baseType == UNIFORM_TEXELBUFFER)
  303. {
  304. VkWriteDescriptorSet write{};
  305. write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  306. write.dstSet = currentDescriptorSet;
  307. write.dstBinding = info.location;
  308. write.dstArrayElement = 0;
  309. write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
  310. write.descriptorCount = info.count;
  311. for (int i = 0; i < info.count; i++)
  312. {
  313. auto b = activeBuffers[info.resourceIndex + i];
  314. if (b == nullptr)
  315. throw love::Exception("uniform variable %s is not set.", info.name.c_str());
  316. bufferViews.push_back((VkBufferView)b->getTexelBufferHandle());
  317. }
  318. write.pTexelBufferView = &bufferViews[bufferViews.size() - info.count];
  319. descriptorWrites.push_back(write);
  320. }
  321. }
  322. vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
  323. vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &currentDescriptorSet, 0, nullptr);
  324. }
  325. Shader::~Shader()
  326. {
  327. unloadVolatile();
  328. }
  329. void Shader::attach()
  330. {
  331. if (!isCompute)
  332. {
  333. if (Shader::current != this)
  334. {
  335. Graphics::flushBatchedDrawsGlobal();
  336. Shader::current = this;
  337. Vulkan::shaderSwitch();
  338. }
  339. }
  340. else
  341. vgfx->setComputeShader(this);
  342. }
  343. int Shader::getVertexAttributeIndex(const std::string &name)
  344. {
  345. auto it = attributes.find(name);
  346. return it == attributes.end() ? -1 : it->second;
  347. }
  348. const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const
  349. {
  350. return builtinUniformInfo[builtin];
  351. }
  352. void Shader::updateUniform(const UniformInfo *info, int count)
  353. {
  354. if (current == this)
  355. Graphics::flushBatchedDrawsGlobal();
  356. if (usesLocalUniformData(info))
  357. memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size());
  358. }
  359. void Shader::sendTextures(const UniformInfo *info, graphics::Texture **textures, int count)
  360. {
  361. if (current == this)
  362. Graphics::flushBatchedDrawsGlobal();
  363. for (int i = 0; i < count; i++)
  364. {
  365. int resourceindex = info->resourceIndex + i;
  366. auto oldTexture = activeTextures[resourceindex];
  367. activeTextures[resourceindex] = textures[i];
  368. activeTextures[resourceindex]->retain();
  369. if (oldTexture)
  370. oldTexture->release();
  371. }
  372. }
  373. void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count)
  374. {
  375. if (current == this)
  376. Graphics::flushBatchedDrawsGlobal();
  377. for (int i = 0; i < count; i++)
  378. {
  379. int resourceindex = info->resourceIndex + i;
  380. auto oldBuffer = activeBuffers[resourceindex];
  381. activeBuffers[resourceindex] = buffers[i];
  382. activeBuffers[resourceindex]->retain();
  383. if (oldBuffer)
  384. oldBuffer->release();
  385. }
  386. }
  387. void Shader::calculateUniformBufferSizeAligned()
  388. {
  389. auto minAlignment = vgfx->getMinUniformBufferOffsetAlignment();
  390. size_t size = localUniformStagingData.size();
  391. auto factor = static_cast<VkDeviceSize>(std::ceil(static_cast<float>(size) / static_cast<float>(minAlignment)));
  392. uniformBufferSizeAligned = factor * minAlignment;
  393. }
  394. void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::SPIRType &type, size_t baseoff, const std::string &basename)
  395. {
  396. using namespace spirv_cross;
  397. const auto &membertypes = type.member_types;
  398. for (size_t uindex = 0; uindex < membertypes.size(); uindex++)
  399. {
  400. const auto &memberType = comp.get_type(membertypes[uindex]);
  401. size_t memberSize = comp.get_declared_struct_member_size(type, uindex);
  402. size_t offset = baseoff + comp.type_struct_member_offset(type, uindex);
  403. std::string name = basename + comp.get_member_name(type.self, uindex);
  404. switch (memberType.basetype)
  405. {
  406. case SPIRType::Struct:
  407. name += ".";
  408. buildLocalUniforms(comp, memberType, offset, name);
  409. continue;
  410. case SPIRType::Int:
  411. case SPIRType::UInt:
  412. case SPIRType::Float:
  413. break;
  414. default:
  415. continue;
  416. }
  417. name = canonicaliizeUniformName(name);
  418. auto uniformit = reflection.allUniforms.find(name);
  419. if (uniformit == reflection.allUniforms.end())
  420. {
  421. handleUnknownUniformName(name.c_str());
  422. continue;
  423. }
  424. UniformInfo &u = *(uniformit->second);
  425. u.active = true;
  426. u.dataSize = memberSize;
  427. u.data = localUniformStagingData.data() + offset;
  428. const auto &valuesit = reflection.localUniformInitializerValues.find(name);
  429. if (valuesit != reflection.localUniformInitializerValues.end())
  430. {
  431. const auto &values = valuesit->second;
  432. if (!values.empty())
  433. memcpy(
  434. u.data,
  435. values.data(),
  436. std::min(u.dataSize, values.size() * sizeof(LocalUniformValue)));
  437. }
  438. BuiltinUniform builtin = BUILTIN_MAX_ENUM;
  439. if (getConstant(u.name.c_str(), builtin))
  440. {
  441. if (builtin == BUILTIN_UNIFORMS_PER_DRAW)
  442. builtinUniformDataOffset = offset;
  443. builtinUniformInfo[builtin] = &u;
  444. }
  445. }
  446. }
  447. void Shader::compileShaders()
  448. {
  449. using namespace glslang;
  450. using namespace spirv_cross;
  451. std::vector<std::unique_ptr<TShader>> glslangShaders;
  452. auto program = std::make_unique<TProgram>();
  453. const auto &enabledExtensions = vgfx->getEnabledOptionalDeviceExtensions();
  454. for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
  455. {
  456. if (!stages[i])
  457. continue;
  458. auto stage = (ShaderStageType)i;
  459. if (stage == SHADERSTAGE_COMPUTE)
  460. isCompute = true;
  461. auto glslangShaderStage = getGlslShaderType(stage);
  462. auto tshader = std::make_unique<TShader>(glslangShaderStage);
  463. tshader->setEnvInput(EShSourceGlsl, glslangShaderStage, EShClientVulkan, 450);
  464. tshader->setEnvClient(EShClientVulkan, EShTargetVulkan_1_2);
  465. if (enabledExtensions.spirv14)
  466. tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_4);
  467. else
  468. tshader->setEnvTarget(EshTargetSpv, EShTargetSpv_1_0);
  469. tshader->setAutoMapLocations(true);
  470. tshader->setAutoMapBindings(true);
  471. tshader->setEnvInputVulkanRulesRelaxed();
  472. tshader->setGlobalUniformBinding(0);
  473. tshader->setGlobalUniformSet(0);
  474. auto &glsl = stages[i]->getSource();
  475. const char *csrc = glsl.c_str();
  476. const int sourceLength = static_cast<int>(glsl.length());
  477. tshader->setStringsWithLengths(&csrc, &sourceLength, 1);
  478. int defaultVersion = 450;
  479. EProfile defaultProfile = ECoreProfile;
  480. bool forceDefault = false;
  481. bool forwardCompat = true;
  482. if (!tshader->parse(GetDefaultResources(), defaultVersion, defaultProfile, forceDefault, forwardCompat, EShMsgSuppressWarnings))
  483. {
  484. const char *stageName = "unknown";
  485. ShaderStage::getConstant(stage, stageName);
  486. std::string err = "Error parsing " + std::string(stageName) + " shader:\n\n"
  487. + std::string(tshader->getInfoLog()) + "\n"
  488. + std::string(tshader->getInfoDebugLog());
  489. throw love::Exception("%s", err.c_str());
  490. }
  491. program->addShader(tshader.get());
  492. glslangShaders.push_back(std::move(tshader));
  493. }
  494. if (!program->link(EShMsgDefault))
  495. throw love::Exception("link failed! %s\n", program->getInfoLog());
  496. if (!program->mapIO())
  497. throw love::Exception("mapIO failed");
  498. BindingMapper bindingMapper;
  499. for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
  500. {
  501. auto shaderStage = (ShaderStageType)i;
  502. auto glslangStage = getGlslShaderType(shaderStage);
  503. auto intermediate = program->getIntermediate(glslangStage);
  504. if (intermediate == nullptr)
  505. continue;
  506. spv::SpvBuildLogger logger;
  507. glslang::SpvOptions opt;
  508. opt.validate = true;
  509. std::vector<uint32_t> spirv;
  510. GlslangToSpv(*intermediate, spirv, &logger, &opt);
  511. spirv_cross::CompilerGLSL comp(spirv);
  512. // we only care about variables that are actually getting used.
  513. auto active = comp.get_active_interface_variables();
  514. auto shaderResources = comp.get_shader_resources(active);
  515. comp.set_enabled_interface_variables(std::move(active));
  516. for (const auto &resource : shaderResources.uniform_buffers)
  517. {
  518. if (resource.name == "gl_DefaultUniformBlock")
  519. {
  520. const auto &type = comp.get_type(resource.base_type_id);
  521. size_t defaultUniformBlockSize = comp.get_declared_struct_size(type);
  522. localUniformStagingData.resize(defaultUniformBlockSize);
  523. localUniformData.resize(defaultUniformBlockSize);
  524. localUniformLocation = bindingMapper(comp, spirv, resource.name, resource.id);
  525. memset(localUniformStagingData.data(), 0, defaultUniformBlockSize);
  526. memset(localUniformData.data(), 0, defaultUniformBlockSize);
  527. std::string basename("");
  528. buildLocalUniforms(comp, type, 0, basename);
  529. memcpy(localUniformData.data(), localUniformStagingData.data(), localUniformStagingData.size());
  530. }
  531. else
  532. throw love::Exception("unimplemented: non default uniform blocks.");
  533. }
  534. for (const auto &r : shaderResources.sampled_images)
  535. {
  536. std::string name = canonicaliizeUniformName(r.name);
  537. auto uniformit = reflection.allUniforms.find(name);
  538. if (uniformit == reflection.allUniforms.end())
  539. {
  540. handleUnknownUniformName(name.c_str());
  541. continue;
  542. }
  543. UniformInfo &u = *(uniformit->second);
  544. u.active = true;
  545. u.location = bindingMapper(comp, spirv, name, r.id);
  546. BuiltinUniform builtin;
  547. if (getConstant(name.c_str(), builtin))
  548. builtinUniformInfo[builtin] = &u;
  549. }
  550. for (const auto &r : shaderResources.storage_buffers)
  551. {
  552. std::string name = canonicaliizeUniformName(r.name);
  553. const auto &uniformit = reflection.storageBuffers.find(name);
  554. if (uniformit == reflection.storageBuffers.end())
  555. {
  556. handleUnknownUniformName(name.c_str());
  557. continue;
  558. }
  559. UniformInfo &u = uniformit->second;
  560. u.active = true;
  561. u.location = bindingMapper(comp, spirv, name, r.id);
  562. }
  563. for (const auto &r : shaderResources.storage_images)
  564. {
  565. std::string name = canonicaliizeUniformName(r.name);
  566. const auto &uniformit = reflection.storageBuffers.find(name);
  567. if (uniformit == reflection.storageBuffers.end())
  568. {
  569. handleUnknownUniformName(name.c_str());
  570. continue;
  571. }
  572. UniformInfo &u = uniformit->second;
  573. u.active = true;
  574. u.location = bindingMapper(comp, spirv, name, r.id);
  575. }
  576. if (shaderStage == SHADERSTAGE_VERTEX)
  577. {
  578. int nextAttributeIndex = ATTRIB_MAX_ENUM;
  579. for (const auto &r : shaderResources.stage_inputs)
  580. {
  581. int index;
  582. BuiltinVertexAttribute builtinAttribute;
  583. if (graphics::getConstant(r.name.c_str(), builtinAttribute))
  584. index = (int)builtinAttribute;
  585. else
  586. index = nextAttributeIndex++;
  587. uint32_t locationOffset;
  588. if (!comp.get_binary_offset_for_decoration(r.id, spv::DecorationLocation, locationOffset))
  589. throw love::Exception("could not get binary offset for vertex attribute %s location", r.name.c_str());
  590. spirv[locationOffset] = (uint32_t)index;
  591. attributes[r.name] = index;
  592. }
  593. }
  594. VkShaderModuleCreateInfo createInfo{};
  595. createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  596. createInfo.codeSize = spirv.size() * sizeof(uint32_t);
  597. createInfo.pCode = spirv.data();
  598. VkShaderModule shaderModule;
  599. if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
  600. throw love::Exception("failed to create shader module");
  601. std::string debugname = getShaderStageDebugName(shaderStage);
  602. if (!debugname.empty() && vgfx->getEnabledOptionalInstanceExtensions().debugInfo)
  603. {
  604. auto device = vgfx->getDevice();
  605. VkDebugUtilsObjectNameInfoEXT nameInfo{};
  606. nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
  607. nameInfo.objectType = VK_OBJECT_TYPE_SHADER_MODULE;
  608. nameInfo.objectHandle = (uint64_t)shaderModule;
  609. nameInfo.pObjectName = debugname.c_str();
  610. vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
  611. }
  612. shaderModules.push_back(shaderModule);
  613. VkPipelineShaderStageCreateInfo shaderStageInfo{};
  614. shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  615. shaderStageInfo.stage = getStageBit((ShaderStageType)i);
  616. shaderStageInfo.module = shaderModule;
  617. shaderStageInfo.pName = "main";
  618. shaderStages.push_back(shaderStageInfo);
  619. }
  620. numBuffers = 0;
  621. numTextures = 0;
  622. numBufferViews = 0;
  623. if (localUniformData.size() > 0)
  624. numBuffers++;
  625. for (const auto kvp : reflection.allUniforms)
  626. {
  627. if (kvp.second->location < 0)
  628. continue;
  629. switch (kvp.second->baseType)
  630. {
  631. case UNIFORM_SAMPLER:
  632. case UNIFORM_STORAGETEXTURE:
  633. numTextures++;
  634. break;
  635. case UNIFORM_STORAGEBUFFER:
  636. numBuffers++;
  637. break;
  638. case UNIFORM_TEXELBUFFER:
  639. numBufferViews++;
  640. break;
  641. default:
  642. continue;
  643. }
  644. }
  645. }
  646. void Shader::createDescriptorSetLayout()
  647. {
  648. std::vector<VkDescriptorSetLayoutBinding> bindings;
  649. VkShaderStageFlags stageFlags;
  650. if (isCompute)
  651. stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
  652. else
  653. stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
  654. for (auto const &entry : reflection.allUniforms)
  655. {
  656. auto type = Vulkan::getDescriptorType(entry.second->baseType);
  657. if (type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
  658. {
  659. VkDescriptorSetLayoutBinding layoutBinding{};
  660. layoutBinding.binding = entry.second->location;
  661. layoutBinding.descriptorType = type;
  662. layoutBinding.descriptorCount = entry.second->count;
  663. layoutBinding.stageFlags = stageFlags;
  664. bindings.push_back(layoutBinding);
  665. }
  666. }
  667. if (!localUniformStagingData.empty())
  668. {
  669. VkDescriptorSetLayoutBinding uniformBinding{};
  670. uniformBinding.binding = localUniformLocation;
  671. uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  672. uniformBinding.descriptorCount = 1;
  673. uniformBinding.stageFlags = stageFlags;
  674. bindings.push_back(uniformBinding);
  675. }
  676. VkDescriptorSetLayoutCreateInfo layoutInfo{};
  677. layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  678. layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
  679. layoutInfo.pBindings = bindings.data();
  680. if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS)
  681. throw love::Exception("failed to create descriptor set layout");
  682. }
  683. void Shader::createPipelineLayout()
  684. {
  685. VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
  686. pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  687. pipelineLayoutInfo.setLayoutCount = 1;
  688. pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
  689. pipelineLayoutInfo.pushConstantRangeCount = 0;
  690. if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
  691. throw love::Exception("failed to create pipeline layout");
  692. if (isCompute)
  693. {
  694. assert(shaderStages.size() == 1);
  695. VkComputePipelineCreateInfo computeInfo{};
  696. computeInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
  697. computeInfo.stage = shaderStages.at(0);
  698. computeInfo.layout = pipelineLayout;
  699. if (vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &computeInfo, nullptr, &computePipeline) != VK_SUCCESS)
  700. throw love::Exception("failed to create compute pipeline");
  701. }
  702. }
  703. void Shader::createDescriptorPoolSizes()
  704. {
  705. if (!localUniformData.empty())
  706. {
  707. VkDescriptorPoolSize size{};
  708. size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  709. size.descriptorCount = 1;
  710. descriptorPoolSizes.push_back(size);
  711. }
  712. for (const auto &entry : reflection.allUniforms)
  713. {
  714. if (entry.second->location < 0)
  715. continue;
  716. VkDescriptorPoolSize size{};
  717. auto type = Vulkan::getDescriptorType(entry.second->baseType);
  718. if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
  719. continue;
  720. size.type = type;
  721. size.descriptorCount = 1;
  722. descriptorPoolSizes.push_back(size);
  723. }
  724. }
  725. void Shader::createStreamBuffers()
  726. {
  727. size_t size = STREAMBUFFER_DEFAULT_SIZE * uniformBufferSizeAligned;
  728. if (size > 0)
  729. streamBuffers.push_back(new StreamBuffer(vgfx, BUFFERUSAGE_UNIFORM, size));
  730. }
  731. void Shader::setVideoTextures(graphics::Texture *ytexture, graphics::Texture *cbtexture, graphics::Texture *crtexture)
  732. {
  733. std::array<graphics::Texture*, 3> textures = {
  734. ytexture, cbtexture, crtexture
  735. };
  736. std::array<BuiltinUniform, 3> builtIns = {
  737. BUILTIN_TEXTURE_VIDEO_Y,
  738. BUILTIN_TEXTURE_VIDEO_CB,
  739. BUILTIN_TEXTURE_VIDEO_CR,
  740. };
  741. static_assert(textures.size() == builtIns.size(), "expected number of textures to be the same");
  742. for (size_t i = 0; i < textures.size(); i++)
  743. {
  744. const UniformInfo *u = builtinUniformInfo[builtIns[i]];
  745. if (u != nullptr)
  746. {
  747. textures[i]->retain();
  748. if (activeTextures[u->resourceIndex])
  749. activeTextures[u->resourceIndex]->release();
  750. activeTextures[u->resourceIndex] = textures[i];
  751. }
  752. }
  753. }
  754. void Shader::setMainTex(graphics::Texture *texture)
  755. {
  756. const UniformInfo *u = builtinUniformInfo[BUILTIN_TEXTURE_MAIN];
  757. if (u != nullptr)
  758. {
  759. texture->retain();
  760. if (activeTextures[u->resourceIndex])
  761. activeTextures[u->resourceIndex]->release();
  762. activeTextures[u->resourceIndex] = texture;
  763. }
  764. }
  765. void Shader::createDescriptorPool()
  766. {
  767. VkDescriptorPoolCreateInfo createInfo{};
  768. createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  769. createInfo.maxSets = DESCRIPTOR_POOL_SIZE;
  770. createInfo.poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size());
  771. createInfo.pPoolSizes = descriptorPoolSizes.data();
  772. VkDescriptorPool pool;
  773. if (vkCreateDescriptorPool(device, &createInfo, nullptr, &pool) != VK_SUCCESS)
  774. throw love::Exception("failed to create descriptor pool");
  775. descriptorPools[currentFrame].push_back(pool);
  776. }
  777. VkDescriptorSet Shader::allocateDescriptorSet()
  778. {
  779. if (descriptorPools[currentFrame].empty())
  780. createDescriptorPool();
  781. while (true)
  782. {
  783. VkDescriptorSetAllocateInfo allocInfo{};
  784. allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  785. allocInfo.descriptorPool = descriptorPools[currentFrame][currentDescriptorPool];
  786. allocInfo.descriptorSetCount = 1;
  787. allocInfo.pSetLayouts = &descriptorSetLayout;
  788. VkDescriptorSet descriptorSet;
  789. VkResult result = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet);
  790. switch (result)
  791. {
  792. case VK_SUCCESS:
  793. return descriptorSet;
  794. case VK_ERROR_OUT_OF_POOL_MEMORY:
  795. currentDescriptorPool++;
  796. if (descriptorPools[currentFrame].size() <= currentDescriptorPool)
  797. createDescriptorPool();
  798. continue;
  799. default:
  800. throw love::Exception("failed to allocate descriptor set");
  801. }
  802. }
  803. }
  804. } // vulkan
  805. } // graphics
  806. } // love