Line data Source code
1 : /**
2 : Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "XLVkPipeline.h"
25 : #include "XLVkDevice.h"
26 : #include "XLVkRenderPass.h"
27 :
28 : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
29 :
30 5847 : static BytesView Shader_emplaceConstant(Bytes &data, BytesView constant) {
31 5847 : auto originalSize = data.size();
32 5847 : auto constantSize = constant.size();
33 5849 : data.resize(originalSize + constantSize);
34 5846 : memcpy(data.data() + originalSize, constant.data(), constantSize);
35 5845 : return BytesView(data.data() + originalSize, constantSize);
36 : }
37 :
38 0 : static BytesView Shader_emplaceConstant(Bytes &data, float constant) {
39 0 : return Shader_emplaceConstant(data, BytesView((const uint8_t *)&constant, sizeof(float)));
40 : }
41 :
42 5847 : static BytesView Shader_emplaceConstant(Bytes &data, int constant) {
43 5847 : return Shader_emplaceConstant(data, BytesView((const uint8_t *)&constant, sizeof(int)));
44 : }
45 :
46 1596 : bool Shader::init(Device &dev, const ProgramData &data) {
47 1596 : _stage = data.stage;
48 1596 : _name = data.key.str<Interface>();
49 :
50 1596 : if (!data.data.empty()) {
51 1596 : return setup(dev, data, data.data);
52 0 : } else if (data.callback != nullptr) {
53 0 : bool ret = false;
54 0 : data.callback([&, this] (SpanView<uint32_t> shaderData) {
55 0 : ret = setup(dev, data, shaderData);
56 0 : });
57 0 : return ret;
58 : }
59 :
60 0 : return false;
61 : }
62 :
63 1596 : bool Shader::setup(Device &dev, const ProgramData &programData, SpanView<uint32_t> data) {
64 1596 : VkShaderModuleCreateInfo createInfo{}; sanitizeVkStruct(createInfo);
65 1596 : createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
66 1596 : createInfo.codeSize = data.size() * sizeof(uint32_t);
67 1596 : createInfo.flags = 0;
68 1596 : createInfo.pCode = data.data();
69 :
70 1596 : if (dev.getTable()->vkCreateShaderModule(dev.getDevice(), &createInfo, nullptr, &_shaderModule) == VK_SUCCESS) {
71 1596 : return core::Shader::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
72 1596 : auto d = ((Device *)dev);
73 1596 : d->getTable()->vkDestroyShaderModule(d->getDevice(), (VkShaderModule)ptr.get(), nullptr);
74 3192 : }, core::ObjectType::ShaderModule, ObjectHandle(_shaderModule));
75 : }
76 0 : return false;
77 : }
78 :
79 0 : bool GraphicPipeline::comparePipelineOrdering(const PipelineInfo &l, const PipelineInfo &r) {
80 0 : if (l.material.getDepthInfo().writeEnabled != r.material.getDepthInfo().writeEnabled) {
81 0 : if (l.material.getDepthInfo().writeEnabled) {
82 0 : return true; // pipelines with depth write comes first
83 : }
84 0 : return false;
85 0 : } else if (l.material.getBlendInfo().enabled != r.material.getBlendInfo().enabled) {
86 0 : if (!l.material.getBlendInfo().enabled) {
87 0 : return true; // pipelines without blending comes first
88 : }
89 0 : return false;
90 : } else {
91 0 : return &l < &r;
92 : }
93 : }
94 :
95 84 : bool GraphicPipeline::init(Device &dev, const PipelineData ¶ms, const SubpassData &pass, const Queue &queue) {
96 84 : VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; sanitizeVkStruct(vertexInputInfo);
97 84 : vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
98 84 : vertexInputInfo.pNext = nullptr;
99 84 : vertexInputInfo.vertexBindingDescriptionCount = 0;
100 84 : vertexInputInfo.pVertexBindingDescriptions = nullptr; // Optional
101 84 : vertexInputInfo.vertexAttributeDescriptionCount = 0;
102 84 : vertexInputInfo.pVertexAttributeDescriptions = nullptr; // Optional
103 :
104 84 : VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; sanitizeVkStruct(inputAssembly);
105 84 : inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
106 84 : inputAssembly.pNext = nullptr;
107 84 : inputAssembly.flags = 0;
108 84 : inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
109 84 : inputAssembly.primitiveRestartEnable = VK_FALSE;
110 :
111 84 : VkViewport viewport{}; sanitizeVkStruct(viewport);
112 84 : viewport.x = 0.0f;
113 84 : viewport.y = 0.0f;
114 84 : viewport.width = 0.0f;
115 84 : viewport.height = 0.0f;
116 84 : viewport.minDepth = 0.0f;
117 84 : viewport.maxDepth = 1.0f;
118 :
119 84 : VkRect2D scissor{}; sanitizeVkStruct(scissor);
120 84 : scissor.offset.x = 0;
121 84 : scissor.offset.y = 0;
122 84 : scissor.extent.width = 0;
123 84 : scissor.extent.height = 0;
124 :
125 84 : VkPipelineViewportStateCreateInfo viewportState{}; sanitizeVkStruct(viewportState);
126 84 : viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
127 84 : viewportState.pNext = nullptr;
128 84 : viewportState.flags = 0;
129 84 : viewportState.viewportCount = 1;
130 84 : viewportState.pViewports = &viewport;
131 84 : viewportState.scissorCount = 1;
132 84 : viewportState.pScissors = &scissor;
133 :
134 84 : VkPipelineRasterizationStateCreateInfo rasterizer{}; sanitizeVkStruct(rasterizer);
135 84 : rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
136 84 : rasterizer.pNext = nullptr;
137 84 : rasterizer.flags = 0;
138 84 : rasterizer.depthClampEnable = VK_FALSE;
139 84 : rasterizer.rasterizerDiscardEnable = VK_FALSE;
140 :
141 84 : if (params.material.getLineWidth() == 0.0f || !dev.hasNonSolidFillMode()) {
142 63 : rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
143 63 : rasterizer.lineWidth = 1.0f;
144 21 : } else if (params.material.getLineWidth() > 0.0f) {
145 21 : rasterizer.polygonMode = VK_POLYGON_MODE_LINE;
146 21 : rasterizer.lineWidth = params.material.getLineWidth();
147 0 : } else if (params.material.getLineWidth() < 0.0f) {
148 0 : rasterizer.polygonMode = VK_POLYGON_MODE_POINT;
149 0 : rasterizer.lineWidth = - params.material.getLineWidth();
150 : }
151 :
152 84 : rasterizer.cullMode = VK_CULL_MODE_NONE;
153 84 : rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
154 84 : rasterizer.depthBiasEnable = VK_FALSE;
155 84 : rasterizer.depthBiasConstantFactor = 0.0f; // Optional
156 84 : rasterizer.depthBiasClamp = 0.0f; // Optional
157 84 : rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
158 :
159 84 : VkPipelineMultisampleStateCreateInfo multisampling{}; sanitizeVkStruct(multisampling);
160 84 : multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
161 84 : multisampling.pNext = nullptr;
162 84 : multisampling.flags = 0;
163 84 : multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
164 84 : multisampling.sampleShadingEnable = VK_FALSE;
165 84 : multisampling.minSampleShading = 1.0f; // Optional
166 84 : multisampling.pSampleMask = nullptr; // Optional
167 84 : multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
168 84 : multisampling.alphaToOneEnable = VK_FALSE; // Optional
169 :
170 84 : Vector<VkPipelineColorBlendAttachmentState> colorBlendAttachments;
171 231 : for (size_t i = 0; i < pass.outputImages.size(); ++ i) {
172 147 : core::BlendInfo blend;
173 147 : if (pass.outputImages[i]->blendInfo.enabled) {
174 63 : blend = pass.outputImages[i]->blendInfo;
175 : } else {
176 84 : blend = params.material.getBlendInfo();
177 : }
178 :
179 147 : colorBlendAttachments.emplace_back(VkPipelineColorBlendAttachmentState{
180 147 : blend.isEnabled() ? VK_TRUE : VK_FALSE,
181 147 : VkBlendFactor(blend.srcColor),
182 147 : VkBlendFactor(blend.dstColor),
183 147 : VkBlendOp(blend.opColor),
184 147 : VkBlendFactor(blend.srcAlpha),
185 147 : VkBlendFactor(blend.dstAlpha),
186 147 : VkBlendOp(blend.opAlpha),
187 147 : VkColorComponentFlags(blend.writeMask),
188 : });
189 : }
190 :
191 84 : VkPipelineColorBlendStateCreateInfo colorBlending{}; sanitizeVkStruct(colorBlending);
192 84 : colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
193 84 : colorBlending.pNext = nullptr;
194 84 : colorBlending.flags = 0;
195 84 : colorBlending.logicOpEnable = VK_FALSE;
196 84 : colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
197 84 : colorBlending.attachmentCount = colorBlendAttachments.size();
198 84 : colorBlending.pAttachments = colorBlendAttachments.data();
199 84 : colorBlending.blendConstants[0] = 0.0f; // Optional
200 84 : colorBlending.blendConstants[1] = 0.0f; // Optional
201 84 : colorBlending.blendConstants[2] = 0.0f; // Optional
202 84 : colorBlending.blendConstants[3] = 0.0f; // Optional
203 :
204 84 : Vector<VkDynamicState> dynamicStates;
205 :
206 84 : if ((params.dynamicState & core::DynamicState::Viewport) != core::DynamicState::None) {
207 84 : dynamicStates.emplace_back(VK_DYNAMIC_STATE_VIEWPORT);
208 : }
209 :
210 84 : if ((params.dynamicState & core::DynamicState::Scissor) != core::DynamicState::None) {
211 84 : dynamicStates.emplace_back(VK_DYNAMIC_STATE_SCISSOR);
212 : }
213 :
214 84 : VkPipelineDynamicStateCreateInfo dynamicState{}; sanitizeVkStruct(dynamicState);
215 84 : dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
216 84 : dynamicState.pNext = nullptr;
217 84 : dynamicState.flags = 0;
218 84 : dynamicState.dynamicStateCount = dynamicStates.size();
219 84 : dynamicState.pDynamicStates = dynamicStates.data();
220 :
221 84 : Vector<VkPipelineShaderStageCreateInfo> shaderStages; shaderStages.reserve(params.shaders.size());
222 :
223 : struct SpecInfo {
224 : VkSpecializationInfo specInfo;
225 : Vector<VkSpecializationMapEntry> entries;
226 : Bytes data;
227 : };
228 :
229 84 : Vector<SpecInfo> specs;
230 84 : size_t constants = 0;
231 252 : for (auto &shader : params.shaders) {
232 168 : if (!shader.constants.empty()) {
233 147 : ++ constants;
234 : }
235 : }
236 84 : specs.reserve(constants);
237 :
238 252 : for (auto &shader : params.shaders) {
239 168 : VkPipelineShaderStageCreateInfo info; sanitizeVkStruct(info);
240 168 : info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
241 168 : info.pNext = nullptr;
242 168 : info.flags = 0;
243 168 : info.stage = VkShaderStageFlagBits(shader.data->stage);
244 168 : info.module = shader.data->program.cast<Shader>()->getModule();
245 :
246 168 : info.pName = shader.data->entryPoints.front().name.data();
247 :
248 168 : if (!dev.getInfo().features.device10.features.shaderSampledImageArrayDynamicIndexing) {
249 0 : for (auto &it : shader.data->entryPoints) {
250 0 : if (StringView(it.name).ends_with("_static")) {
251 0 : info.pName = it.name.data();
252 : }
253 : }
254 : }
255 :
256 168 : if (!shader.constants.empty()) {
257 147 : auto &spec = specs.emplace_back();
258 147 : spec.entries.reserve(shader.constants.size());
259 147 : spec.data.reserve(sizeof(uint32_t) * shader.constants.size());
260 147 : uint32_t idx = 0;
261 357 : for (auto &it : shader.constants) {
262 210 : VkSpecializationMapEntry &entry = spec.entries.emplace_back();
263 210 : entry.constantID = idx;
264 210 : entry.offset = spec.data.size();
265 :
266 210 : BytesView data;
267 210 : switch (it.type) {
268 0 : case core::SpecializationConstant::Int:
269 0 : data = Shader_emplaceConstant(spec.data, it.intValue);
270 0 : entry.size = data.size();
271 0 : break;
272 0 : case core::SpecializationConstant::Float:
273 0 : data = Shader_emplaceConstant(spec.data, it.floatValue);
274 0 : entry.size = data.size();
275 0 : break;
276 210 : case core::SpecializationConstant::Predefined:
277 210 : data = dev.emplaceConstant(it.predefinedValue, spec.data);
278 210 : entry.size = data.size();
279 210 : break;
280 : }
281 210 : ++ idx;
282 : }
283 :
284 147 : spec.specInfo.mapEntryCount = spec.entries.size();
285 147 : spec.specInfo.pMapEntries = spec.entries.data();
286 147 : spec.specInfo.dataSize = spec.data.size();
287 147 : spec.specInfo.pData = spec.data.data();
288 147 : info.pSpecializationInfo = &spec.specInfo;
289 : } else {
290 21 : info.pSpecializationInfo = nullptr;
291 : }
292 168 : shaderStages.emplace_back(info);
293 : }
294 :
295 84 : VkPipelineDepthStencilStateCreateInfo depthState; sanitizeVkStruct(depthState);
296 84 : depthState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
297 84 : depthState.pNext = nullptr;
298 84 : depthState.flags = 0;
299 84 : if (pass.depthStencil) {
300 63 : auto a = (core::ImageAttachment *)pass.depthStencil->pass->attachment->attachment.get();
301 63 : if (a && core::isDepthFormat(a->getImageInfo().format)) {
302 63 : auto &depth = params.material.getDepthInfo();
303 63 : auto &bounds = params.material.getDepthBounds();
304 63 : depthState.depthTestEnable = depth.testEnabled ? VK_TRUE : VK_FALSE;
305 63 : depthState.depthWriteEnable = depth.writeEnabled ? VK_TRUE : VK_FALSE;
306 63 : depthState.depthCompareOp = VkCompareOp(depth.compare);
307 :
308 63 : depthState.depthBoundsTestEnable = bounds.enabled ? VK_TRUE : VK_FALSE;
309 63 : depthState.minDepthBounds = bounds.min;
310 63 : depthState.maxDepthBounds = bounds.max;
311 : } else {
312 0 : depthState.depthTestEnable = VK_FALSE;
313 0 : depthState.depthWriteEnable = VK_FALSE;
314 0 : depthState.depthCompareOp = VkCompareOp(0);
315 :
316 0 : depthState.depthBoundsTestEnable = VK_FALSE;
317 0 : depthState.minDepthBounds = 0.0f;
318 0 : depthState.maxDepthBounds = 0.0f;
319 : }
320 :
321 63 : if (a && core::isStencilFormat(a->getImageInfo().format)) {
322 0 : auto &front = params.material.getStencilInfoFront();
323 0 : auto &back = params.material.getStencilInfoBack();
324 :
325 0 : depthState.stencilTestEnable = params.material.isStancilEnabled() ? VK_TRUE : VK_FALSE;
326 :
327 0 : depthState.front.failOp = VkStencilOp(front.fail);
328 0 : depthState.front.passOp = VkStencilOp(front.pass);
329 0 : depthState.front.depthFailOp = VkStencilOp(front.depthFail);
330 0 : depthState.front.compareOp = VkCompareOp(front.compare);
331 0 : depthState.front.compareMask = front.compareMask;
332 0 : depthState.front.writeMask = front.writeMask;
333 0 : depthState.front.reference = front.reference;
334 :
335 0 : depthState.back.failOp = VkStencilOp(back.fail);
336 0 : depthState.back.passOp = VkStencilOp(back.pass);
337 0 : depthState.back.depthFailOp = VkStencilOp(back.depthFail);
338 0 : depthState.back.compareOp = VkCompareOp(back.compare);
339 0 : depthState.back.compareMask = back.compareMask;
340 0 : depthState.back.writeMask = back.writeMask;
341 0 : depthState.back.reference = back.reference;
342 : } else {
343 63 : depthState.stencilTestEnable = VK_FALSE;
344 :
345 63 : depthState.front.failOp = VK_STENCIL_OP_KEEP;
346 63 : depthState.front.passOp = VK_STENCIL_OP_KEEP;
347 63 : depthState.front.depthFailOp = VK_STENCIL_OP_KEEP;
348 63 : depthState.front.compareOp = VK_COMPARE_OP_NEVER;
349 63 : depthState.front.compareMask = 0;
350 63 : depthState.front.writeMask = 0;
351 63 : depthState.front.reference = 0;
352 :
353 63 : depthState.back.failOp = VK_STENCIL_OP_KEEP;
354 63 : depthState.back.passOp = VK_STENCIL_OP_KEEP;
355 63 : depthState.back.depthFailOp = VK_STENCIL_OP_KEEP;
356 63 : depthState.back.compareOp = VK_COMPARE_OP_NEVER;
357 63 : depthState.back.compareMask = 0;
358 63 : depthState.back.writeMask = 0;
359 63 : depthState.back.reference = 0;
360 : }
361 : }
362 :
363 84 : VkGraphicsPipelineCreateInfo pipelineInfo{}; sanitizeVkStruct(pipelineInfo);
364 84 : pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
365 84 : pipelineInfo.pNext = nullptr;
366 84 : pipelineInfo.flags = 0;
367 84 : pipelineInfo.stageCount = shaderStages.size();
368 84 : pipelineInfo.pStages = shaderStages.data();
369 84 : pipelineInfo.pVertexInputState = &vertexInputInfo;
370 84 : pipelineInfo.pInputAssemblyState = &inputAssembly;
371 84 : pipelineInfo.pViewportState = &viewportState;
372 84 : pipelineInfo.pRasterizationState = &rasterizer;
373 84 : pipelineInfo.pMultisampleState = &multisampling;
374 84 : pipelineInfo.pDepthStencilState = pass.depthStencil ? &depthState : nullptr; // Optional
375 84 : pipelineInfo.pColorBlendState = &colorBlending;
376 84 : pipelineInfo.pDynamicState = (dynamicStates.size() > 0) ? &dynamicState : nullptr; // Optional
377 :
378 84 : pipelineInfo.layout = pass.pass->impl.cast<RenderPass>()->getPipelineLayout(params.layout->index);
379 84 : pipelineInfo.renderPass = pass.pass->impl.cast<RenderPass>()->getRenderPass();
380 84 : pipelineInfo.subpass = pass.index;
381 84 : pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
382 84 : pipelineInfo.basePipelineIndex = -1;
383 :
384 84 : if (dev.getTable()->vkCreateGraphicsPipelines(dev.getDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_pipeline) == VK_SUCCESS) {
385 84 : _name = params.key.str<Interface>();
386 84 : return core::GraphicPipeline::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
387 84 : auto d = ((Device *)dev);
388 84 : d->getTable()->vkDestroyPipeline(d->getDevice(), (VkPipeline)ptr.get(), nullptr);
389 168 : }, core::ObjectType::Pipeline, ObjectHandle(_pipeline));
390 : }
391 0 : return false;
392 84 : }
393 :
394 1510 : bool ComputePipeline::init(Device &dev, const PipelineData ¶ms, const SubpassData &pass, const Queue &) {
395 : VkComputePipelineCreateInfo pipelineInfo;
396 1510 : pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
397 1510 : pipelineInfo.pNext = nullptr;
398 1510 : pipelineInfo.flags = 0;
399 1510 : pipelineInfo.layout = pass.pass->impl.cast<RenderPass>()->getPipelineLayout(params.layout->index);
400 1511 : pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
401 1511 : pipelineInfo.basePipelineIndex = 0;
402 :
403 : struct SpecInfo {
404 : VkSpecializationInfo specInfo;
405 : Vector<VkSpecializationMapEntry> entries;
406 : Bytes data;
407 : };
408 :
409 1511 : Vector<SpecInfo> specs;
410 1512 : pipelineInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
411 1512 : pipelineInfo.stage.pNext = nullptr;
412 1512 : pipelineInfo.stage.flags = 0;
413 1512 : pipelineInfo.stage.stage = VkShaderStageFlagBits(params.shader.data->stage);
414 1512 : pipelineInfo.stage.module = params.shader.data->program.cast<Shader>()->getModule();
415 1511 : pipelineInfo.stage.pName = params.shader.data->entryPoints.front().name.data();
416 1510 : pipelineInfo.stage.pSpecializationInfo = nullptr;
417 :
418 1510 : if (!dev.getInfo().features.device10.features.shaderSampledImageArrayDynamicIndexing) {
419 0 : for (auto &it : params.shader.data->entryPoints) {
420 0 : if (StringView(it.name).ends_with("_static")) {
421 0 : pipelineInfo.stage.pName = it.name.data();
422 : }
423 : }
424 : }
425 :
426 3040 : for (auto &it : params.shader.data->entryPoints) {
427 1530 : if (it.name == pipelineInfo.stage.pName) {
428 1509 : _localX = it.localX;
429 1509 : _localY = it.localY;
430 1509 : _localZ = it.localZ;
431 : }
432 : }
433 :
434 1508 : if (!params.shader.constants.empty()) {
435 1364 : auto &spec = specs.emplace_back();
436 1365 : spec.entries.reserve(params.shader.constants.size());
437 1365 : spec.data.reserve(sizeof(uint32_t) * params.shader.constants.size());
438 1365 : uint32_t idx = 0;
439 7208 : for (auto &it : params.shader.constants) {
440 5847 : VkSpecializationMapEntry &entry = spec.entries.emplace_back();
441 5847 : entry.constantID = idx;
442 5847 : entry.offset = spec.data.size();
443 :
444 5847 : BytesView data;
445 5847 : switch (it.type) {
446 5847 : case core::SpecializationConstant::Int:
447 5847 : data = Shader_emplaceConstant(spec.data, it.intValue);
448 5843 : entry.size = data.size();
449 5843 : break;
450 0 : case core::SpecializationConstant::Float:
451 0 : data = Shader_emplaceConstant(spec.data, it.floatValue);
452 0 : entry.size = data.size();
453 0 : break;
454 0 : case core::SpecializationConstant::Predefined:
455 0 : data = dev.emplaceConstant(it.predefinedValue, spec.data);
456 0 : entry.size = data.size();
457 0 : break;
458 : }
459 5843 : ++ idx;
460 : }
461 :
462 1358 : spec.specInfo.mapEntryCount = spec.entries.size();
463 1365 : spec.specInfo.pMapEntries = spec.entries.data();
464 1365 : spec.specInfo.dataSize = spec.data.size();
465 1365 : spec.specInfo.pData = spec.data.data();
466 1365 : pipelineInfo.stage.pSpecializationInfo = &spec.specInfo;
467 : } else {
468 146 : pipelineInfo.stage.pSpecializationInfo = nullptr;
469 : }
470 :
471 1511 : if (dev.getTable()->vkCreateComputePipelines(dev.getDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_pipeline) == VK_SUCCESS) {
472 1512 : _name = params.key.str<Interface>();
473 1510 : return core::ComputePipeline::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
474 1512 : auto d = ((Device *)dev);
475 1512 : d->getTable()->vkDestroyPipeline(d->getDevice(), (VkPipeline)ptr.get(), nullptr);
476 3021 : }, core::ObjectType::Pipeline, ObjectHandle(_pipeline));
477 : }
478 0 : return false;
479 1512 : }
480 :
481 : }
|