MythTV  master
mythshadervulkan.cpp
Go to the documentation of this file.
1 // MythTV
5 
6 // Std
7 #include <algorithm>
8 
9 #define LOC QString("VulkanShader: ")
10 
11 // libglslang
12 #ifdef USING_GLSLANG
13 #include <glslang/Public/ShaderLang.h>
14 #include <glslang/SPIRV/GlslangToSpv.h>
15 
16 static const TBuiltInResource s_TBuiltInResource = {
17  /* .MaxLights = */ 32,
18  /* .MaxClipPlanes = */ 6,
19  /* .MaxTextureUnits = */ 32,
20  /* .MaxTextureCoords = */ 32,
21  /* .MaxVertexAttribs = */ 64,
22  /* .MaxVertexUniformComponents = */ 4096,
23  /* .MaxVaryingFloats = */ 64,
24  /* .MaxVertexTextureImageUnits = */ 32,
25  /* .MaxCombinedTextureImageUnits = */ 80,
26  /* .MaxTextureImageUnits = */ 32,
27  /* .MaxFragmentUniformComponents = */ 4096,
28  /* .MaxDrawBuffers = */ 32,
29  /* .MaxVertexUniformVectors = */ 128,
30  /* .MaxVaryingVectors = */ 8,
31  /* .MaxFragmentUniformVectors = */ 16,
32  /* .MaxVertexOutputVectors = */ 16,
33  /* .MaxFragmentInputVectors = */ 15,
34  /* .MinProgramTexelOffset = */ -8,
35  /* .MaxProgramTexelOffset = */ 7,
36  /* .MaxClipDistances = */ 8,
37  /* .MaxComputeWorkGroupCountX = */ 65535,
38  /* .MaxComputeWorkGroupCountY = */ 65535,
39  /* .MaxComputeWorkGroupCountZ = */ 65535,
40  /* .MaxComputeWorkGroupSizeX = */ 1024,
41  /* .MaxComputeWorkGroupSizeY = */ 1024,
42  /* .MaxComputeWorkGroupSizeZ = */ 64,
43  /* .MaxComputeUniformComponents = */ 1024,
44  /* .MaxComputeTextureImageUnits = */ 16,
45  /* .MaxComputeImageUniforms = */ 8,
46  /* .MaxComputeAtomicCounters = */ 8,
47  /* .MaxComputeAtomicCounterBuffers = */ 1,
48  /* .MaxVaryingComponents = */ 60,
49  /* .MaxVertexOutputComponents = */ 64,
50  /* .MaxGeometryInputComponents = */ 64,
51  /* .MaxGeometryOutputComponents = */ 128,
52  /* .MaxFragmentInputComponents = */ 128,
53  /* .MaxImageUnits = */ 8,
54  /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
55  /* .MaxCombinedShaderOutputResources = */ 8,
56  /* .MaxImageSamples = */ 0,
57  /* .MaxVertexImageUniforms = */ 0,
58  /* .MaxTessControlImageUniforms = */ 0,
59  /* .MaxTessEvaluationImageUniforms = */ 0,
60  /* .MaxGeometryImageUniforms = */ 0,
61  /* .MaxFragmentImageUniforms = */ 8,
62  /* .MaxCombinedImageUniforms = */ 8,
63  /* .MaxGeometryTextureImageUnits = */ 16,
64  /* .MaxGeometryOutputVertices = */ 256,
65  /* .MaxGeometryTotalOutputComponents = */ 1024,
66  /* .MaxGeometryUniformComponents = */ 1024,
67  /* .MaxGeometryVaryingComponents = */ 64,
68  /* .MaxTessControlInputComponents = */ 128,
69  /* .MaxTessControlOutputComponents = */ 128,
70  /* .MaxTessControlTextureImageUnits = */ 16,
71  /* .MaxTessControlUniformComponents = */ 1024,
72  /* .MaxTessControlTotalOutputComponents = */ 4096,
73  /* .MaxTessEvaluationInputComponents = */ 128,
74  /* .MaxTessEvaluationOutputComponents = */ 128,
75  /* .MaxTessEvaluationTextureImageUnits = */ 16,
76  /* .MaxTessEvaluationUniformComponents = */ 1024,
77  /* .MaxTessPatchComponents = */ 120,
78  /* .MaxPatchVertices = */ 32,
79  /* .MaxTessGenLevel = */ 64,
80  /* .MaxViewports = */ 16,
81  /* .MaxVertexAtomicCounters = */ 0,
82  /* .MaxTessControlAtomicCounters = */ 0,
83  /* .MaxTessEvaluationAtomicCounters = */ 0,
84  /* .MaxGeometryAtomicCounters = */ 0,
85  /* .MaxFragmentAtomicCounters = */ 8,
86  /* .MaxCombinedAtomicCounters = */ 8,
87  /* .MaxAtomicCounterBindings = */ 1,
88  /* .MaxVertexAtomicCounterBuffers = */ 0,
89  /* .MaxTessControlAtomicCounterBuffers = */ 0,
90  /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
91  /* .MaxGeometryAtomicCounterBuffers = */ 0,
92  /* .MaxFragmentAtomicCounterBuffers = */ 1,
93  /* .MaxCombinedAtomicCounterBuffers = */ 1,
94  /* .MaxAtomicCounterBufferSize = */ 16384,
95  /* .MaxTransformFeedbackBuffers = */ 4,
96  /* .MaxTransformFeedbackInterleavedComponents = */ 64,
97  /* .MaxCullDistances = */ 8,
98  /* .MaxCombinedClipAndCullDistances = */ 8,
99  /* .MaxSamples = */ 4,
100  /* .maxMeshOutputVerticesNV = */ 256,
101  /* .maxMeshOutputPrimitivesNV = */ 512,
102  /* .maxMeshWorkGroupSizeX_NV = */ 32,
103  /* .maxMeshWorkGroupSizeY_NV = */ 1,
104  /* .maxMeshWorkGroupSizeZ_NV = */ 1,
105  /* .maxTaskWorkGroupSizeX_NV = */ 32,
106  /* .maxTaskWorkGroupSizeY_NV = */ 1,
107  /* .maxTaskWorkGroupSizeZ_NV = */ 1,
108  /* .maxMeshViewCountNV = */ 4,
109 
110  .limits = {
111  /* .nonInductiveForLoops = */ true,
112  /* .whileLoops = */ true,
113  /* .doWhileLoops = */ true,
114  /* .generalUniformIndexing = */ true,
115  /* .generalAttributeMatrixVectorIndexing = */ true,
116  /* .generalVaryingIndexing = */ true,
117  /* .generalSamplerIndexing = */ true,
118  /* .generalVariableIndexing = */ true,
119  /* .generalConstantMatrixVectorIndexing = */ true,
120  }
121 };
122 
123 static auto GLSLangCompile(EShLanguage Stage, const QString &Code)
124 {
125  std::vector<uint32_t> result;
126  auto *shader = new glslang::TShader(Stage);
127  if (!shader)
128  return result;
129 
130  QByteArray data = Code.toLocal8Bit();
131  const char *tmp = data.constData();
132  shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1);
133  shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
134  shader->setStrings(&tmp, 1);
135  if (!shader->parse(&s_TBuiltInResource, glslang::EShTargetVulkan_1_1, true, EShMsgDefault))
136  {
137  LOG(VB_GENERAL, LOG_ERR, LOC + "Shader parse error:");
138  LOG(VB_GENERAL, LOG_ERR, shader->getInfoLog());
139  delete shader;
140  return result;
141  }
142 
143  auto *program = new glslang::TProgram();
144  if (!program)
145  {
146  delete shader;
147  return result;
148  }
149 
150  program->addShader(shader);
151  if (program->link(EShMsgDefault))
152  {
153  auto ByteCodeToString = [](std::vector<uint32_t> &OpCodes)
154  {
155  QString string;
156  int count = 0;
157  for (uint32_t opcode : OpCodes)
158  {
159  if (count++ == 0) string += "\n";
160  if (count > 5) count = 0;
161  string += "0x" + QString("%1, ").arg(opcode, 8, 16, QLatin1Char('0')).toUpper();
162  }
163  return string;
164  };
165 
166  glslang::SpvOptions options { };
167  options.generateDebugInfo = false;
168  options.disassemble = false;
169  options.validate = false;
170  options.disableOptimizer = false;
171  options.optimizeSize = true;
172  GlslangToSpv(*program->getIntermediate(Stage), result, &options);
173  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Generated SPIR-V: %1bytes").arg(result.size() * sizeof (uint32_t)));
174  LOG(VB_GENERAL, LOG_INFO, "Source:\n" + Code);
175  LOG(VB_GENERAL, LOG_INFO, "ByteCode:\n" + ByteCodeToString(result));
176  }
177  else
178  {
179  LOG(VB_GENERAL, LOG_ERR, LOC + "Shader link error:");
180  LOG(VB_GENERAL, LOG_ERR, program->getInfoLog());
181  }
182 
183  delete shader;
184  delete program;
185  return result;
186 }
187 
188 bool MythShaderVulkan::InitGLSLang(bool Release /* = false */)
189 {
190  static QMutex s_glslangLock;
191  static int s_glslangRefcount = 0;
192  static bool s_initSuccess = false;
193  QMutexLocker locker(&s_glslangLock);
194 
195  if (Release)
196  {
197  s_glslangRefcount--;
198  if (s_glslangRefcount < 0)
199  {
200  LOG(VB_GENERAL, LOG_ERR, LOC + "GLSLang ref count error");
201  return false;
202  }
203 
204  if (s_glslangRefcount < 1)
205  {
206  LOG(VB_GENERAL, LOG_INFO, LOC + "GLSLang released");
207  glslang::FinalizeProcess();
208  }
209  return true;
210  }
211 
212  if (s_glslangRefcount < 1)
213  {
214  s_initSuccess = glslang::InitializeProcess();
215  if (s_initSuccess)
216  LOG(VB_GENERAL, LOG_INFO, LOC + "GLSLang initialised");
217  }
218  s_glslangRefcount++;
219  return s_initSuccess;
220 }
221 
222 bool MythShaderVulkan::CreateShaderFromGLSL(const std::vector<MythGLSLStage> &Stages)
223 {
224  if (Stages.empty())
225  return false;
226 
227  if (!MythShaderVulkan::InitGLSLang())
228  return false;
229 
230  std::vector<MythSPIRVStage> spirvstages;
231 
232  auto glslangtype = [](VkShaderStageFlags Type)
233  {
234  switch (Type)
235  {
236  case VK_SHADER_STAGE_VERTEX_BIT: return EShLangVertex;
237  case VK_SHADER_STAGE_FRAGMENT_BIT: return EShLangFragment;
238  case VK_SHADER_STAGE_COMPUTE_BIT: return EShLangCompute;
239  default: break;
240  }
241  return EShLangCount;
242  };
243 
244  for (const auto& stage : Stages)
245  if (glslangtype(stage.first) != EShLangCount)
246  spirvstages.emplace_back(stage.first, GLSLangCompile(glslangtype(stage.first), stage.second));
247  MythShaderVulkan::InitGLSLang(true);
248  return CreateShaderFromSPIRV(spirvstages);
249 }
250 #endif
251 
261  const std::vector<int> &Stages,
262  const MythShaderMap *Sources,
263  const MythBindingMap *Bindings)
264 {
265  auto * result = new MythShaderVulkan(Vulkan, Stages, Sources, Bindings);
266  if (result && !result->IsValidVulkan())
267  {
268  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create shader");
269  delete result;
270  result = nullptr;
271  }
272  return result;
273 }
274 
276  const std::vector<int> &Stages,
277  const MythShaderMap *Sources,
278  const MythBindingMap *Bindings)
279  : MythVulkanObject(Vulkan)
280 {
281  if (!m_vulkanValid || Stages.empty())
282  return;
283  m_vulkanValid = false;
284 
285  if (!Sources)
286  Sources = &k450DefaultShaders;
287 
288  if (!Bindings)
289  Bindings = &k450ShaderBindings;
290 
291  // ensure we have sources and bindings
292  for (const auto & stage : Stages)
293  if (Sources->find(stage) == Sources->end() || Bindings->find(stage) == Bindings->end())
294  return;
295 
296  // build the descriptor set layouts from the shader descriptions
297  bool foundvertices = false;
298  bool pushconstants = false;
299  VkPushConstantRange ranges = { };
300 
301  std::map<int, std::vector<VkDescriptorSetLayoutBinding>> layoutbindings;
302  std::map<int, std::vector<VkDescriptorPoolSize>> poolsizes;
303  for (const auto & stage : Stages)
304  {
305  bool isvertex = false;
306  MythBindingDesc desc = Bindings->at(stage);
307  m_topology = std::get<0>(desc);
308  MythStageLayout binding = std::get<1>(desc);
309 
310  for (auto & stagelayout : binding)
311  {
312  if (stagelayout.second.stageFlags == VK_SHADER_STAGE_VERTEX_BIT)
313  isvertex = true;
314 
315  if (layoutbindings.find(stagelayout.first) != layoutbindings.end())
316  layoutbindings.at(stagelayout.first).emplace_back(stagelayout.second);
317  else
318  layoutbindings.insert( { stagelayout.first, { stagelayout.second } } );
319 
320  VkDescriptorPoolSize poolsize = {stagelayout.second.descriptorType, stagelayout.second.descriptorCount};
321  if (poolsizes.find(stagelayout.first) != poolsizes.end())
322  poolsizes.at(stagelayout.first).emplace_back(poolsize);
323  else
324  poolsizes.insert( { stagelayout.first, { poolsize } } );
325  }
326 
327  if (isvertex && !foundvertices)
328  {
329  foundvertices = true;
330  m_vertexBindingDesc = std::get<2>(desc);
331  m_vertexAttributes = std::get<3>(desc);
332  }
333 
334  if (!pushconstants)
335  {
336  VkPushConstantRange range = std::get<4>(desc);
337  if (range.stageFlags)
338  {
339  pushconstants = true;
340  ranges = range;
341  }
342  }
343  }
344 
345  // convert poolsizes to vector
346  for (const auto& poolsize : poolsizes)
347  m_descriptorPoolSizes.emplace_back(poolsize.second);
348 
349  // create the desriptor layouts
350  for (auto & layoutbinding : layoutbindings)
351  {
352  VkDescriptorSetLayout layout = MYTH_NULL_DISPATCH;
353  VkDescriptorSetLayoutCreateInfo layoutinfo { };
354  layoutinfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
355  layoutinfo.bindingCount = static_cast<uint32_t>(layoutbinding.second.size());
356  layoutinfo.pBindings = layoutbinding.second.data();
357  if (m_vulkanFuncs->vkCreateDescriptorSetLayout(m_vulkanDevice, &layoutinfo, nullptr, &layout) != VK_SUCCESS)
358  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create DescriptorSetLayout");
359  else
360  m_descriptorSetLayouts.push_back(layout);
361  }
362 
363  if (m_descriptorSetLayouts.size() != layoutbindings.size())
364  {
365  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create all layouts");
366  return;
367  }
368 
369  VkPipelineLayoutCreateInfo pipelinelayout { };
370  pipelinelayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
371  pipelinelayout.setLayoutCount = static_cast<uint32_t>(m_descriptorSetLayouts.size());
372  pipelinelayout.pSetLayouts = m_descriptorSetLayouts.data();
373 
374  if (pushconstants)
375  {
376  pipelinelayout.pushConstantRangeCount = 1;
377  pipelinelayout.pPushConstantRanges = &ranges;
378  }
379 
380  if (m_vulkanFuncs->vkCreatePipelineLayout(m_vulkanDevice, &pipelinelayout, nullptr, &m_pipelineLayout) != VK_SUCCESS)
381  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create pipeline layout");
382 
383  if (!m_pipelineLayout)
384  return;
385 
386 #ifdef USING_GLSLANG
387  static bool useglsl = qEnvironmentVariableIsSet("MYTHTV_GLSLANG");
388  if (useglsl)
389  {
390  std::vector<MythGLSLStage> glslstages;
391  std::transform(Stages.cbegin(), Stages.cend(), std::back_inserter(glslstages),
392  [&](int Stage) { return MythGLSLStage{Stage & VK_SHADER_STAGE_ALL_GRAPHICS, Sources->at(Stage).first }; });
393  m_vulkanValid = MythShaderVulkan::CreateShaderFromGLSL(glslstages);
394  return;
395  }
396 #endif
397 
398  std::vector<MythSPIRVStage> stages;
399  std::transform(Stages.cbegin(), Stages.cend(), std::back_inserter(stages),
400  [&](int Stage) { return MythSPIRVStage{Stage & VK_SHADER_STAGE_ALL_GRAPHICS, Sources->at(Stage).second }; });
401  m_vulkanValid = MythShaderVulkan::CreateShaderFromSPIRV(stages);
402 }
403 
405 {
406  if (m_vulkanValid)
407  {
408  m_vulkanFuncs->vkDestroyPipelineLayout(m_vulkanDevice, m_pipelineLayout, nullptr);
409  for (auto & layout : m_descriptorSetLayouts)
410  m_vulkanFuncs->vkDestroyDescriptorSetLayout(m_vulkanDevice, layout, nullptr);
411  for (auto & stage : m_stages)
412  m_vulkanFuncs->vkDestroyShaderModule(m_vulkanDevice, stage.module, nullptr);
413  }
414  for (auto * spirv : m_spirv)
415  delete [] spirv;
416 }
417 
418 bool MythShaderVulkan::CreateShaderFromSPIRV(const std::vector<MythSPIRVStage> &Stages)
419 {
420  if (Stages.empty())
421  return false;
422 
423  if (std::any_of(Stages.cbegin(), Stages.cend(), [](const MythSPIRVStage& Stage) { return Stage.second.empty(); }))
424  return false;
425 
426  bool success = true;
427  for (const auto & stage : Stages)
428  {
429  auto size = stage.second.size() * sizeof (uint32_t);
430  auto *code = reinterpret_cast<uint32_t*>(new uint8_t [size]);
431  memcpy(code, stage.second.data(), size);
432  VkShaderModule module = MYTH_NULL_DISPATCH;
433  VkShaderModuleCreateInfo create { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, nullptr, 0, size, code };
434  success &= (m_vulkanFuncs->vkCreateShaderModule(m_vulkanDevice, &create, nullptr, &module) == VK_SUCCESS);
435  m_stages.push_back( { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr,
436  0, static_cast<VkShaderStageFlagBits>(stage.first), module, "main", nullptr } );
437  m_spirv.push_back(code);
438  }
439  return success;
440 }
441 
442 const std::vector<VkPipelineShaderStageCreateInfo>& MythShaderVulkan::Stages(void) const
443 {
444  return m_stages;
445 }
446 
447 
449 {
450  return m_vertexAttributes;
451 }
452 
453 const VkVertexInputBindingDescription& MythShaderVulkan::GetVertexBindingDesc(void) const
454 {
455  return m_vertexBindingDesc;
456 }
457 
458 VkPipelineLayout MythShaderVulkan::GetPipelineLayout(void) const
459 {
460  return m_pipelineLayout;
461 }
462 
463 const std::vector<VkDescriptorPoolSize>& MythShaderVulkan::GetPoolSizes(size_t Set) const
464 {
465  if (Set < m_descriptorPoolSizes.size())
466  return m_descriptorPoolSizes.at(Set);
467  static const std::vector<VkDescriptorPoolSize> broken;
468  return broken;
469 }
470 
471 VkDescriptorSetLayout MythShaderVulkan::GetDescSetLayout(size_t Set) const
472 {
473  if (Set < m_descriptorSetLayouts.size())
474  return m_descriptorSetLayouts.at(Set);
475  return MYTH_NULL_DISPATCH;
476 }
477 
478 VkPrimitiveTopology MythShaderVulkan::GetTopology() const
479 {
480  return m_topology;
481 }
MythShaderVulkan::GetDescSetLayout
VkDescriptorSetLayout GetDescSetLayout(size_t Set) const
Definition: mythshadervulkan.cpp:471
MythShaderVulkan::GetPoolSizes
const std::vector< VkDescriptorPoolSize > & GetPoolSizes(size_t Set) const
Definition: mythshadervulkan.cpp:463
MythBindingDesc
std::tuple< VkPrimitiveTopology, MythStageLayout, VkVertexInputBindingDescription, MythVertexAttrs, VkPushConstantRange > MythBindingDesc
Definition: mythshadervulkan.h:17
MythShaderVulkan::~MythShaderVulkan
~MythShaderVulkan()
Definition: mythshadervulkan.cpp:404
MythVulkanObject
Definition: mythrendervulkan.h:32
MythShaderVulkan::m_descriptorSetLayouts
std::vector< VkDescriptorSetLayout > m_descriptorSetLayouts
Definition: mythshadervulkan.h:62
MYTH_NULL_DISPATCH
#define MYTH_NULL_DISPATCH
Definition: mythrendervulkan.h:29
MythShaderVulkan::m_topology
VkPrimitiveTopology m_topology
Definition: mythshadervulkan.h:54
MythShaderVulkan::GetVertexBindingDesc
const VkVertexInputBindingDescription & GetVertexBindingDesc(void) const
Definition: mythshadervulkan.cpp:453
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythVulkanObject::m_vulkanValid
bool m_vulkanValid
Definition: mythrendervulkan.h:47
MythSPIRVStage
std::pair< VkShaderStageFlags, const std::vector< uint32_t > > MythSPIRVStage
Definition: mythshadervulkan.h:9
MythShaderVulkan::m_stages
std::vector< VkPipelineShaderStageCreateInfo > m_stages
Definition: mythshadervulkan.h:57
MythShaderVulkan::m_spirv
std::vector< uint32_t * > m_spirv
Definition: mythshadervulkan.h:58
MythShaderVulkan::Create
static MythShaderVulkan * Create(MythVulkanObject *Vulkan, const std::vector< int > &Stages, const MythShaderMap *Sources=nullptr, const MythBindingMap *Bindings=nullptr)
Definition: mythshadervulkan.cpp:260
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
k450DefaultShaders
static const MythShaderMap k450DefaultShaders
Definition: mythshadersvulkan.h:43
MythVulkanObject::m_vulkanDevice
VkDevice m_vulkanDevice
Definition: mythrendervulkan.h:49
MythShaderVulkan::Stages
const std::vector< VkPipelineShaderStageCreateInfo > & Stages(void) const
Definition: mythshadervulkan.cpp:442
MythShaderVulkan::m_vertexBindingDesc
VkVertexInputBindingDescription m_vertexBindingDesc
Definition: mythshadervulkan.h:55
mythlogging.h
MythShaderVulkan::GetPipelineLayout
VkPipelineLayout GetPipelineLayout(void) const
Definition: mythshadervulkan.cpp:458
LOC
#define LOC
Definition: mythshadervulkan.cpp:9
MythStageLayout
std::vector< MythSetLayout > MythStageLayout
Definition: mythshadervulkan.h:12
mythshadervulkan.h
MythShaderVulkan::MythShaderVulkan
MythShaderVulkan(MythVulkanObject *Vulkan, const std::vector< int > &Stages, const MythShaderMap *Sources=nullptr, const MythBindingMap *Bindings=nullptr)
Definition: mythshadervulkan.cpp:275
MythBindingMap
std::map< int, MythBindingDesc > MythBindingMap
Definition: mythshadervulkan.h:18
MythVulkanObject::m_vulkanFuncs
QVulkanDeviceFunctions * m_vulkanFuncs
Definition: mythrendervulkan.h:50
MythShaderVulkan::m_pipelineLayout
VkPipelineLayout m_pipelineLayout
Definition: mythshadervulkan.h:59
MythShaderVulkan::GetTopology
VkPrimitiveTopology GetTopology() const
Definition: mythshadervulkan.cpp:478
MythShaderVulkan::m_vertexAttributes
MythVertexAttrs m_vertexAttributes
Definition: mythshadervulkan.h:56
MythShaderVulkan::m_descriptorPoolSizes
std::vector< std::vector< VkDescriptorPoolSize > > m_descriptorPoolSizes
Definition: mythshadervulkan.h:63
MythShaderVulkan::CreateShaderFromSPIRV
bool CreateShaderFromSPIRV(const std::vector< MythSPIRVStage > &Stages)
Definition: mythshadervulkan.cpp:418
MythShaderVulkan::GetVertexAttributes
const MythVertexAttrs & GetVertexAttributes(void) const
Definition: mythshadervulkan.cpp:448
MythShaderMap
std::map< int, std::pair< QString, std::vector< uint32_t > >> MythShaderMap
Definition: mythshadervulkan.h:7
MythVertexAttrs
std::vector< VkVertexInputAttributeDescription > MythVertexAttrs
Definition: mythshadervulkan.h:10
k450ShaderBindings
static const MythBindingMap k450ShaderBindings
Definition: mythshadersvulkan.h:26
MythShaderVulkan
Creates shader objects suitable for use with the Vulkan API.
Definition: mythshadervulkan.h:20
mythshadersvulkan.h
build_compdb.options
options
Definition: build_compdb.py:11