LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkPipeline.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 270 340 79.4 %
Date: 2024-05-12 00:16:13 Functions: 9 12 75.0 %

          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 &params, 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 &params, 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             : }

Generated by: LCOV version 1.14