PopulateCreateInfoVk.h#
Helper functionality for populating the Pipeline Create Infos.
Includes#
PVRVk/ComputePipelineVk.h
PVRVk/DescriptorSetVk.h
PVRVk/DeviceVk.h
PVRVk/GraphicsPipelineVk.h
PVRVk/PipelineLayoutVk.h
PVRVk/RaytracingPipelineVk.h
PVRVk/RenderPassVk.h
PVRVk/ShaderModuleVk.h
Namespaces#
Classes#
Functions#
Source Code#
#pragma once
#include "PVRVk/DeviceVk.h"
#include "PVRVk/PipelineLayoutVk.h"
#include "PVRVk/DescriptorSetVk.h"
#include "PVRVk/RenderPassVk.h"
#include "PVRVk/ShaderModuleVk.h"
#include "PVRVk/GraphicsPipelineVk.h"
#include "PVRVk/ComputePipelineVk.h"
#include "PVRVk/RaytracingPipelineVk.h"
namespace pvrvk {
namespace impl {
inline void convert(VkVertexInputAttributeDescription& vkva, const VertexInputAttributeDescription& pvrva)
{
vkva.binding = pvrva.getBinding();
vkva.format = static_cast<VkFormat>(pvrva.getFormat());
vkva.location = pvrva.getLocation();
vkva.offset = pvrva.getOffset();
}
inline void convert(VkVertexInputBindingDescription& vkvb, const VertexInputBindingDescription& pvrvb)
{
vkvb.binding = pvrvb.getBinding();
vkvb.inputRate = static_cast<VkVertexInputRate>(pvrvb.getInputRate());
vkvb.stride = pvrvb.getStride();
}
inline void convert(VkPipelineColorBlendAttachmentState& vkcb, const PipelineColorBlendAttachmentState& pvrcb)
{
vkcb.alphaBlendOp = static_cast<VkBlendOp>(pvrcb.getAlphaBlendOp());
vkcb.blendEnable = pvrcb.getBlendEnable();
vkcb.colorBlendOp = static_cast<VkBlendOp>(pvrcb.getColorBlendOp());
vkcb.colorWriteMask = static_cast<VkColorComponentFlags>(pvrcb.getColorWriteMask());
vkcb.dstAlphaBlendFactor = static_cast<VkBlendFactor>(pvrcb.getDstAlphaBlendFactor());
vkcb.dstColorBlendFactor = static_cast<VkBlendFactor>(pvrcb.getDstColorBlendFactor());
vkcb.srcAlphaBlendFactor = static_cast<VkBlendFactor>(pvrcb.getSrcAlphaBlendFactor());
vkcb.srcColorBlendFactor = static_cast<VkBlendFactor>(pvrcb.getSrcColorBlendFactor());
}
inline void convert(VkStencilOpState& vkStencilState, const StencilOpState& stencilState)
{
vkStencilState.failOp = static_cast<VkStencilOp>(stencilState.getFailOp());
vkStencilState.passOp = static_cast<VkStencilOp>(stencilState.getPassOp());
vkStencilState.depthFailOp = static_cast<VkStencilOp>(stencilState.getDepthFailOp());
vkStencilState.compareOp = static_cast<VkCompareOp>(stencilState.getCompareOp());
vkStencilState.compareMask = stencilState.getCompareMask();
vkStencilState.writeMask = stencilState.getWriteMask();
vkStencilState.reference = stencilState.getReference();
}
inline void convert(VkViewport& vkvp, const Viewport& vp)
{
vkvp.x = vp.getX();
vkvp.y = vp.getY();
vkvp.width = vp.getWidth();
vkvp.height = vp.getHeight();
vkvp.minDepth = vp.getMinDepth();
vkvp.maxDepth = vp.getMaxDepth();
}
inline void populateShaderInfo(const VkShaderModule& shaderModule, pvrvk::ShaderStageFlags shaderStageFlags, const std::string& entryPoint, const ShaderConstantInfo* shaderConsts,
uint32_t shaderConstCount, VkSpecializationInfo& specializationInfo, unsigned char* specializationInfoData, VkSpecializationMapEntry* mapEntries,
VkPipelineShaderStageCreateInfo& outShaderCreateInfo)
{
// caculate the number of size in bytes required.
uint32_t specicalizedataSize = 0;
for (uint32_t i = 0; i < shaderConstCount; ++i) { specicalizedataSize += shaderConsts[i].sizeInBytes; }
if (specicalizedataSize)
{
assert(specicalizedataSize < FrameworkCaps::MaxSpecialisationInfoDataSize && "Specialised Data out of range.");
uint32_t dataOffset = 0;
for (uint32_t i = 0; i < shaderConstCount; ++i)
{
memcpy(&specializationInfoData[dataOffset], shaderConsts[i].data, shaderConsts[i].sizeInBytes);
mapEntries[i] = VkSpecializationMapEntry{ shaderConsts[i].constantId, dataOffset, shaderConsts[i].sizeInBytes };
dataOffset += shaderConsts[i].sizeInBytes;
}
specializationInfo.mapEntryCount = shaderConstCount;
specializationInfo.pMapEntries = mapEntries;
specializationInfo.dataSize = specicalizedataSize;
specializationInfo.pData = specializationInfoData;
}
outShaderCreateInfo.sType = static_cast<VkStructureType>(pvrvk::StructureType::e_PIPELINE_SHADER_STAGE_CREATE_INFO);
outShaderCreateInfo.pNext = nullptr;
outShaderCreateInfo.flags = static_cast<VkPipelineShaderStageCreateFlags>(pvrvk::PipelineShaderStageCreateFlags::e_NONE);
outShaderCreateInfo.pSpecializationInfo = (specicalizedataSize ? &specializationInfo : nullptr);
outShaderCreateInfo.stage = static_cast<VkShaderStageFlagBits>(shaderStageFlags);
outShaderCreateInfo.module = shaderModule;
outShaderCreateInfo.pName = entryPoint.c_str();
}
struct GraphicsPipelinePopulate
{
private:
VkGraphicsPipelineCreateInfo createInfo; //< After construction, will contain the ready-to-use create info
VkPipelineInputAssemblyStateCreateInfo _ia; //< Input assembler create info
VkPipelineRasterizationStateCreateInfo _rs; //< rasterization create info
VkPipelineMultisampleStateCreateInfo _ms; //< Multisample create info
VkPipelineViewportStateCreateInfo _vp; //< Viewport createinfo
VkPipelineColorBlendStateCreateInfo _cb; //< Color blend create info
VkPipelineDepthStencilStateCreateInfo _ds; //< Depth-stencil create info
VkPipelineVertexInputStateCreateInfo _vertexInput; //< Vertex input create info
VkPipelineShaderStageCreateInfo _shaders[static_cast<uint32_t>(10)];
VkPipelineTessellationStateCreateInfo _tessState;
VkVertexInputBindingDescription _vkVertexBindings[FrameworkCaps::MaxVertexBindings]; // Memory for the bindings
VkVertexInputAttributeDescription _vkVertexAttributes[FrameworkCaps::MaxVertexAttributes]; // Memory for the attributes
VkPipelineColorBlendAttachmentState _vkBlendAttachments[FrameworkCaps::MaxColorAttachments]; // Memory for the attachments
VkPipelineDynamicStateCreateInfo _vkDynamicState;
VkPipelineFragmentShadingRateStateCreateInfoKHR _vkFragmentShadingRate;
std::vector<VkDynamicState> _dynamicStates;
VkRect2D _scissors[FrameworkCaps::MaxScissorRegions];
VkViewport _viewports[FrameworkCaps::MaxViewportRegions];
VkSpecializationInfo specializationInfos[FrameworkCaps::MaxSpecialisationInfos];
unsigned char specializationInfoData[FrameworkCaps::MaxSpecialisationInfos][FrameworkCaps::MaxSpecialisationInfoDataSize];
std::vector<VkSpecializationMapEntry> specilizationEntries[FrameworkCaps::MaxSpecialisationInfos];
public:
GraphicsPipelinePopulate() {}
const VkGraphicsPipelineCreateInfo& getVkCreateInfo() const { return createInfo; }
bool init(const GraphicsPipelineCreateInfo& gpcp)
{
if (!gpcp.pipelineLayout)
{
assert(false && "Invalid Pipeline Layout");
return false;
}
if (!gpcp.renderPass)
{
assert(false && "Invalid RenderPass");
return false;
}
VkPipelineRasterizationStateStreamCreateInfoEXT pipelineRasterizationStateStreamCreateInfoEXT = {};
pipelineRasterizationStateStreamCreateInfoEXT.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT);
{
// renderpass validation
if (!gpcp.renderPass)
{
assert(false && "Invalid RenderPass: A Pipeline must have a valid render pass");
return false;
}
// assert that the vertex & fragment shader stage must be valid else it should be inhertied from the parent
if (!gpcp.isSafetyCritical && !gpcp.vertexShader.isActive())
{
assert(false && "Graphics Pipeline should either have a valid vertex shader or inherited from its parent");
return false;
}
if (!gpcp.isSafetyCritical && !gpcp.fragmentShader.isActive())
{
assert(false && "Graphics Pipeline should either have a valid fragment shader or inherited from its parent");
return false;
}
createInfo.sType = static_cast<VkStructureType>(StructureType::e_GRAPHICS_PIPELINE_CREATE_INFO);
createInfo.pNext = gpcp.pNext;
createInfo.flags = static_cast<VkPipelineCreateFlags>(gpcp.flags);
// Set up the pipeline state
createInfo.pInputAssemblyState = &_ia;
createInfo.pRasterizationState = &_rs;
createInfo.pMultisampleState = nullptr;
createInfo.pViewportState = &_vp;
createInfo.pColorBlendState = &_cb;
createInfo.pDepthStencilState = (gpcp.depthStencil.isAllStatesEnabled() ? &_ds : nullptr);
createInfo.pTessellationState = (gpcp.tesselationStates.getControlShader() ? &_tessState : nullptr);
createInfo.pVertexInputState = &_vertexInput;
createInfo.pDynamicState = nullptr;
createInfo.layout = gpcp.pipelineLayout->getVkHandle();
createInfo.renderPass = gpcp.renderPass->getVkHandle();
createInfo.subpass = gpcp.subpass;
if (!gpcp.isSafetyCritical)
{
createInfo.stageCount = (uint32_t)((gpcp.vertexShader.isActive() ? 1 : 0) + (gpcp.fragmentShader.isActive() ? 1 : 0) +
(gpcp.tesselationStates.isControlShaderActive() ? 1 : 0) + (gpcp.tesselationStates.isEvaluationShaderActive() ? 1 : 0) + (gpcp.geometryShader.isActive() ? 1 : 0));
}
createInfo.pStages = &_shaders[0];
}
if (createInfo.pTessellationState)
{
_tessState.flags = static_cast<VkPipelineTessellationStateCreateFlags>(pvrvk::PipelineTessellationStateCreateFlags::e_NONE);
_tessState.patchControlPoints = gpcp.tesselationStates.getNumPatchControlPoints();
_tessState.pNext = 0;
_tessState.sType = static_cast<VkStructureType>(pvrvk::StructureType::e_PIPELINE_TESSELLATION_STATE_CREATE_INFO);
}
{
auto val = gpcp.inputAssembler;
// input assembly
_ia.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);
_ia.pNext = nullptr;
_ia.flags = static_cast<VkPipelineInputAssemblyStateCreateFlags>(PipelineInputAssemblyStateCreateFlags::e_NONE);
_ia.topology = static_cast<VkPrimitiveTopology>(val.getPrimitiveTopology());
_ia.primitiveRestartEnable = val.isPrimitiveRestartEnabled();
}
{
auto val = gpcp.vertexInput;
// vertex input
memset(&_vertexInput, 0, sizeof(_vertexInput));
_vertexInput.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
_vertexInput.pNext = nullptr;
_vertexInput.flags = static_cast<VkPipelineVertexInputStateCreateFlags>(PipelineVertexInputStateCreateFlags::e_NONE);
assert(val.getAttributes().size() <= FrameworkCaps::MaxVertexAttributes);
for (uint32_t i = 0; i < val.getAttributes().size(); i++) { convert(_vkVertexAttributes[i], val.getAttributes()[i]); }
assert(val.getInputBindings().size() <= FrameworkCaps::MaxVertexBindings);
for (uint32_t i = 0; i < val.getInputBindings().size(); i++) { convert(_vkVertexBindings[i], val.getInputBindingByIndex(i)); }
_vertexInput.vertexBindingDescriptionCount = static_cast<uint32_t>(val.getInputBindings().size());
_vertexInput.pVertexBindingDescriptions = static_cast<uint32_t>(val.getInputBindings().size()) == 0u ? nullptr : &_vkVertexBindings[0];
_vertexInput.vertexAttributeDescriptionCount = static_cast<uint32_t>(val.getAttributes().size());
_vertexInput.pVertexAttributeDescriptions = (val.getAttributes().size() ? &_vkVertexAttributes[0] : nullptr);
}
{
if (gpcp.isSafetyCritical)
{
std::vector<const PipelineShaderStageCreateInfo*> vectorPointer;
if (gpcp.vertexShader.getShaderStage() != ShaderStageFlags::e_NONE) { vectorPointer.push_back(&gpcp.vertexShader); }
if (gpcp.fragmentShader.getShaderStage() != ShaderStageFlags::e_NONE) { vectorPointer.push_back(&gpcp.fragmentShader); }
for (size_t i = 0; i < vectorPointer.size(); ++i)
{
_shaders[i] = {};
_shaders[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
_shaders[i].pName = vectorPointer[i]->getEntryPoint().c_str();
_shaders[i].stage = static_cast<VkShaderStageFlagBits>(vectorPointer[i]->getShaderStage());
}
createInfo.stageCount = static_cast<uint32_t>(vectorPointer.size());
}
else
{
uint32_t shaderIndex = 0;
if (gpcp.vertexShader.isActive())
{
specilizationEntries[0].resize(gpcp.vertexShader.getNumShaderConsts());
populateShaderInfo(gpcp.vertexShader.getShader()->getVkHandle(), ShaderStageFlags::e_VERTEX_BIT, gpcp.vertexShader.getEntryPoint(),
gpcp.vertexShader.getAllShaderConstants(), gpcp.vertexShader.getNumShaderConsts(), specializationInfos[0], specializationInfoData[0],
specilizationEntries[0].data(), _shaders[shaderIndex]);
++shaderIndex;
}
if (gpcp.fragmentShader.isActive())
{
specilizationEntries[1].resize(gpcp.fragmentShader.getNumShaderConsts());
populateShaderInfo(gpcp.fragmentShader.getShader()->getVkHandle(), ShaderStageFlags::e_FRAGMENT_BIT, gpcp.fragmentShader.getEntryPoint(),
gpcp.fragmentShader.getAllShaderConstants(), gpcp.fragmentShader.getNumShaderConsts(), specializationInfos[1], specializationInfoData[1],
specilizationEntries[1].data(), _shaders[shaderIndex]);
++shaderIndex;
}
if (gpcp.geometryShader.isActive())
{
specilizationEntries[2].resize(gpcp.geometryShader.getNumShaderConsts());
populateShaderInfo(gpcp.geometryShader.getShader()->getVkHandle(), ShaderStageFlags::e_GEOMETRY_BIT, gpcp.geometryShader.getEntryPoint(),
gpcp.geometryShader.getAllShaderConstants(), gpcp.geometryShader.getNumShaderConsts(), specializationInfos[2], specializationInfoData[2],
specilizationEntries[2].data(), _shaders[shaderIndex]);
++shaderIndex;
}
if (gpcp.tesselationStates.isControlShaderActive())
{
specilizationEntries[3].resize(gpcp.tesselationStates.getNumControlShaderConstants());
populateShaderInfo(gpcp.tesselationStates.getControlShader()->getVkHandle(), ShaderStageFlags::e_TESSELLATION_CONTROL_BIT,
gpcp.tesselationStates.getControlShaderEntryPoint(), gpcp.tesselationStates.getAllControlShaderConstants(),
gpcp.tesselationStates.getNumControlShaderConstants(), specializationInfos[3], specializationInfoData[3], specilizationEntries[3].data(),
_shaders[shaderIndex]);
++shaderIndex;
}
if (gpcp.tesselationStates.isEvaluationShaderActive())
{
specilizationEntries[4].resize(gpcp.tesselationStates.getNumEvaluatinonShaderConstants());
populateShaderInfo(gpcp.tesselationStates.getEvaluationShader()->getVkHandle(), ShaderStageFlags::e_TESSELLATION_EVALUATION_BIT,
gpcp.tesselationStates.getEvaluationShaderEntryPoint(), gpcp.tesselationStates.getAllEvaluationShaderConstants(),
gpcp.tesselationStates.getNumEvaluatinonShaderConstants(), specializationInfos[4], specializationInfoData[4], specilizationEntries[4].data(),
_shaders[shaderIndex]);
++shaderIndex;
}
}
}
// ColorBlend
{
auto val = gpcp.colorBlend;
assert(val.getNumAttachmentStates() <= FrameworkCaps::MaxColorAttachments);
// color blend
_cb.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO);
_cb.pNext = nullptr;
_cb.flags = static_cast<VkPipelineColorBlendStateCreateFlags>(PipelineColorBlendStateCreateFlags::e_NONE);
_cb.logicOp = static_cast<VkLogicOp>(val.getLogicOp());
_cb.logicOpEnable = val.isLogicOpEnabled();
{
_cb.blendConstants[0] = val.getColorBlendConst().getR();
_cb.blendConstants[1] = val.getColorBlendConst().getG();
_cb.blendConstants[2] = val.getColorBlendConst().getB();
_cb.blendConstants[3] = val.getColorBlendConst().getA();
}
for (uint32_t i = 0; i < val.getNumAttachmentStates(); i++) { convert(_vkBlendAttachments[i], val.getAttachmentState(i)); }
_cb.pAttachments = &_vkBlendAttachments[0];
_cb.attachmentCount = static_cast<uint32_t>(val.getNumAttachmentStates());
}
// DepthStencil
if (createInfo.pDepthStencilState)
{
auto val = gpcp.depthStencil;
// depth-stencil
_ds.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
_ds.pNext = nullptr;
_ds.flags = static_cast<VkPipelineDepthStencilStateCreateFlags>(PipelineDepthStencilStateCreateFlags::e_NONE);
_ds.depthTestEnable = val.isDepthTestEnable();
_ds.depthWriteEnable = val.isDepthWriteEnable();
_ds.depthCompareOp = static_cast<VkCompareOp>(val.getDepthComapreOp());
_ds.depthBoundsTestEnable = val.isDepthBoundTestEnable();
_ds.stencilTestEnable = val.isStencilTestEnable();
_ds.minDepthBounds = val.getMinDepth();
_ds.maxDepthBounds = val.getMaxDepth();
convert(_ds.front, val.getStencilFront());
convert(_ds.back, val.getStencilBack());
}
// Viewport
{
assert(gpcp.viewport.getNumViewportScissors() > 0 && "Pipeline must have atleast one viewport and scissor");
for (uint32_t i = 0; i < gpcp.viewport.getNumViewportScissors(); ++i)
{
convert(_viewports[i], gpcp.viewport.getViewport(i));
_scissors[i] = gpcp.viewport.getScissor(i).get();
}
// viewport-scissor
_vp.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_VIEWPORT_STATE_CREATE_INFO);
_vp.pNext = nullptr;
_vp.flags = static_cast<VkPipelineViewportStateCreateFlags>(PipelineViewportStateCreateFlags::e_NONE);
_vp.viewportCount = gpcp.viewport.getNumViewportScissors();
_vp.pViewports = _viewports;
_vp.scissorCount = gpcp.viewport.getNumViewportScissors();
_vp.pScissors = _scissors;
}
// Rasterizer
{
auto val = gpcp.rasterizer;
// rasterization
_rs.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_RASTERIZATION_STATE_CREATE_INFO);
_rs.pNext = nullptr;
_rs.flags = static_cast<VkPipelineRasterizationStateCreateFlags>(PipelineRasterizationStateCreateFlags::e_NONE);
_rs.depthClampEnable = !val.isDepthClipEnabled();
_rs.rasterizerDiscardEnable = val.isRasterizerDiscardEnabled();
_rs.polygonMode = static_cast<VkPolygonMode>(val.getPolygonMode());
_rs.cullMode = static_cast<VkCullModeFlags>(val.getCullFace());
_rs.frontFace = static_cast<VkFrontFace>(val.getFrontFaceWinding());
_rs.depthBiasEnable = val.isDepthBiasEnabled();
_rs.depthBiasClamp = val.getDepthBiasClamp();
_rs.depthBiasConstantFactor = val.getDepthBiasConstantFactor();
_rs.depthBiasSlopeFactor = val.getDepthBiasSlopeFactor();
_rs.lineWidth = val.getLineWidth();
if (val.getRasterizationStream() != 0)
{
pipelineRasterizationStateStreamCreateInfoEXT.rasterizationStream = val.getRasterizationStream();
appendPNext((VkBaseInStructure*)&_rs, &pipelineRasterizationStateStreamCreateInfoEXT);
}
}
// Multisample
if (!_rs.rasterizerDiscardEnable)
{
auto val = gpcp.multiSample;
// multisampling
_ms.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO);
_ms.pNext = nullptr;
_ms.flags = static_cast<VkPipelineMultisampleStateCreateFlags>(PipelineMultisampleStateCreateFlags::e_NONE);
_ms.rasterizationSamples = static_cast<VkSampleCountFlagBits>(gpcp.multiSample.getRasterizationSamples());
_ms.sampleShadingEnable = val.isSampleShadingEnabled();
_ms.minSampleShading = val.getMinSampleShading();
_ms.pSampleMask = &gpcp.multiSample.getSampleMask();
_ms.alphaToCoverageEnable = val.isAlphaToCoverageEnabled();
_ms.alphaToOneEnable = val.isAlphaToOneEnabled();
createInfo.pMultisampleState = &_ms;
}
// Dynamic State
{
std::vector<pvrvk::DynamicState> dynamicStatesEnabled = gpcp.dynamicStates.getDynamicStates();
for (pvrvk::DynamicState state : dynamicStatesEnabled) { _dynamicStates.push_back((VkDynamicState)state); }
_vkDynamicState.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_DYNAMIC_STATE_CREATE_INFO);
_vkDynamicState.flags = static_cast<VkPipelineDynamicStateCreateFlags>(PipelineDynamicStateCreateFlags::e_NONE);
_vkDynamicState.pNext = nullptr;
_vkDynamicState.pDynamicStates = _dynamicStates.data();
_vkDynamicState.dynamicStateCount = static_cast<uint32_t>(_dynamicStates.size());
createInfo.pDynamicState = (_dynamicStates.size() != 0 ? &_vkDynamicState : nullptr);
}
// pNext Chain
{
// fragment shading rate extension
if (gpcp.fragmentShadingRate.isEnabled())
{
_vkFragmentShadingRate.sType = static_cast<VkStructureType>(StructureType::e_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR);
_vkFragmentShadingRate.fragmentSize = gpcp.fragmentShadingRate.getFragmentSize().get();
_vkFragmentShadingRate.combinerOps[0] = (VkFragmentShadingRateCombinerOpKHR)gpcp.fragmentShadingRate.getCombinerOpPipelinePrimitive();
_vkFragmentShadingRate.combinerOps[1] = (VkFragmentShadingRateCombinerOpKHR)gpcp.fragmentShadingRate.getCombinerOpResultAttachment();
// push back the previously set pNext pointer in chain
_vkFragmentShadingRate.pNext = createInfo.pNext;
createInfo.pNext = &_vkFragmentShadingRate;
}
}
createInfo.basePipelineHandle = VK_NULL_HANDLE;
createInfo.basePipelineIndex = 0;
if (gpcp.basePipeline != VK_NULL_HANDLE)
{
createInfo.basePipelineHandle = gpcp.basePipeline->getVkHandle();
createInfo.basePipelineIndex = gpcp.basePipelineIndex;
}
return true;
}
};
struct ComputePipelinePopulate
{
VkComputePipelineCreateInfo createInfo;
VkPipelineShaderStageCreateInfo _shader;
VkSpecializationInfo specializationInfos;
unsigned char specializationInfoData[FrameworkCaps::MaxSpecialisationInfoDataSize];
std::vector<VkSpecializationMapEntry> specilizationEntries;
VkComputePipelineCreateInfo& operator*() { return createInfo; }
void init(const ComputePipelineCreateInfo& cpcp)
{
if (!cpcp.pipelineLayout) { throw ErrorValidationFailedEXT("PipelineLayout must be valid"); }
createInfo.sType = static_cast<VkStructureType>(StructureType::e_COMPUTE_PIPELINE_CREATE_INFO);
createInfo.pNext = nullptr;
createInfo.flags = static_cast<VkPipelineCreateFlags>(cpcp.flags);
// Set up the pipeline state
createInfo.basePipelineHandle = (cpcp.basePipeline ? cpcp.basePipeline->getVkHandle() : VK_NULL_HANDLE);
createInfo.basePipelineIndex = cpcp.basePipelineIndex;
createInfo.layout = cpcp.pipelineLayout->getVkHandle();
specilizationEntries.resize(cpcp.computeShader.getNumShaderConsts());
populateShaderInfo(cpcp.computeShader.getShader()->getVkHandle(), ShaderStageFlags::e_COMPUTE_BIT, cpcp.computeShader.getEntryPoint(),
cpcp.computeShader.getAllShaderConstants(), cpcp.computeShader.getNumShaderConsts(), specializationInfos, specializationInfoData, specilizationEntries.data(), _shader);
createInfo.stage = _shader;
}
};
struct RaytracingPipelinePopulate
{
VkRayTracingPipelineCreateInfoKHR createInfo;
VkRayTracingPipelineCreateInfoKHR& operator*() { return createInfo; }
std::vector<VkPipelineShaderStageCreateInfo> stages;
std::vector<VkRayTracingShaderGroupCreateInfoKHR> shaderGroups;
void init(const RaytracingPipelineCreateInfo& raytracingPipeline)
{
if (!raytracingPipeline.pipelineLayout) { throw ErrorValidationFailedEXT("PipelineLayout must be valid"); }
createInfo = {};
createInfo.sType = static_cast<VkStructureType>(StructureType::e_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
for (size_t i = 0; i < raytracingPipeline.stages.size(); ++i)
{
stages.push_back({ static_cast<VkStructureType>(StructureType::e_PIPELINE_SHADER_STAGE_CREATE_INFO), nullptr, 0,
static_cast<VkShaderStageFlagBits>(raytracingPipeline.stages[i].getShaderStage()),
raytracingPipeline.stages[i].getShader()->getVkHandle(), raytracingPipeline.stages[i].getEntryPoint().c_str(), nullptr });
}
for (size_t i = 0; i < raytracingPipeline.shaderGroups.size(); ++i)
{
shaderGroups.push_back({ static_cast<VkStructureType>(StructureType::e_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR), nullptr,
static_cast<VkRayTracingShaderGroupTypeKHR>(raytracingPipeline.shaderGroups[i].getType()),
raytracingPipeline.shaderGroups[i].getGeneralShader(), raytracingPipeline.shaderGroups[i].getClosestHitShader(),
raytracingPipeline.shaderGroups[i].getAnyHitShader(), raytracingPipeline.shaderGroups[i].getIntersectionShader() });
}
createInfo.stageCount = static_cast<uint32_t>(stages.size());
createInfo.pStages = stages.data();
createInfo.groupCount = static_cast<uint32_t>(raytracingPipeline.shaderGroups.size());
createInfo.pGroups = shaderGroups.data();
createInfo.maxPipelineRayRecursionDepth = raytracingPipeline.maxRecursionDepth; // Ray depth
createInfo.layout = raytracingPipeline.pipelineLayout->getVkHandle();
}
};
} // namespace impl
} // namespace pvrvk