blob: b85cac4f8dc7d9e104e2b40a3b5346d754358926 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2023 LunarG, Inc.
* Copyright (c) 2023 Nintendo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Wrapper that can construct monolithic pipeline or use
VK_EXT_graphics_pipeline_library for pipeline construction or use
VK_EXT_shader_object for shader objects.
*//*--------------------------------------------------------------------*/
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "deSharedPtr.hpp"
#include "deSTLUtil.hpp"
#include "tcuVector.hpp"
#include "tcuVectorType.hpp"
#include "tcuMaybe.hpp"
#include "vkRefUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkTypeUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkPipelineConstructionUtil.hpp"
#include "vkBarrierUtil.hpp"
#include <memory>
#include <set>
#include <map>
namespace vk
{
namespace
{
enum PipelineSetupState
{
PSS_NONE = 0x00000000,
PSS_VERTEX_INPUT_INTERFACE = 0x00000001,
PSS_PRE_RASTERIZATION_SHADERS = 0x00000002,
PSS_FRAGMENT_SHADER = 0x00000004,
PSS_FRAGMENT_OUTPUT_INTERFACE = 0x00000008,
};
using TessellationDomainOriginStatePtr = std::unique_ptr<VkPipelineTessellationDomainOriginStateCreateInfo>;
} // anonymous namespace
static const VkVertexInputBindingDescription defaultVertexInputBindingDescription
{
0u, // deUint32 binding
sizeof(tcu::Vec4), // deUint32 stride
VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate
};
static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescription
{
0u, // deUint32 location
0u, // deUint32 binding
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format
0u // deUint32 offset
};
static const VkPipelineVertexInputStateCreateInfo defaultVertexInputState
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
(VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags
1u, // deUint32 vertexBindingDescriptionCount
&defaultVertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
1u, // deUint32 vertexAttributeDescriptionCount
&defaultVertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
};
static const VkStencilOpState defaultStencilOpState
{
VK_STENCIL_OP_KEEP, // VkStencilOp failOp
VK_STENCIL_OP_KEEP, // VkStencilOp passOp
VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
VK_COMPARE_OP_NEVER, // VkCompareOp compareOp
0u, // deUint32 compareMask
0u, // deUint32 writeMask
0u // deUint32 reference
};
static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilState
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineDepthStencilStateCreateFlags flags
VK_FALSE, // VkBool32 depthTestEnable
VK_FALSE, // VkBool32 depthWriteEnable
VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp depthCompareOp
VK_FALSE, // VkBool32 depthBoundsTestEnable
VK_FALSE, // VkBool32 stencilTestEnable
defaultStencilOpState, // VkStencilOpState front
defaultStencilOpState, // VkStencilOpState back
0.0f, // float minDepthBounds
1.0f, // float maxDepthBounds
};
static const VkPipelineMultisampleStateCreateInfo defaultMultisampleState
{
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineMultisampleStateCreateFlags flags
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples
VK_FALSE, // VkBool32 sampleShadingEnable
1.0f, // float minSampleShading
DE_NULL, // const VkSampleMask* pSampleMask
VK_FALSE, // VkBool32 alphaToCoverageEnable
VK_FALSE // VkBool32 alphaToOneEnable
};
static const VkPipelineColorBlendAttachmentState defaultColorBlendAttachmentState
{
VK_FALSE, // VkBool32 blendEnable
VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
0xf // VkColorComponentFlags colorWriteMask
};
static const VkPipelineColorBlendStateCreateInfo defaultColorBlendState
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineColorBlendStateCreateFlags flags
VK_FALSE, // VkBool32 logicOpEnable
VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
1u, // deUint32 attachmentCount
&defaultColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
{ 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
};
namespace
{
#ifndef CTS_USES_VULKANSC
VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)
{
return
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT, // VkStructureType sType;
DE_NULL, // void* pNext;
flags, // VkGraphicsPipelineLibraryFlagsEXT flags;
};
}
#endif // CTS_USES_VULKANSC
Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
VkDevice device,
VkPipelineCache pipelineCache,
const VkGraphicsPipelineCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator = nullptr)
{
VkPipeline object = 0;
const auto retcode = vk.createGraphicsPipelines(device, pipelineCache, 1u, pCreateInfo, pAllocator, &object);
#ifndef CTS_USES_VULKANSC
const bool allowCompileRequired = ((pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0u);
if (allowCompileRequired && retcode == VK_PIPELINE_COMPILE_REQUIRED)
throw PipelineCompileRequiredError("createGraphicsPipelines returned VK_PIPELINE_COMPILE_REQUIRED");
#endif // CTS_USES_VULKANSC
VK_CHECK(retcode);
return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device, pAllocator));
}
} // anonymous
bool isConstructionTypeLibrary (PipelineConstructionType pipelineConstructionType)
{
return pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY ||
pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY;
}
bool isConstructionTypeShaderObject (PipelineConstructionType pipelineConstructionType) {
return pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV ||
pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY ||
pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV ||
pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
}
void checkPipelineConstructionRequirements (const InstanceInterface& vki,
VkPhysicalDevice physicalDevice,
PipelineConstructionType pipelineConstructionType)
{
if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
return;
const auto& supportedExtensions = enumerateCachedDeviceExtensionProperties(vki, physicalDevice);
if (isConstructionTypeShaderObject(pipelineConstructionType))
{
if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_shader_object")))
TCU_THROW(NotSupportedError, "VK_EXT_shader_object not supported");
return;
}
if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_graphics_pipeline_library")))
TCU_THROW(NotSupportedError, "VK_EXT_graphics_pipeline_library not supported");
}
PipelineCreateFlags2 translateCreateFlag(VkPipelineCreateFlags flagToTranslate)
{
return (PipelineCreateFlags2)flagToTranslate;
}
void addToChain(void** structThatStartsChain, void* structToAddAtTheEnd)
{
DE_ASSERT(structThatStartsChain);
if (structToAddAtTheEnd == DE_NULL)
return;
// Cast to the base out structure which has a non-const pNext pointer.
auto* structToAddAtTheEndCasted = reinterpret_cast<VkBaseOutStructure*>(structToAddAtTheEnd);
// make sure that pNext pointer of structure that is added to chain is empty;
// we are construting chains on our own and there are cases that use same
// structure for multiple instances of GraphicsPipelineWrapper
structToAddAtTheEndCasted->pNext = DE_NULL;
deUint32 safetyCouter = 10u;
void** structInChain = structThatStartsChain;
do
{
// check if this is free spot
if (*structInChain == DE_NULL)
{
// attach new structure at the end
*structInChain = structToAddAtTheEndCasted;
return;
}
// Cast to the base out structure which has a non-const pNext pointer.
auto* gpl = reinterpret_cast<VkBaseOutStructure*>(*structInChain);
// move structure pointer one position down the pNext chain
structInChain = reinterpret_cast<void**>(&gpl->pNext);
}
while (--safetyCouter);
// probably safetyCouter is to small
DE_ASSERT(false);
}
namespace {
using PipelineShaderStageModuleIdPtr = std::unique_ptr<PipelineShaderStageModuleIdentifierCreateInfoWrapper>;
}
PipelineLayoutWrapper::PipelineLayoutWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, const std::vector<vk::Move<VkDescriptorSetLayout>>& descriptorSetLayout)
: m_pipelineConstructionType (pipelineConstructionType)
, m_vk (&vk)
, m_device (device)
, m_flags ((VkPipelineLayoutCreateFlags)0u)
, m_setLayoutCount ((deUint32)descriptorSetLayout.size())
, m_pushConstantRangeCount (0u)
, m_pushConstantRanges ()
{
#ifndef CTS_USES_VULKANSC
if (isConstructionTypeShaderObject(pipelineConstructionType))
m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
#endif
m_setLayouts.resize(m_setLayoutCount);
for (deUint32 i = 0; i < m_setLayoutCount; ++i)
m_setLayouts[i] = *descriptorSetLayout[i];
VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
createInfo.flags = m_flags;
createInfo.setLayoutCount = m_setLayoutCount;
createInfo.pSetLayouts = de::dataOrNull(m_setLayouts);
createInfo.pushConstantRangeCount = m_pushConstantRangeCount;
createInfo.pPushConstantRanges = de::dataOrNull(m_pushConstantRanges);
m_pipelineLayout = createPipelineLayout(vk, device, &createInfo);
}
PipelineLayoutWrapper::PipelineLayoutWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, deUint32 setLayoutCount, const VkDescriptorSetLayout* descriptorSetLayout)
: m_pipelineConstructionType (pipelineConstructionType)
, m_vk (&vk)
, m_device (device)
, m_flags ((VkPipelineLayoutCreateFlags)0u)
, m_setLayoutCount (setLayoutCount)
, m_pushConstantRangeCount (0u)
, m_pushConstantRanges ()
{
#ifndef CTS_USES_VULKANSC
if (isConstructionTypeShaderObject(pipelineConstructionType))
m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
#endif
m_setLayouts.resize(m_setLayoutCount);
for (deUint32 i = 0; i < m_setLayoutCount; ++i)
m_setLayouts[i] = descriptorSetLayout[i];
VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
createInfo.flags = m_flags;
createInfo.setLayoutCount = m_setLayoutCount;
createInfo.pSetLayouts = de::dataOrNull(m_setLayouts);
createInfo.pushConstantRangeCount = m_pushConstantRangeCount;
createInfo.pPushConstantRanges = de::dataOrNull(m_pushConstantRanges);
m_pipelineLayout = createPipelineLayout(vk, device, &createInfo);
}
PipelineLayoutWrapper::PipelineLayoutWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, const VkDescriptorSetLayout descriptorSetLayout, const VkPushConstantRange* pushConstantRange)
: m_pipelineConstructionType (pipelineConstructionType)
, m_vk(&vk)
, m_device(device)
, m_flags ((VkPipelineLayoutCreateFlags)0u)
{
#ifndef CTS_USES_VULKANSC
if (isConstructionTypeShaderObject(pipelineConstructionType))
m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
#endif
if (descriptorSetLayout == VK_NULL_HANDLE)
{
m_setLayoutCount = 0;
}
else
{
m_setLayoutCount = 1;
m_setLayouts.resize(1);
m_setLayouts[0] = descriptorSetLayout;
}
if (pushConstantRange == DE_NULL)
{
m_pushConstantRangeCount = 0;
}
else
{
m_pushConstantRangeCount = 1;
m_pushConstantRanges.resize(1);
m_pushConstantRanges[0] = *pushConstantRange;
}
VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
createInfo.flags = m_flags;
createInfo.setLayoutCount = m_setLayoutCount;
createInfo.pSetLayouts = de::dataOrNull(m_setLayouts);
createInfo.pushConstantRangeCount = m_pushConstantRangeCount;
createInfo.pPushConstantRanges = de::dataOrNull(m_pushConstantRanges);
m_pipelineLayout = createPipelineLayout(vk, device, &createInfo);
}
PipelineLayoutWrapper::PipelineLayoutWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks*)
: m_pipelineConstructionType (pipelineConstructionType)
, m_vk (&vk)
, m_device (device)
, m_flags (pCreateInfo->flags)
, m_setLayoutCount (pCreateInfo->setLayoutCount)
, m_pushConstantRangeCount (pCreateInfo->pushConstantRangeCount)
{
#ifndef CTS_USES_VULKANSC
if (isConstructionTypeShaderObject(pipelineConstructionType))
m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
#endif
m_setLayouts.resize(pCreateInfo->setLayoutCount);
for (deUint32 i = 0; i < pCreateInfo->setLayoutCount; ++i)
m_setLayouts[i] = pCreateInfo->pSetLayouts[i];
m_pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount);
for (deUint32 i = 0; i < pCreateInfo->pushConstantRangeCount; ++i)
m_pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i];
VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
createInfo.flags = m_flags;
createInfo.setLayoutCount = m_setLayoutCount;
createInfo.pSetLayouts = m_setLayouts.data();
createInfo.pushConstantRangeCount = m_pushConstantRangeCount;
createInfo.pPushConstantRanges = m_pushConstantRanges.data();
m_pipelineLayout = createPipelineLayout(vk, device, &createInfo);
}
PipelineLayoutWrapper::PipelineLayoutWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, const VkDevice device, const deUint32 setLayoutCount, const VkDescriptorSetLayout* descriptorSetLayout, const deUint32 pushConstantRangeCount, const VkPushConstantRange* pPushConstantRanges, const VkPipelineLayoutCreateFlags flags)
: m_pipelineConstructionType (pipelineConstructionType)
, m_vk (&vk)
, m_device (device)
, m_flags (flags)
, m_setLayoutCount (setLayoutCount)
, m_pushConstantRangeCount (pushConstantRangeCount)
{
#ifndef CTS_USES_VULKANSC
if (isConstructionTypeShaderObject(pipelineConstructionType))
m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
#endif
m_setLayouts.resize(m_setLayoutCount);
m_pushConstantRanges.resize(m_pushConstantRangeCount);
for (deUint32 i = 0; i < m_setLayoutCount; ++i)
m_setLayouts[i] = descriptorSetLayout[i];
for (deUint32 i = 0; i < m_pushConstantRangeCount; ++i)
m_pushConstantRanges[i] = pPushConstantRanges[i];
VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
createInfo.flags = m_flags;
createInfo.setLayoutCount = m_setLayoutCount;
createInfo.pSetLayouts = m_setLayouts.data();
createInfo.pushConstantRangeCount = m_pushConstantRangeCount;
createInfo.pPushConstantRanges = m_pushConstantRanges.data();
m_pipelineLayout = createPipelineLayout(vk, device, &createInfo);
}
PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineLayoutWrapper&& rhs) noexcept
: m_pipelineConstructionType (rhs.m_pipelineConstructionType)
, m_vk (rhs.m_vk)
, m_device (rhs.m_device)
, m_flags (rhs.m_flags)
, m_setLayoutCount (rhs.m_setLayoutCount)
, m_setLayouts (std::move(rhs.m_setLayouts))
, m_pushConstantRangeCount (rhs.m_pushConstantRangeCount)
, m_pushConstantRanges (std::move(rhs.m_pushConstantRanges))
, m_pipelineLayout (rhs.m_pipelineLayout)
{ }
PipelineLayoutWrapper& PipelineLayoutWrapper::operator= (PipelineLayoutWrapper&& rhs)
{
m_pipelineConstructionType = rhs.m_pipelineConstructionType;
m_vk = rhs.m_vk;
m_device = rhs.m_device;
m_flags = rhs.m_flags;
m_setLayoutCount = rhs.m_setLayoutCount;
m_setLayouts = std::move(rhs.m_setLayouts);
m_pushConstantRangeCount = rhs.m_pushConstantRangeCount;
m_pushConstantRanges = std::move(rhs.m_pushConstantRanges);
m_pipelineLayout = rhs.m_pipelineLayout;
return *this;
}
void PipelineLayoutWrapper::bindDescriptorSets (VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) const
{
if (!isConstructionTypeShaderObject(m_pipelineConstructionType))
{
m_vk->cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, *m_pipelineLayout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
}
else
{
//m_vk->cmdBindDescriptorSets2EXT(commandBuffer, &m_setLayouts[firstSet], vk::VK_SHADER_STAGE_ALL_GRAPHICS, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
m_vk->cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, *m_pipelineLayout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
}
}
#ifndef CTS_USES_VULKANSC
RenderPassWrapper::SubpassDependency::SubpassDependency (const VkSubpassDependency& dependency)
: srcSubpass (dependency.srcSubpass)
, dstSubpass (dependency.dstSubpass)
, srcStageMask (dependency.srcStageMask)
, dstStageMask (dependency.dstStageMask)
, srcAccessMask (dependency.srcAccessMask)
, dstAccessMask (dependency.dstAccessMask)
, dependencyFlags (dependency.dependencyFlags)
, sync2 (false)
{
}
RenderPassWrapper::SubpassDependency::SubpassDependency (const VkSubpassDependency2& dependency)
: srcSubpass (dependency.srcSubpass)
, dstSubpass (dependency.dstSubpass)
, srcStageMask (0u)
, dstStageMask (0u)
, srcAccessMask (0u)
, dstAccessMask (0u)
, dependencyFlags (dependency.dependencyFlags)
, sync2 (false)
{
DE_ASSERT(dependency.viewOffset == 0);
const auto memBarrier = findStructure<VkMemoryBarrier2>(dependency.pNext);
if (memBarrier)
{
srcStageMask = memBarrier->srcStageMask;
dstStageMask = memBarrier->dstStageMask;
srcAccessMask = memBarrier->srcAccessMask;
dstAccessMask = memBarrier->dstAccessMask;
sync2 = true;
}
else
{
srcStageMask = dependency.srcStageMask;
dstStageMask = dependency.dstStageMask;
srcAccessMask = dependency.srcAccessMask;
dstAccessMask = dependency.dstAccessMask;
}
}
#endif // CTS_USES_VULKANSC
RenderPassWrapper::RenderPassWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, const VkRenderPassCreateInfo* pCreateInfo)
: m_isDynamicRendering (vk::isConstructionTypeShaderObject(pipelineConstructionType))
#ifndef CTS_USES_VULKANSC
, m_renderingInfo ()
, m_secondaryCommandBuffers (false)
#endif
{
if (!m_isDynamicRendering)
{
m_renderPass = vk::createRenderPass(vk, device, pCreateInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
const auto multiView = findStructure<VkRenderPassMultiviewCreateInfo>(pCreateInfo->pNext);
if (multiView)
{
for (deUint32 i = 0; i < multiView->subpassCount; ++i)
m_viewMasks.push_back(multiView->pViewMasks[i]);
}
m_attachments.resize(pCreateInfo->attachmentCount);
m_layouts.resize(pCreateInfo->attachmentCount);
for (deUint32 i = 0; i < pCreateInfo->attachmentCount; ++i)
{
m_attachments[i] = vk::initVulkanStructure();
m_attachments[i].flags = pCreateInfo->pAttachments[i].flags;
m_attachments[i].format = pCreateInfo->pAttachments[i].format;
m_attachments[i].samples = pCreateInfo->pAttachments[i].samples;
m_attachments[i].loadOp = pCreateInfo->pAttachments[i].loadOp;
m_attachments[i].storeOp = pCreateInfo->pAttachments[i].storeOp;
m_attachments[i].stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp;
m_attachments[i].stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp;
m_attachments[i].initialLayout = pCreateInfo->pAttachments[i].initialLayout;
m_attachments[i].finalLayout = pCreateInfo->pAttachments[i].finalLayout;
m_layouts[i] = pCreateInfo->pAttachments[i].initialLayout;
}
m_subpasses.resize(pCreateInfo->subpassCount);
for (deUint32 s = 0; s < pCreateInfo->subpassCount; ++s)
{
// Input attachments are not supported with dynamic rendering
DE_ASSERT(pCreateInfo->pSubpasses[s].inputAttachmentCount == 0);
auto& subpass = m_subpasses[s];
subpass.m_colorAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
for (deUint32 i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
{
deUint32 j = pCreateInfo->pSubpasses[s].pColorAttachments[i].attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_colorAttachments[i].attachmentInfo = vk::initVulkanStructure();
subpass.m_colorAttachments[i].index = j;
subpass.m_colorAttachments[i].format = pCreateInfo->pAttachments[j].format;
subpass.m_colorAttachments[i].attachmentInfo.imageView = DE_NULL;
subpass.m_colorAttachments[i].attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pColorAttachments[i].layout;
subpass.m_colorAttachments[i].attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_colorAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
subpass.m_colorAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_colorAttachments[i].attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_colorAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_colorAttachments[i].attachmentInfo.clearValue = {};
}
else
{
subpass.m_colorAttachments[i].index = VK_ATTACHMENT_UNUSED;
}
}
if (pCreateInfo->pSubpasses[s].pDepthStencilAttachment != DE_NULL)
{
deUint32 j = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
subpass.m_depthStencilAttachment.index = j;
subpass.m_depthStencilAttachment.format = pCreateInfo->pAttachments[j].format;
subpass.m_depthStencilAttachment.attachmentInfo.imageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->layout;
subpass.m_depthStencilAttachment.attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_depthStencilAttachment.attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_depthStencilAttachment.attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_depthStencilAttachment.attachmentInfo.clearValue = {};
subpass.m_depthStencilAttachment.stencilLoadOp = pCreateInfo->pAttachments[j].stencilLoadOp;
subpass.m_depthStencilAttachment.stencilStoreOp = pCreateInfo->pAttachments[j].stencilStoreOp;
}
else
{
subpass.m_depthStencilAttachment.index = VK_ATTACHMENT_UNUSED;
}
}
if (pCreateInfo->pSubpasses[s].pResolveAttachments != DE_NULL)
{
subpass.m_resolveAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
for (deUint32 i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
{
deUint32 j = pCreateInfo->pSubpasses[s].pResolveAttachments[i].attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_resolveAttachments[i].attachmentInfo = vk::initVulkanStructure();
subpass.m_resolveAttachments[i].index = j;
subpass.m_resolveAttachments[i].format = pCreateInfo->pAttachments[j].format;
subpass.m_resolveAttachments[i].attachmentInfo.imageView = DE_NULL;
subpass.m_resolveAttachments[i].attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pResolveAttachments[i].layout;
subpass.m_resolveAttachments[i].attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_resolveAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
subpass.m_resolveAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_resolveAttachments[i].attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_resolveAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_resolveAttachments[i].attachmentInfo.clearValue = {};
}
else
{
subpass.m_resolveAttachments[i].index = VK_ATTACHMENT_UNUSED;
}
}
}
}
m_dependencies.reserve(pCreateInfo->dependencyCount);
for (uint32_t depIdx = 0u; depIdx < pCreateInfo->dependencyCount; ++depIdx)
m_dependencies.emplace_back(pCreateInfo->pDependencies[depIdx]);
#endif
}
}
RenderPassWrapper::RenderPassWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo)
: RenderPassWrapper (vk, device, pCreateInfo, isConstructionTypeShaderObject(pipelineConstructionType))
{}
RenderPassWrapper::RenderPassWrapper (const DeviceInterface& vk, VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo, bool dynamicRendering)
: m_isDynamicRendering (dynamicRendering)
#ifndef CTS_USES_VULKANSC
, m_renderingInfo ()
, m_secondaryCommandBuffers (false)
#endif
{
if (!m_isDynamicRendering)
{
m_renderPass = vk::createRenderPass2(vk, device, pCreateInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
const auto multiView = findStructure<VkRenderPassMultiviewCreateInfo>(pCreateInfo->pNext);
if (multiView)
{
for (deUint32 i = 0; i < multiView->subpassCount; ++i)
m_viewMasks.push_back(multiView->pViewMasks[i]);
}
m_attachments.resize(pCreateInfo->attachmentCount);
m_layouts.resize(pCreateInfo->attachmentCount);
for (deUint32 i = 0; i < pCreateInfo->attachmentCount; ++i)
{
m_attachments[i] = pCreateInfo->pAttachments[i];
m_layouts[i] = pCreateInfo->pAttachments[i].initialLayout;
}
m_subpasses.resize(pCreateInfo->subpassCount);
for (deUint32 s = 0; s < pCreateInfo->subpassCount; ++s)
{
// Input attachments are not supported with dynamic rendering
DE_ASSERT(pCreateInfo->pSubpasses[s].inputAttachmentCount == 0);
auto& subpass = m_subpasses[s];
subpass.m_colorAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
const auto msrtss = findStructure<VkMultisampledRenderToSingleSampledInfoEXT>(pCreateInfo->pSubpasses[s].pNext);
if (msrtss)
subpass.m_msrtss = *msrtss;
const auto dsr = findStructure<VkSubpassDescriptionDepthStencilResolve>(pCreateInfo->pSubpasses[s].pNext);
if (dsr)
{
subpass.m_dsr = *dsr;
if (dsr->pDepthStencilResolveAttachment)
{
subpass.m_depthStencilResolveAttachment = *dsr->pDepthStencilResolveAttachment;
subpass.m_dsr.pDepthStencilResolveAttachment = &subpass.m_depthStencilResolveAttachment;
}
}
for (deUint32 i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
{
deUint32 j = pCreateInfo->pSubpasses[s].pColorAttachments[i].attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_colorAttachments[i].attachmentInfo = vk::initVulkanStructure();
subpass.m_colorAttachments[i].index = j;
subpass.m_colorAttachments[i].format = pCreateInfo->pAttachments[j].format;
subpass.m_colorAttachments[i].attachmentInfo.imageView = DE_NULL;
subpass.m_colorAttachments[i].attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pColorAttachments[i].layout;
subpass.m_colorAttachments[i].attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_colorAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
subpass.m_colorAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_colorAttachments[i].attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_colorAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_colorAttachments[i].attachmentInfo.clearValue = {};
}
else
{
subpass.m_colorAttachments[i].index = VK_ATTACHMENT_UNUSED;
}
}
if (pCreateInfo->pSubpasses[s].pDepthStencilAttachment != DE_NULL)
{
deUint32 j = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
subpass.m_depthStencilAttachment.index = j;
subpass.m_depthStencilAttachment.format = pCreateInfo->pAttachments[j].format;
subpass.m_depthStencilAttachment.attachmentInfo.imageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->layout;
subpass.m_depthStencilAttachment.attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_depthStencilAttachment.attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_depthStencilAttachment.attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_depthStencilAttachment.attachmentInfo.clearValue = {};
subpass.m_depthStencilAttachment.stencilLoadOp = pCreateInfo->pAttachments[j].stencilLoadOp;
subpass.m_depthStencilAttachment.stencilStoreOp = pCreateInfo->pAttachments[j].stencilStoreOp;
}
else
{
subpass.m_depthStencilAttachment.index = VK_ATTACHMENT_UNUSED;
}
}
if (pCreateInfo->pSubpasses[s].pResolveAttachments != DE_NULL)
{
subpass.m_resolveAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
for (deUint32 i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
{
deUint32 j = pCreateInfo->pSubpasses[s].pResolveAttachments[i].attachment;
if (j < pCreateInfo->attachmentCount)
{
subpass.m_resolveAttachments[i].attachmentInfo = vk::initVulkanStructure();
subpass.m_resolveAttachments[i].index = j;
subpass.m_resolveAttachments[i].format = pCreateInfo->pAttachments[j].format;
subpass.m_resolveAttachments[i].attachmentInfo.imageView = DE_NULL;
subpass.m_resolveAttachments[i].attachmentInfo.imageLayout = pCreateInfo->pSubpasses[s].pResolveAttachments[i].layout;
subpass.m_resolveAttachments[i].attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_resolveAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
subpass.m_resolveAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_resolveAttachments[i].attachmentInfo.loadOp = pCreateInfo->pAttachments[j].loadOp;
subpass.m_resolveAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
subpass.m_resolveAttachments[i].attachmentInfo.clearValue = {};
}
else
{
subpass.m_resolveAttachments[i].index = VK_ATTACHMENT_UNUSED;
}
}
}
}
m_dependencies.reserve(pCreateInfo->dependencyCount);
for (uint32_t depIdx = 0u; depIdx < pCreateInfo->dependencyCount; ++depIdx)
m_dependencies.emplace_back(pCreateInfo->pDependencies[depIdx]);
#endif
}
}
RenderPassWrapper::RenderPassWrapper (PipelineConstructionType pipelineConstructionType, const DeviceInterface& vk, const VkDevice device, const VkFormat colorFormat, const VkFormat depthStencilFormat, const VkAttachmentLoadOp loadOperation, const VkImageLayout finalLayoutColor,
const VkImageLayout finalLayoutDepthStencil, const VkImageLayout subpassLayoutColor, const VkImageLayout subpassLayoutDepthStencil, const VkAllocationCallbacks* const allocationCallbacks)
: m_isDynamicRendering (isConstructionTypeShaderObject(pipelineConstructionType))
#ifndef CTS_USES_VULKANSC
, m_renderingInfo ()
#endif
{
if (!m_isDynamicRendering)
{
m_renderPass = vk::makeRenderPass(vk, device, colorFormat, depthStencilFormat, loadOperation, finalLayoutColor, finalLayoutDepthStencil, subpassLayoutColor, subpassLayoutDepthStencil, allocationCallbacks);
}
else
{
#ifndef CTS_USES_VULKANSC
const bool hasColor = colorFormat != VK_FORMAT_UNDEFINED;
const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
const VkImageLayout initialLayoutColor = loadOperation == VK_ATTACHMENT_LOAD_OP_LOAD ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
const VkImageLayout initialLayoutDepthStencil = loadOperation == VK_ATTACHMENT_LOAD_OP_LOAD ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
m_subpasses.resize(1);
auto& subpass = m_subpasses[0];
if (hasColor)
{
subpass.m_colorAttachments.resize(1);
subpass.m_colorAttachments[0].attachmentInfo = vk::initVulkanStructure();
subpass.m_colorAttachments[0].index = 0u;
subpass.m_colorAttachments[0].format = colorFormat;
subpass.m_colorAttachments[0].attachmentInfo.imageView = DE_NULL;
subpass.m_colorAttachments[0].attachmentInfo.imageLayout = subpassLayoutColor;
subpass.m_colorAttachments[0].attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_colorAttachments[0].attachmentInfo.resolveImageView = DE_NULL;
subpass.m_colorAttachments[0].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_colorAttachments[0].attachmentInfo.loadOp = loadOperation;
subpass.m_colorAttachments[0].attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
subpass.m_colorAttachments[0].attachmentInfo.clearValue = {};
const VkAttachmentDescription2 colorAttachmentDescription =
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
DE_NULL,
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
colorFormat, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
loadOperation, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
initialLayoutColor, // VkImageLayout initialLayout
finalLayoutColor // VkImageLayout finalLayout
};
m_attachments.push_back(colorAttachmentDescription);
m_layouts.push_back(colorAttachmentDescription.initialLayout);
}
if (hasDepthStencil)
{
subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
subpass.m_depthStencilAttachment.index = hasColor ? 1u : 0u;
subpass.m_depthStencilAttachment.format = depthStencilFormat;
subpass.m_depthStencilAttachment.attachmentInfo.imageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.imageLayout = subpassLayoutDepthStencil;
subpass.m_depthStencilAttachment.attachmentInfo.resolveMode = vk::VK_RESOLVE_MODE_NONE;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView = DE_NULL;
subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
subpass.m_depthStencilAttachment.attachmentInfo.loadOp = loadOperation;
subpass.m_depthStencilAttachment.attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
subpass.m_depthStencilAttachment.attachmentInfo.clearValue = {};
subpass.m_depthStencilAttachment.stencilLoadOp = loadOperation;
subpass.m_depthStencilAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
const VkAttachmentDescription2 depthStencilAttachmentDescription =
{
VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
DE_NULL,
(VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
depthStencilFormat, // VkFormat format
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
loadOperation, // VkAttachmentLoadOp loadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
loadOperation, // VkAttachmentLoadOp stencilLoadOp
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
initialLayoutDepthStencil, // VkImageLayout initialLayout
finalLayoutDepthStencil // VkImageLayout finalLayout
};
m_attachments.push_back(depthStencilAttachmentDescription);
m_layouts.push_back(depthStencilAttachmentDescription.initialLayout);
}
#endif
}
}
RenderPassWrapper::RenderPassWrapper (RenderPassWrapper&& rhs) noexcept
: m_isDynamicRendering (rhs.m_isDynamicRendering)
, m_renderPass (rhs.m_renderPass)
, m_framebuffer (rhs.m_framebuffer)
#ifndef CTS_USES_VULKANSC
, m_subpasses (std::move(rhs.m_subpasses))
, m_dependencies (std::move(rhs.m_dependencies))
, m_attachments (std::move(rhs.m_attachments))
, m_images (std::move(rhs.m_images))
, m_imageViews (std::move(rhs.m_imageViews))
, m_clearValues (std::move(rhs.m_clearValues))
, m_layouts (std::move(rhs.m_layouts))
, m_activeSubpass (rhs.m_activeSubpass)
, m_renderingInfo (rhs.m_renderingInfo)
, m_layers (rhs.m_layers)
, m_viewMasks (std::move(rhs.m_viewMasks))
, m_secondaryCommandBuffers (rhs.m_secondaryCommandBuffers)
#endif
{
}
RenderPassWrapper& RenderPassWrapper::operator= (RenderPassWrapper&& rhs) noexcept
{
m_isDynamicRendering = rhs.m_isDynamicRendering;
m_renderPass = rhs.m_renderPass;
m_framebuffer = rhs.m_framebuffer;
#ifndef CTS_USES_VULKANSC
m_subpasses = std::move(rhs.m_subpasses);
m_dependencies = std::move(rhs.m_dependencies);
m_attachments = std::move(rhs.m_attachments);
m_images = std::move(rhs.m_images);
m_imageViews = std::move(rhs.m_imageViews);
m_clearValues = std::move(rhs.m_clearValues);
m_layouts = std::move(rhs.m_layouts);
m_activeSubpass = rhs.m_activeSubpass;
m_renderingInfo = rhs.m_renderingInfo;
m_layers = rhs.m_layers;
m_viewMasks = std::move(rhs.m_viewMasks);
m_secondaryCommandBuffers = rhs.m_secondaryCommandBuffers;
#endif
return *this;
}
#ifndef CTS_USES_VULKANSC
void RenderPassWrapper::clearAttachments(const DeviceInterface& vk, const VkCommandBuffer commandBuffer) const
{
for (deUint32 i = 0; i < (deUint32)m_attachments.size() && i < (deUint32)m_clearValues.size(); ++i)
{
const auto tcuFormat = vk::mapVkFormat(m_attachments[i].format);
bool hasDepthAspect = tcu::hasDepthComponent(tcuFormat.order);
bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
if (m_attachments[i].loadOp != vk::VK_ATTACHMENT_LOAD_OP_CLEAR && !(hasStencilAspect && m_attachments[i].stencilLoadOp == vk::VK_ATTACHMENT_LOAD_OP_CLEAR))
continue;
vk::VkRenderingInfo renderingInfo = vk::initVulkanStructure();
renderingInfo.renderArea = m_renderingInfo.renderArea;
renderingInfo.layerCount = m_renderingInfo.layerCount;
vk::VkRenderingAttachmentInfo attachment = vk::initVulkanStructure();
attachment.imageView = m_imageViews[i];
attachment.imageLayout = m_layouts[i];
attachment.loadOp = vk::VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.storeOp = vk::VK_ATTACHMENT_STORE_OP_STORE;
attachment.clearValue = m_clearValues[i];
if (hasDepthAspect || hasStencilAspect)
{
renderingInfo.pDepthAttachment = hasDepthAspect ? &attachment : DE_NULL;
renderingInfo.pStencilAttachment = hasStencilAspect ? &attachment : DE_NULL;
}
else
{
renderingInfo.colorAttachmentCount = 1u;
renderingInfo.pColorAttachments = &attachment;
}
vk.cmdBeginRendering(commandBuffer, &renderingInfo);
vk.cmdEndRendering(commandBuffer);
}
}
void RenderPassWrapper::updateLayout(VkImage updatedImage, VkImageLayout newLayout) const
{
for (deUint32 i = 0; i < (deUint32)m_images.size(); ++i)
if (m_images[i] == updatedImage)
m_layouts[i] = newLayout;
}
namespace
{
void recordImageBarrier (const DeviceInterface& vk,
const VkCommandBuffer commandBuffer,
const bool sync2,
const VkPipelineStageFlags2 srcStageMask,
const VkAccessFlags2 srcAccessMask,
const VkPipelineStageFlags2 dstStageMask,
const VkAccessFlags2 dstAccessMask,
const VkImageLayout prevLayout,
const VkImageLayout newLayout,
const VkImage image,
const VkImageSubresourceRange& subresourceRange)
{
if (sync2)
{
const auto barrier = makeImageMemoryBarrier2(
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
prevLayout,
newLayout,
image,
subresourceRange);
const VkDependencyInfo depInfo =
{
VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkDependencyFlags dependencyFlags;
0u, // uint32_t memoryBarrierCount;
nullptr, // const VkMemoryBarrier2* pMemoryBarriers;
0u, // uint32_t bufferMemoryBarrierCount;
nullptr, // const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
1u, // uint32_t imageMemoryBarrierCount;
&barrier, // const VkImageMemoryBarrier2* pImageMemoryBarriers;
};
vk.cmdPipelineBarrier2(commandBuffer, &depInfo);
}
else
{
const auto barrier = makeImageMemoryBarrier(
static_cast<VkAccessFlags>(srcAccessMask),
static_cast<VkAccessFlags>(dstAccessMask),
prevLayout,
newLayout,
image,
subresourceRange);
vk.cmdPipelineBarrier(
commandBuffer,
static_cast<VkPipelineStageFlags>(srcStageMask),
static_cast<VkPipelineStageFlags>(dstStageMask),
0u, 0u, nullptr, 0u, nullptr, 1u, &barrier);
}
}
} // anonymous namespace
void RenderPassWrapper::transitionLayouts (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const Subpass& subpass, bool renderPassBegin) const
{
// Use the access and stage flags for dependencies on external subpasses in
// the initial layout transitions for images.
VkAccessFlags2 externalAccessFlags = 0u;
VkPipelineStageFlags2 externalStageFlags = 0u;
bool sync2 = false;
if (renderPassBegin)
{
for (const auto& dep : m_dependencies)
{
if (dep.srcSubpass == VK_SUBPASS_EXTERNAL)
{
externalAccessFlags |= dep.srcAccessMask;
externalStageFlags |= dep.srcStageMask;
}
if (dep.sync2)
sync2 = true;
}
}
for (deUint32 i = 0; i < (deUint32)m_attachments.size(); ++i)
{
// renderPassBegin is true when vkCmdBeginRenderPass should be called in a normal renderPass, and it is false when vkCmdNextSupass should be called
// Every image is transioned from VK_IMAGE_LAYOUT_UNDEFINED to it's first used layout, so that all images can be cleared in the beginning
if (renderPassBegin && m_layouts[i] != vk::VK_IMAGE_LAYOUT_UNDEFINED)
continue;
if (m_images[i] != VK_NULL_HANDLE)
{
for (deUint32 j = 0; j < (deUint32)subpass.m_colorAttachments.size(); ++j)
{
if (subpass.m_colorAttachments[j].index == i)
{
const auto subresourceRange = makeImageSubresourceRange(
vk::VK_IMAGE_ASPECT_COLOR_BIT,
0u,
VK_REMAINING_MIP_LEVELS,
0u,
VK_REMAINING_ARRAY_LAYERS);
const VkPipelineStageFlags2 srcStageMask = (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
const VkAccessFlags2 srcAccessMask = externalAccessFlags;
const VkPipelineStageFlags2 dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
const VkAccessFlags2 dstAccessMask = vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
const VkImageLayout newLayout = subpass.m_colorAttachments[j].attachmentInfo.imageLayout;
recordImageBarrier(vk,
commandBuffer,
sync2,
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
m_layouts[i],
newLayout,
m_images[i],
subresourceRange);
updateLayout(m_images[i], newLayout);
}
}
if (subpass.m_depthStencilAttachment.index == i)
{
const auto tcuFormat = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
const bool hasDepthAspect = tcu::hasDepthComponent(tcuFormat.order);
const bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
VkImageAspectFlags aspect = (VkImageAspectFlags)0u;
if (hasDepthAspect)
aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
if (hasStencilAspect)
aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
const auto subresourceRange = makeImageSubresourceRange(
aspect,
0u,
VK_REMAINING_MIP_LEVELS,
0u,
VK_REMAINING_ARRAY_LAYERS);
const VkPipelineStageFlags2 srcStageMask = (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
const VkAccessFlags2 srcAccessMask = externalAccessFlags;
const VkPipelineStageFlags2 dstStageMask = (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
const VkAccessFlags2 dstAccessMask = (vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
const VkImageLayout newLayout = subpass.m_depthStencilAttachment.attachmentInfo.imageLayout;
recordImageBarrier(vk,
commandBuffer,
sync2,
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
m_layouts[i],
newLayout,
m_images[i],
subresourceRange);
updateLayout(m_images[i], newLayout);
}
for (deUint32 j = 0; j < (deUint32)subpass.m_resolveAttachments.size(); ++j)
{
if (subpass.m_resolveAttachments[j].index == i)
{
const auto subresourceRange = makeImageSubresourceRange(
vk::VK_IMAGE_ASPECT_COLOR_BIT,
0u,
VK_REMAINING_MIP_LEVELS,
0u,
VK_REMAINING_ARRAY_LAYERS);
const VkPipelineStageFlags2 srcStageMask = (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
const VkAccessFlags2 srcAccessMask = externalAccessFlags;
const VkPipelineStageFlags2 dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
const VkAccessFlags2 dstAccessMask = vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
const VkImageLayout newLayout = subpass.m_resolveAttachments[j].attachmentInfo.imageLayout;
recordImageBarrier(vk,
commandBuffer,
sync2,
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
m_layouts[i],
newLayout,
m_images[i],
subresourceRange);
updateLayout(m_images[i], newLayout);
}
}
if (subpass.m_dsr.sType == vk::VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE)
{
if (subpass.m_dsr.pDepthStencilResolveAttachment && i == subpass.m_dsr.pDepthStencilResolveAttachment->attachment)
{
const auto tcuFormat = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
const bool hasDepthAspect = tcu::hasDepthComponent(tcuFormat.order);
const bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
VkImageAspectFlags aspect = (VkImageAspectFlags)0u;
if (hasDepthAspect)
aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
if (hasStencilAspect)
aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
const auto subresourceRange = makeImageSubresourceRange(
aspect,
0u,
VK_REMAINING_MIP_LEVELS,
0u,
VK_REMAINING_ARRAY_LAYERS);
const VkPipelineStageFlags2 srcStageMask = (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
const VkAccessFlags2 srcAccessMask = externalAccessFlags;
const VkPipelineStageFlags2 dstStageMask = (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
const VkAccessFlags2 dstAccessMask = vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
const VkImageLayout newLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
recordImageBarrier(vk,
commandBuffer,
sync2,
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
m_layouts[i],
newLayout,
m_images[i],
subresourceRange);
updateLayout(m_images[i], newLayout);
}
}
}
}
}
void RenderPassWrapper::insertDependencies (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, uint32_t subpassIdx) const
{
for (const auto& dep : m_dependencies)
{
// Subpass self-dependencies should be handled with manual barriers inside the render pass.
if (dep.dstSubpass != subpassIdx || dep.srcSubpass == subpassIdx)
continue;
if (dep.sync2)
{
const VkMemoryBarrier2 barrier =
{
VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
nullptr, // const void* pNext;
dep.srcStageMask, // VkPipelineStageFlags2 srcStageMask;
dep.srcAccessMask, // VkAccessFlags2 srcAccessMask;
dep.dstStageMask, // VkPipelineStageFlags2 dstStageMask;
dep.dstAccessMask, // VkAccessFlags2 dstAccessMask;
};
const VkDependencyInfo depInfo =
{
VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
dep.dependencyFlags, // VkDependencyFlags dependencyFlags;
1u, // uint32_t memoryBarrierCount;
&barrier, // const VkMemoryBarrier2* pMemoryBarriers;
0u, // uint32_t bufferMemoryBarrierCount;
nullptr, // const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
0u, // uint32_t imageMemoryBarrierCount;
nullptr, // const VkImageMemoryBarrier2* pImageMemoryBarriers;
};
vk.cmdPipelineBarrier2(commandBuffer, &depInfo);
}
else
{
const VkMemoryBarrier barrier =
{
VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
nullptr, // const void* pNext;
static_cast<VkAccessFlags>(dep.srcAccessMask), // VkAccessFlags srcAccessMask;
static_cast<VkAccessFlags>(dep.dstAccessMask), // VkAccessFlags dstAccessMask;
};
vk.cmdPipelineBarrier(commandBuffer,
static_cast<VkPipelineStageFlags>(dep.srcStageMask),
static_cast<VkPipelineStageFlags>(dep.dstStageMask),
dep.dependencyFlags,
1u, &barrier,
0u, nullptr, 0u, nullptr);
}
}
}
void RenderPassWrapper::fillInheritanceRenderingInfo(deUint32 subpassIndex, std::vector<vk::VkFormat>* colorFormats, vk::VkCommandBufferInheritanceRenderingInfo* inheritanceRenderingInfo) const
{
const auto& subpass = m_subpasses[subpassIndex];
colorFormats->resize(subpass.m_colorAttachments.size());
for (deUint32 i = 0; i < (deUint32)subpass.m_colorAttachments.size(); ++i)
(*colorFormats)[i] = subpass.m_colorAttachments[i].format;
inheritanceRenderingInfo->colorAttachmentCount = (deUint32)subpass.m_colorAttachments.size();
inheritanceRenderingInfo->pColorAttachmentFormats = colorFormats->data();
if (subpass.m_depthStencilAttachment.format != vk::VK_FORMAT_UNDEFINED)
{
const auto tcuFormat = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
if (tcu::hasDepthComponent(tcuFormat.order))
inheritanceRenderingInfo->depthAttachmentFormat = subpass.m_depthStencilAttachment.format;
if (tcu::hasStencilComponent(tcuFormat.order))
inheritanceRenderingInfo->stencilAttachmentFormat = subpass.m_depthStencilAttachment.format;
}
if (subpassIndex < (deUint32)m_viewMasks.size())
inheritanceRenderingInfo->viewMask = m_viewMasks[subpassIndex];
}
#endif
void RenderPassWrapper::begin (const DeviceInterface& vk,
const VkCommandBuffer commandBuffer,
const VkRect2D& renderArea,
const deUint32 clearValueCount,
const VkClearValue* clearValues,
const VkSubpassContents contents,
const void* pNext) const
{
if (!m_isDynamicRendering)
{
beginRenderPass(vk, commandBuffer, *m_renderPass, *m_framebuffer, renderArea, clearValueCount, clearValues, contents, pNext);
}
else
{
#ifndef CTS_USES_VULKANSC
m_activeSubpass = 0;
m_clearValues.resize(clearValueCount);
for (deUint32 i = 0; i < clearValueCount; ++i)
m_clearValues[i] = clearValues[i];
for (deUint32 i = 0; i < (deUint32)m_subpasses.size(); ++i)
transitionLayouts(vk, commandBuffer, m_subpasses[i], true);
insertDependencies(vk, commandBuffer, 0u);
m_secondaryCommandBuffers = contents == vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
m_renderingInfo = vk::initVulkanStructure();
m_renderingInfo.flags = (vk::VkRenderingFlags)0u;
m_renderingInfo.renderArea = renderArea;
m_renderingInfo.layerCount = m_layers;
m_renderingInfo.viewMask = 0x0;
clearAttachments(vk, commandBuffer);
beginRendering(vk, commandBuffer);
#endif
}
}
void RenderPassWrapper::begin (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkRect2D& renderArea, const VkClearValue& clearValue, const VkSubpassContents contents) const
{
begin(vk, commandBuffer, renderArea, 1u, &clearValue, contents);
}
void RenderPassWrapper::begin (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkRect2D& renderArea, const tcu::Vec4& clearColor, const VkSubpassContents contents) const
{
const VkClearValue clearValue = makeClearValueColor(clearColor);
begin(vk, commandBuffer, renderArea, clearValue, contents);
}
void RenderPassWrapper::begin(const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkRect2D& renderArea, const tcu::Vec4& clearColor, const float clearDepth, const deUint32 clearStencil, const VkSubpassContents contents) const
{
const VkClearValue clearValues[] =
{
makeClearValueColor(clearColor), // attachment 0
makeClearValueDepthStencil(clearDepth, clearStencil), // attachment 1
};
begin(vk, commandBuffer, renderArea, 2, clearValues, contents);
}
void RenderPassWrapper::begin (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkRect2D& renderArea, const VkSubpassContents contents) const
{
begin(vk, commandBuffer, renderArea, 0u, DE_NULL, contents);
}
void RenderPassWrapper::begin(const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkRect2D& renderArea, const tcu::UVec4& clearColor, const VkSubpassContents contents) const
{
const VkClearValue clearValue = makeClearValueColorU32(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
begin(vk, commandBuffer, renderArea, clearValue, contents);
}
void RenderPassWrapper::end (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) const
{
if (!m_isDynamicRendering)
{
vk.cmdEndRenderPass(commandBuffer);
}
else
{
#ifndef CTS_USES_VULKANSC
vk.cmdEndRendering(commandBuffer);
// Use dependencies for external subpasses to extract destination access
// flags and pipeline stage flags for the final layout transition
// barriers.
VkAccessFlags2 externalAccessFlags = 0u;
VkPipelineStageFlags2 externalStageFlags = 0u;
bool sync2 = false;
for (const auto& dep : m_dependencies)
{
if (dep.dstSubpass == VK_SUBPASS_EXTERNAL)
{
externalAccessFlags |= dep.dstAccessMask;
externalStageFlags |= dep.dstStageMask;
}
if (dep.sync2)
sync2 = true;
}
for (deUint32 i = 0; i < (deUint32)m_attachments.size(); ++i)
{
if (m_layouts[i] == m_attachments[i].finalLayout)
continue;
const bool color = !vk::isDepthStencilFormat(m_attachments[i].format);
VkImageAspectFlags aspect = color ? (vk::VkImageAspectFlags)vk::VK_IMAGE_ASPECT_COLOR_BIT : (vk::VkImageAspectFlags)0u;
if (!color)
{
const bool hasDepthAspect = tcu::hasDepthComponent(vk::mapVkFormat(m_attachments[i].format).order);
const bool hasStencilAspect = tcu::hasStencilComponent(vk::mapVkFormat(m_attachments[i].format).order);
if (hasDepthAspect)
aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
if (hasStencilAspect)
aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
}
const auto subresourceRange = makeImageSubresourceRange(
aspect,
0u,
VK_REMAINING_MIP_LEVELS,
0u,
VK_REMAINING_ARRAY_LAYERS);
const VkPipelineStageFlags2 srcStageMask = (color ? vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT : vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
const VkAccessFlags2 srcAccessMask = (color ? vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT : vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
const VkPipelineStageFlags2 dstStageMask = (vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | externalStageFlags);
const VkAccessFlags2 dstAccessMask = externalAccessFlags;
const VkImageLayout newLayout = m_attachments[i].finalLayout;
recordImageBarrier(vk,
commandBuffer,
sync2,
srcStageMask,
srcAccessMask,
dstStageMask,
dstAccessMask,
m_layouts[i],
newLayout,
m_images[i],
subresourceRange);
}
insertDependencies(vk, commandBuffer, VK_SUBPASS_EXTERNAL);
#endif
}
}
void RenderPassWrapper::beginRendering (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) const
{
DE_UNREF(vk);
DE_UNREF(commandBuffer);
#ifndef CTS_USES_VULKANSC
const auto& subpass = m_subpasses[m_activeSubpass];
std::vector<vk::VkRenderingAttachmentInfo> colorAttachments;
for (deUint32 i = 0; i < (deUint32)subpass.m_colorAttachments.size(); ++i)
{
colorAttachments.emplace_back();
auto& colorAttachment = colorAttachments.back();
colorAttachment = vk::initVulkanStructure();
if (subpass.m_colorAttachments[i].index == VK_ATTACHMENT_UNUSED)
continue;
colorAttachment = subpass.m_colorAttachments[i].attachmentInfo;
colorAttachment.loadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
if (!subpass.m_resolveAttachments.empty() && subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
{
if (isUintFormat(subpass.m_resolveAttachments[i].format) || isIntFormat(subpass.m_resolveAttachments[i].format))
colorAttachment.resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
else
colorAttachment.resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
colorAttachment.resolveImageView = subpass.m_resolveAttachments[i].attachmentInfo.imageView;
colorAttachment.resolveImageLayout = subpass.m_resolveAttachments[i].attachmentInfo.imageLayout;
}
}
m_renderingInfo.colorAttachmentCount = (deUint32)colorAttachments.size();
m_renderingInfo.pColorAttachments = colorAttachments.data();
subpass.m_depthStencilAttachment.attachmentInfo.loadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
VkRenderingAttachmentInfo depthAttachment = subpass.m_depthStencilAttachment.attachmentInfo;
VkRenderingAttachmentInfo stencilAttachment = subpass.m_depthStencilAttachment.attachmentInfo;
stencilAttachment.storeOp = subpass.m_depthStencilAttachment.stencilStoreOp;
if (depthAttachment.imageView != VK_NULL_HANDLE)
{
const auto tcuFormat = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
bool hasDepthAspect = tcu::hasDepthComponent(tcuFormat.order);
bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
m_renderingInfo.pDepthAttachment = hasDepthAspect ? &depthAttachment : DE_NULL;
m_renderingInfo.pStencilAttachment = hasStencilAspect ? &stencilAttachment : DE_NULL;
}
else
{
m_renderingInfo.pDepthAttachment = DE_NULL;
m_renderingInfo.pStencilAttachment = DE_NULL;
}
if (m_activeSubpass < (deUint32)m_viewMasks.size())
m_renderingInfo.viewMask = m_viewMasks[m_activeSubpass];
m_renderingInfo.pNext = DE_NULL;
if (subpass.m_msrtss.sType == VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT)
{
subpass.m_msrtss.pNext = DE_NULL;
m_renderingInfo.pNext = &subpass.m_msrtss;
}
if (subpass.m_dsr.sType == VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE)
{
depthAttachment.resolveMode = subpass.m_dsr.depthResolveMode;
stencilAttachment.resolveMode = subpass.m_dsr.stencilResolveMode;
if (subpass.m_dsr.pDepthStencilResolveAttachment)
{
depthAttachment.resolveImageView = m_imageViews[subpass.m_dsr.pDepthStencilResolveAttachment->attachment];
depthAttachment.resolveImageLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
stencilAttachment.resolveImageView = m_imageViews[subpass.m_dsr.pDepthStencilResolveAttachment->attachment];
stencilAttachment.resolveImageLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
}
}
m_renderingInfo.flags = (VkRenderingFlags)0u;
if (m_secondaryCommandBuffers)
m_renderingInfo.flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
vk.cmdBeginRendering(commandBuffer, &m_renderingInfo);
#endif
}
void RenderPassWrapper::nextSubpass (const DeviceInterface& vk, const VkCommandBuffer commandBuffer, const VkSubpassContents contents) const
{
if (!m_isDynamicRendering)
{
vk.cmdNextSubpass(commandBuffer, contents);
}
else
{
#ifndef CTS_USES_VULKANSC
vk.cmdEndRendering(commandBuffer);
++m_activeSubpass;
DE_ASSERT(m_activeSubpass < (deUint32)m_subpasses.size());
const auto& subpass = m_subpasses[m_activeSubpass];
transitionLayouts(vk, commandBuffer, subpass, false);
insertDependencies(vk, commandBuffer, m_activeSubpass);
beginRendering(vk, commandBuffer);
#endif
}
}
void RenderPassWrapper::createFramebuffer (const DeviceInterface& vk, const VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const std::vector<vk::VkImage>& images)
{
DE_UNREF(images);
if (!m_isDynamicRendering)
{
m_framebuffer = vk::createFramebuffer(vk, device, pCreateInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
m_images = images;
m_imageViews.resize(pCreateInfo->attachmentCount);
for (deUint32 i = 0; i < pCreateInfo->attachmentCount; ++i)
m_imageViews[i] = pCreateInfo->pAttachments[i];
for (auto& subpass : m_subpasses)
{
for (deUint32 i = 0; i < (deUint32)subpass.m_colorAttachments.size(); ++i)
{
if (subpass.m_colorAttachments[i].index != VK_ATTACHMENT_UNUSED)
subpass.m_colorAttachments[i].attachmentInfo.imageView = pCreateInfo->pAttachments[subpass.m_colorAttachments[i].index];
}
if (subpass.m_depthStencilAttachment.attachmentInfo.imageLayout != VK_IMAGE_LAYOUT_UNDEFINED)
{
if (subpass.m_depthStencilAttachment.index != VK_ATTACHMENT_UNUSED)
subpass.m_depthStencilAttachment.attachmentInfo.imageView = pCreateInfo->pAttachments[subpass.m_depthStencilAttachment.index];
}
for (deUint32 i = 0; i < (deUint32)subpass.m_resolveAttachments.size(); ++i)
{
if (subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
subpass.m_resolveAttachments[i].attachmentInfo.imageView = pCreateInfo->pAttachments[subpass.m_resolveAttachments[i].index];
}
}
m_layers = pCreateInfo->layers;
#endif
}
}
void RenderPassWrapper::createFramebuffer (const DeviceInterface& vk, const VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, vk::VkImage colorImage, vk::VkImage depthStencilImage)
{
DE_UNREF(colorImage);
DE_UNREF(depthStencilImage);
if (!m_isDynamicRendering)
{
m_framebuffer = vk::createFramebuffer(vk, device, pCreateInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
if (colorImage != VK_NULL_HANDLE)
{
m_images.push_back(colorImage);
DE_ASSERT(pCreateInfo->attachmentCount > 0);
m_imageViews.push_back(pCreateInfo->pAttachments[0]);
}
if (depthStencilImage != VK_NULL_HANDLE)
m_images.push_back(depthStencilImage);
for (auto& subpass : m_subpasses)
{
DE_ASSERT(subpass.m_colorAttachments.size() <= 1);
if (pCreateInfo->pAttachments)
{
if (!subpass.m_colorAttachments.empty() && subpass.m_colorAttachments[0].index < pCreateInfo->attachmentCount)
subpass.m_colorAttachments[0].attachmentInfo.imageView = pCreateInfo->pAttachments[subpass.m_colorAttachments[0].index];
if (subpass.m_depthStencilAttachment.index < pCreateInfo->attachmentCount)
subpass.m_depthStencilAttachment.attachmentInfo.imageView = pCreateInfo->pAttachments[subpass.m_depthStencilAttachment.index];
}
}
#endif
}
}
void RenderPassWrapper::createFramebuffer (const DeviceInterface& vk, const VkDevice device, const VkImage colorImage, const VkImageView colorAttachment, const deUint32 width, const deUint32 height, const deUint32 layers)
{
DE_UNREF(colorImage);
if (!m_isDynamicRendering)
{
VkFramebufferCreateInfo createInfo = initVulkanStructure();
createInfo.flags = (VkFramebufferCreateFlags)0u;
createInfo.renderPass = *m_renderPass;
createInfo.attachmentCount = (colorAttachment != VK_NULL_HANDLE) ? 1u : 0u;
createInfo.pAttachments = &colorAttachment;
createInfo.width = width;
createInfo.height = height;
createInfo.layers = layers;
m_framebuffer = vk::createFramebuffer(vk, device, &createInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
m_images.push_back(colorImage);
m_imageViews.push_back(colorAttachment);
if (colorImage != VK_NULL_HANDLE)
{
for (auto& subpass : m_subpasses)
{
DE_ASSERT(subpass.m_colorAttachments.size() == 1);
subpass.m_colorAttachments[0].attachmentInfo.imageView = colorAttachment;
}
}
#endif
}
}
void RenderPassWrapper::createFramebuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 attachmentCount, const VkImage* imagesArray, const VkImageView* attachmentsArray, const deUint32 width, const deUint32 height, const deUint32 layers)
{
DE_UNREF(imagesArray);
if (!m_isDynamicRendering)
{
VkFramebufferCreateInfo createInfo = initVulkanStructure();
createInfo.flags = (VkFramebufferCreateFlags)0u;
createInfo.renderPass = *m_renderPass;
createInfo.attachmentCount = attachmentCount;
createInfo.pAttachments = attachmentsArray;
createInfo.width = width;
createInfo.height = height;
createInfo.layers = layers;
m_framebuffer = vk::createFramebuffer(vk, device, &createInfo);
}
else
{
#ifndef CTS_USES_VULKANSC
for (deUint32 i = 0; i < attachmentCount; ++i)
{
m_images.push_back(imagesArray[i]);
m_imageViews.push_back(attachmentsArray[i]);
}
for (auto& subpass : m_subpasses)
{
for (deUint32 i = 0; i < (deUint32)subpass.m_colorAttachments.size(); ++i)
{
if (subpass.m_colorAttachments[i].index != VK_ATTACHMENT_UNUSED)
subpass.m_colorAttachments[i].attachmentInfo.imageView = attachmentsArray[subpass.m_colorAttachments[i].index];
}
if (subpass.m_depthStencilAttachment.attachmentInfo.imageLayout != VK_IMAGE_LAYOUT_UNDEFINED)
{
if (subpass.m_depthStencilAttachment.index != VK_ATTACHMENT_UNUSED)
subpass.m_depthStencilAttachment.attachmentInfo.imageView = attachmentsArray[subpass.m_depthStencilAttachment.index];
}
for (deUint32 i = 0; i < (deUint32)subpass.m_resolveAttachments.size(); ++i)
{
if (subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
subpass.m_resolveAttachments[i].attachmentInfo.imageView = attachmentsArray[subpass.m_resolveAttachments[i].index];
}
}
#endif
}
}
ShaderWrapper::ShaderWrapper ()
: m_vk (DE_NULL)
, m_device (VK_NULL_HANDLE)
, m_binary (DE_NULL)
, m_moduleCreateFlags ((VkShaderModuleCreateFlags)0u)
, m_layout (DE_NULL)
, m_specializationInfo (DE_NULL)
#ifndef CTS_USES_VULKANSC
, m_shaderCreateFlags ((VkShaderCreateFlagsEXT)0u)
, m_binaryDataSize (0u)
#endif
{
}
ShaderWrapper::ShaderWrapper (const DeviceInterface& vk, VkDevice device, const vk::ProgramBinary& binary, const vk::VkShaderModuleCreateFlags createFlags)
: m_vk (&vk)
, m_device (device)
, m_binary (&binary)
, m_moduleCreateFlags (createFlags)
, m_layout (DE_NULL)
, m_specializationInfo(DE_NULL)
#ifndef CTS_USES_VULKANSC
, m_shaderCreateFlags ((VkShaderCreateFlagsEXT)0u)
, m_binaryDataSize (0u)
#endif
{
}
ShaderWrapper::ShaderWrapper (const ShaderWrapper& rhs) noexcept
: m_vk (rhs.m_vk)
, m_device (rhs.m_device)
, m_binary (rhs.m_binary)
, m_moduleCreateFlags (rhs.m_moduleCreateFlags)
, m_layout (rhs.m_layout)
, m_specializationInfo (rhs.m_specializationInfo)
#ifndef CTS_USES_VULKANSC
, m_shaderCreateFlags (rhs.m_shaderCreateFlags)
, m_binaryDataSize (rhs.m_binaryDataSize)
, m_binaryData (rhs.m_binaryData)
#endif
{}
ShaderWrapper& ShaderWrapper::operator= (const ShaderWrapper& rhs) noexcept
{
m_vk = rhs.m_vk;
m_device = rhs.m_device;
m_binary = rhs.m_binary;
m_moduleCreateFlags = rhs.m_moduleCreateFlags;
m_layout = rhs.m_layout;
m_specializationInfo = rhs.m_specializationInfo;
#ifndef CTS_USES_VULKANSC
m_shaderCreateFlags = rhs.m_shaderCreateFlags;
m_binaryDataSize = rhs.m_binaryDataSize;
m_binaryData = rhs.m_binaryData;
#endif
return *this;
}
vk::VkShaderModule ShaderWrapper::getModule (void) const
{
if (!m_module)
{
if (!m_vk)
return DE_NULL;
m_module = createShaderModule(*m_vk, m_device, *m_binary, m_moduleCreateFlags);
}
return *m_module;
}
size_t ShaderWrapper::getCodeSize (void) const
{
return m_binary->getSize();
}
void* ShaderWrapper::getBinary (void) const
{
return (void*)m_binary->getBinary();
}
void ShaderWrapper::createModule (void)
{
if (m_vk)
m_module = createShaderModule(*m_vk, m_device, *m_binary, m_moduleCreateFlags);
}
void ShaderWrapper::setLayoutAndSpecialization (const PipelineLayoutWrapper* layout, const VkSpecializationInfo* specializationInfo)
{
m_layout = layout;
m_specializationInfo = specializationInfo;
}
#ifndef CTS_USES_VULKANSC
void ShaderWrapper::getShaderBinary (void)
{
m_vk->getShaderBinaryDataEXT(m_device, *m_shader, &m_binaryDataSize, DE_NULL);
m_binaryData.resize(m_binaryDataSize);
m_vk->getShaderBinaryDataEXT(m_device, *m_shader, &m_binaryDataSize, m_binaryData.data());
}
#endif
// Structure storing *CreateInfo structures that do not need to exist in memory after pipeline was constructed.
struct GraphicsPipelineWrapper::InternalData
{
const InstanceInterface& vki;
const DeviceInterface& vk;
VkPhysicalDevice physicalDevice;
VkDevice device;
const std::vector<std::string>& deviceExtensions;
const PipelineConstructionType pipelineConstructionType;
const VkPipelineCreateFlags pipelineFlags;
PipelineCreateFlags2 pipelineFlags2;
// attribute used for making sure pipeline is configured in correct order
int setupState;
std::vector<PipelineShaderStageModuleIdPtr> pipelineShaderIdentifiers;
std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStages;
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
VkPipelineRasterizationStateCreateInfo defaultRasterizationState;
VkPipelineViewportStateCreateInfo viewportState;
VkPipelineTessellationStateCreateInfo tessellationState;
VkPipelineFragmentShadingRateStateCreateInfoKHR* pFragmentShadingRateState;
PipelineRenderingCreateInfoWrapper pRenderingState;
RenderingAttachmentLocationInfoWrapper pRenderingAttachmentLocation;
RenderingInputAttachmentIndexInfoWrapper pRenderingInputAttachmentIndex;
const VkPipelineDynamicStateCreateInfo* pDynamicState;
PipelineRepresentativeFragmentTestCreateInfoWrapper pRepresentativeFragmentTestState;
TessellationDomainOriginStatePtr pTessellationDomainOrigin;
deBool useViewportState;
deBool useDefaultRasterizationState;
deBool useDefaultDepthStencilState;
deBool useDefaultColorBlendState;
deBool useDefaultMultisampleState;
deBool useDefaultVertexInputState;
bool failOnCompileWhenLinking;
bool explicitLinkPipelineLayoutSet;
VkGraphicsPipelineCreateInfo monolithicPipelineCreateInfo;
ShaderWrapper vertexShader;
ShaderWrapper tessellationControlShader;
ShaderWrapper tessellationEvaluationShader;
ShaderWrapper geometryShader;
ShaderWrapper fragmentShader;
ShaderWrapper meshShader;
ShaderWrapper taskShader;
bool tessellationShaderFeature;
bool geometryShaderFeature;
bool taskShaderFeature;
bool meshShaderFeature;
// Store all dynamic state that are used with shader objects
std::vector<vk::VkDynamicState> shaderObjectDynamicStates;
#ifndef CTS_USES_VULKANSC
// Store the state that a pipeline would be created with, but shader objects have to set dynamically
struct PipelineCreateState {
std::vector<VkViewport> viewports;
std::vector<VkRect2D> scissors;
float lineWidth = 1.0f;
VkDepthBiasRepresentationEXT depthBiasRepresentation = vk::VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT;
VkBool32 depthBiasExact = VK_FALSE;
float depthBiasConstantFactor = 0.0f;
float depthBiasClamp = 0.0f;
float depthBiasSlopeFactor = 1.0f;
float blendConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
float minDepthBounds = 0.0f;
float maxDepthBounds = 1.0f;
VkStencilOpState stencilFront = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0 };
VkStencilOpState stencilBack = { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0 };
VkCullModeFlags cullMode = VK_CULL_MODE_NONE;
deBool depthTestEnable = VK_FALSE;
deBool depthWriteEnable = VK_FALSE;
VkCompareOp depthCompareOp = VK_COMPARE_OP_NEVER;
deBool depthBoundsTestEnable = VK_FALSE;
VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
deBool stencilTestEnable = VK_FALSE;
std::vector<VkVertexInputAttributeDescription2EXT> attributes;
std::vector<VkVertexInputBindingDescription2EXT> bindings;
deBool depthBiasEnable = VK_FALSE;
VkLogicOp logicOp = VK_LOGIC_OP_CLEAR;
uint32_t patchControlPoints = 1;
deBool primitiveRestartEnable = VK_FALSE;
deBool rasterizerDiscardEnable = VK_FALSE;
deBool alphaToCoverageEnable = VK_FALSE;
deBool alphaToOneEnable = VK_FALSE;
std::vector<VkColorBlendAdvancedEXT> colorBlendAdvanced;
std::vector<VkBool32> colorBlendEnables;
std::vector<VkColorBlendEquationEXT> blendEquations;
std::vector<VkColorComponentFlags> colorWriteMasks;
VkConservativeRasterizationModeEXT conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
VkCoverageModulationModeNV coverageModulationMode = VK_COVERAGE_MODULATION_MODE_NONE_NV;
deBool coverageModulationTableEnable = VK_FALSE;
std::vector<float> coverageModulationTable;
VkCoverageReductionModeNV coverageReductionMode = VK_COVERAGE_REDUCTION_MODE_MERGE_NV;
deBool coverageToColorEnable = VK_FALSE;
deUint32 coverageToColorLocation = 0;
deBool depthClampEnable = VK_FALSE;
deBool depthClipEnable = VK_FALSE;
deBool negativeOneToOne = VK_FALSE;
deUint32 colorWriteEnableAttachmentCount = 0;
std::vector<VkBool32> colorWriteEnables;
float extraPrimitiveOverestimationSize = 0.0f;
VkLineRasterizationModeEXT lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
deBool stippledLineEnable = VK_FALSE;
deUint32 lineStippleFactor = 1;
deUint16 lineStipplePattern = 0x1;
deBool logicOpEnable = VK_FALSE;
VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL;
VkProvokingVertexModeEXT provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkExtent2D fragmentShadingRateSize = { 1u, 1u };
VkFragmentShadingRateCombinerOpKHR combinerOps[2] = { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR };
deUint32 rasterizationStream = 0;
deBool representativeFragmentTestEnable = VK_FALSE;
deBool sampleLocationsEnable = VK_FALSE;
std::vector<VkSampleLocationEXT> pSampleLocations;
VkSampleLocationsInfoEXT sampleLocationsInfo = vk::initVulkanStructure();
std::vector<VkSampleMask> sampleMasks;
deBool shadingRateImageEnable = VK_FALSE;
VkTessellationDomainOrigin domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
std::vector<VkViewportSwizzleNV> viewportSwizzles;
deBool viewportWScalingEnable = VK_FALSE;
deUint32 viewportWScalingCount = 0;
std::vector<VkViewportWScalingNV> viewportWScalings;
VkCoarseSampleOrderTypeNV coarseSampleOrderType = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV;
deUint32 coarseCustomSampleOrderCount = 0;
std::vector<std::vector<VkCoarseSampleLocationNV>> coarseSampleLocations;
std::vector<VkCoarseSampleOrderCustomNV> coarseCustomSampleOrders;
deUint32 shadingRatePaletteCount = 0;
std::vector<std::vector<VkShadingRatePaletteEntryNV>> shadingRatePaletteEntries;
std::vector<VkShadingRatePaletteNV> shadingRatePalettes;
deUint32 exclusiveScissorCount = 0;
std::vector<VkRect2D> exclussiveScissors;
deBool discardRectangleEnable = VK_FALSE;
std::vector<VkRect2D> discardRectangles;
VkDiscardRectangleModeEXT discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
VkImageAspectFlags attachmentFeedbackLoopEnable = VK_IMAGE_ASPECT_NONE;
} pipelineCreateState;
#endif
// initialize with most common values
InternalData(const InstanceInterface& instanceInterface, const DeviceInterface& vkd, VkPhysicalDevice physDevice, VkDevice vkDevice, const std::vector<std::string>& deviceExts, const PipelineConstructionType constructionType, const VkPipelineCreateFlags pipelineCreateFlags)
: vki (instanceInterface)
, vk (vkd)
, physicalDevice (physDevice)
, device (vkDevice)
, deviceExtensions (deviceExts)
, pipelineConstructionType (constructionType)
, pipelineFlags (pipelineCreateFlags)
, pipelineFlags2 (0u)
, setupState (PSS_NONE)
, inputAssemblyState
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineInputAssemblyStateCreateFlags flags
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology
VK_FALSE // VkBool32 primitiveRestartEnable
}
, defaultRasterizationState
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineRasterizationStateCreateFlags flags
VK_FALSE, // VkBool32 depthClampEnable
VK_FALSE, // VkBool32 rasterizerDiscardEnable
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode
VK_CULL_MODE_NONE, // VkCullModeFlags cullMode
VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace
VK_FALSE, // VkBool32 depthBiasEnable
0.0f, // float depthBiasConstantFactor
0.0f, // float depthBiasClamp
0.0f, // float depthBiasSlopeFactor
1.0f // float lineWidth
}
, viewportState
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
1u, // deUint32 viewportCount
DE_NULL, // const VkViewport* pViewports
1u, // deUint32 scissorCount
DE_NULL // const VkRect2D* pScissors
}
, tessellationState
{
VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineTessellationStateCreateFlags flags
3u // deUint32 patchControlPoints
}
, pFragmentShadingRateState (nullptr)
, pDynamicState (DE_NULL)
, pRepresentativeFragmentTestState(nullptr)
, pTessellationDomainOrigin ()
, useViewportState (DE_TRUE)
, useDefaultRasterizationState (DE_FALSE)
, useDefaultDepthStencilState (DE_FALSE)
, useDefaultColorBlendState (DE_FALSE)
, useDefaultMultisampleState (DE_FALSE)
, useDefaultVertexInputState (DE_TRUE)
, failOnCompileWhenLinking (false)
, explicitLinkPipelineLayoutSet (false)
, tessellationShaderFeature (false)
, geometryShaderFeature (false)
, taskShaderFeature (false)
, meshShaderFeature (false)
{
monolithicPipelineCreateInfo = initVulkanStructure();
}
bool extensionEnabled (const std::string& ext) const
{
return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
}
};
GraphicsPipelineWrapper::GraphicsPipelineWrapper(const InstanceInterface& vki,
const DeviceInterface& vk,
VkPhysicalDevice physicalDevice,
VkDevice device,
const std::vector<std::string>& deviceExtensions,
const PipelineConstructionType pipelineConstructionType,
const VkPipelineCreateFlags flags)
: m_internalData (new InternalData(vki, vk, physicalDevice, device, deviceExtensions, pipelineConstructionType, flags))
{
}
GraphicsPipelineWrapper::GraphicsPipelineWrapper(GraphicsPipelineWrapper&& pw) noexcept
: m_pipelineFinal (pw.m_pipelineFinal)
, m_internalData (pw.m_internalData)
{
std::move(pw.m_pipelineParts, pw.m_pipelineParts + de::arrayLength(pw.m_pipelineParts), m_pipelineParts);
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setMonolithicPipelineLayout(const PipelineLayoutWrapper& layout)
{
// make sure pipeline was not already built
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
m_internalData->monolithicPipelineCreateInfo.layout = *layout;
m_internalData->explicitLinkPipelineLayoutSet = true;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDynamicState(const VkPipelineDynamicStateCreateInfo* dynamicState)
{
// make sure states are not yet setup - all pipeline states must know about dynamic state
DE_ASSERT(m_internalData && m_internalData->setupState == PSS_NONE);
m_internalData->pDynamicState = dynamicState;
m_internalData->monolithicPipelineCreateInfo.pDynamicState = dynamicState;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setRepresentativeFragmentTestState(PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState)
{
// Representative fragment test state is needed by the fragment shader state.
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
m_internalData->pRepresentativeFragmentTestState = representativeFragmentTestState;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2)
{
// make sure states are not yet setup - all pipeline states must know about createFlags2
DE_ASSERT(m_internalData && m_internalData->setupState == PSS_NONE);
m_internalData->pipelineFlags2 = pipelineFlags2;
return *this;
}
std::vector<VkDynamicState> getDynamicStates(const VkPipelineDynamicStateCreateInfo* dynamicStateInfo, uint32_t setupState)
{
static const std::set<VkDynamicState> vertexInputStates {
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
};
static const std::set<VkDynamicState> preRastStates {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
VK_DYNAMIC_STATE_LINE_WIDTH,
VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT,
VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
VK_DYNAMIC_STATE_DEPTH_BIAS,
VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
#ifndef CTS_USES_VULKANSC
VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT,
VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT,
VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT,
VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV,
VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV,
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV,
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
#endif
};
static const std::set<VkDynamicState> fragShaderStates {
VK_DYNAMIC_STATE_DEPTH_BOUNDS,
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_STENCIL_OP_EXT,
VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
// Needs MSAA info here as well as fragment output state
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
#ifndef CTS_USES_VULKANSC
VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
#endif
};
static const std::set<VkDynamicState> fragOutputStates {
VK_DYNAMIC_STATE_LOGIC_OP_EXT,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
#ifndef CTS_USES_VULKANSC
VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT,
#endif
};
const std::set<VkDynamicState> dynamicStates (dynamicStateInfo->pDynamicStates,
dynamicStateInfo->pDynamicStates + dynamicStateInfo->dynamicStateCount);
// Verify all passed states are contained in at least one of the vectors above, so they won't get lost.
for (const auto dynState : dynamicStates)
{
DE_UNREF(dynState); // For release builds.
DE_ASSERT( de::contains(vertexInputStates.begin(), vertexInputStates.end(), dynState)
|| de::contains(preRastStates.begin(), preRastStates.end(), dynState)
|| de::contains(fragShaderStates.begin(), fragShaderStates.end(), dynState)
|| de::contains(fragOutputStates.begin(), fragOutputStates.end(), dynState));
}
std::set<VkDynamicState> intersectedStates;
if (setupState & PSS_VERTEX_INPUT_INTERFACE)
std::set_intersection(vertexInputStates.begin(), vertexInputStates.end(), dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
if (setupState & PSS_PRE_RASTERIZATION_SHADERS)
std::set_intersection(preRastStates.begin(), preRastStates.end(), dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
if (setupState & PSS_FRAGMENT_SHADER)
std::set_intersection(fragShaderStates.begin(), fragShaderStates.end(), dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
if (setupState & PSS_FRAGMENT_OUTPUT_INTERFACE)
std::set_intersection(fragOutputStates.begin(), fragOutputStates.end(), dynamicStates.begin(), dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
const std::vector<VkDynamicState> returnedStates (begin(intersectedStates), end(intersectedStates));
return returnedStates;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultTopology(const VkPrimitiveTopology topology)
{
// topology is needed by vertex input state, make sure vertex input state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
m_internalData->inputAssemblyState.topology = topology;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultPatchControlPoints(const deUint32 patchControlPoints)
{
// patchControlPoints are needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->tessellationState.patchControlPoints = patchControlPoints;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultTessellationDomainOrigin (const VkTessellationDomainOrigin domainOrigin, bool forceExtStruct)
{
// Tessellation domain origin is needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
// We need the extension structure when:
// - We want to force it.
// - The domain origin is not the default value.
// - We have already hooked the extension structure.
if (forceExtStruct || domainOrigin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT || m_internalData->pTessellationDomainOrigin)
{
if (!m_internalData->pTessellationDomainOrigin)
{
m_internalData->pTessellationDomainOrigin.reset(new VkPipelineTessellationDomainOriginStateCreateInfo(initVulkanStructure()));
m_internalData->tessellationState.pNext = m_internalData->pTessellationDomainOrigin.get();
}
m_internalData->pTessellationDomainOrigin->domainOrigin = domainOrigin;
}
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultRasterizerDiscardEnable(const deBool rasterizerDiscardEnable)
{
// rasterizerDiscardEnable is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->defaultRasterizationState.rasterizerDiscardEnable = rasterizerDiscardEnable;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultRasterizationState()
{
// RasterizationState is used in pre-rasterization shader state, make sure this state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->useDefaultRasterizationState = DE_TRUE;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultDepthStencilState()
{
// DepthStencilState is used in fragment shader state, make sure fragment shader state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
m_internalData->useDefaultDepthStencilState = DE_TRUE;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultColorBlendState()
{
// ColorBlendState is used in fragment shader state, make sure fragment shader state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
m_internalData->useDefaultColorBlendState = DE_TRUE;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultMultisampleState()
{
// MultisampleState is used in fragment shader state, make sure fragment shader state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
m_internalData->useDefaultMultisampleState = DE_TRUE;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultVertexInputState(const deBool useDefaultVertexInputState)
{
// Make sure vertex input state was not setup yet.
DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
m_internalData->useDefaultVertexInputState = useDefaultVertexInputState;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultViewportsCount(deUint32 viewportCount)
{
// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->viewportState.viewportCount = viewportCount;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setDefaultScissorsCount(deUint32 scissorCount)
{
// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->viewportState.scissorCount = scissorCount;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setViewportStatePnext(const void* pNext)
{
// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->viewportState.pNext = pNext;
return *this;
}
#ifndef CTS_USES_VULKANSC
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setRenderingColorAttachmentsInfo(PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo)
{
/* When both graphics pipeline library and dynamic rendering enabled, we just need only viewMask of VkPipelineRenderingCreateInfo
* on non-fragment stages. But we need the rest info for setting up fragment output states.
* This method provides a way to verify this condition.
*/
if (!m_internalData->pRenderingState.ptr || !isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
return *this;
DE_ASSERT(m_internalData && (m_internalData->setupState > PSS_VERTEX_INPUT_INTERFACE) &&
(m_internalData->setupState < PSS_FRAGMENT_OUTPUT_INTERFACE) &&
(m_internalData->pRenderingState.ptr->viewMask == pipelineRenderingCreateInfo.ptr->viewMask));
m_internalData->pRenderingState.ptr = pipelineRenderingCreateInfo.ptr;
return *this;
}
#endif
GraphicsPipelineWrapper& GraphicsPipelineWrapper::disableViewportState(const bool disable)
{
// ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
m_internalData->useViewportState = !disable;
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupVertexInputState(const VkPipelineVertexInputStateCreateInfo* vertexInputState,
const VkPipelineInputAssemblyStateCreateInfo* inputAssemblyState,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
const bool useNullPtrs)
{
// make sure pipeline was not already build
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set first
DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
DE_UNREF(partPipelineCache);
DE_UNREF(partCreationFeedback);
m_internalData->setupState = PSS_VERTEX_INPUT_INTERFACE;
const auto pVertexInputState = ((vertexInputState || useNullPtrs || !m_internalData->useDefaultVertexInputState)
? vertexInputState
: &defaultVertexInputState);
const auto pInputAssemblyState = ((inputAssemblyState || useNullPtrs) ? inputAssemblyState : &m_internalData->inputAssemblyState);
if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
m_internalData->monolithicPipelineCreateInfo.pVertexInputState = pVertexInputState;
m_internalData->monolithicPipelineCreateInfo.pInputAssemblyState = pInputAssemblyState;
}
#ifndef CTS_USES_VULKANSC
// note we could just use else to if statement above but sinc
// this section is cut out for Vulkan SC its cleaner with separate if
if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
void* firstStructInChain = reinterpret_cast<void*>(&libraryCreateInfo);
addToChain(&firstStructInChain, partCreationFeedback.ptr);
VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
std::vector<VkDynamicState> states;
if(m_internalData->pDynamicState)
{
states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
pickedDynamicStateInfo.pDynamicStates = states.data();
pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
}
VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
pipelinePartCreateInfo.pNext = firstStructInChain;
pipelinePartCreateInfo.flags = (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
pipelinePartCreateInfo.pVertexInputState = pVertexInputState;
pipelinePartCreateInfo.pInputAssemblyState = pInputAssemblyState;
pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pipelinePartCreateInfo.flags = 0u;
}
m_pipelineParts[0] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
}
#endif // CTS_USES_VULKANSC
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState(const std::vector<VkViewport>& viewports,
const std::vector<VkRect2D>& scissors,
const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper vertexShader,
const VkPipelineRasterizationStateCreateInfo* rasterizationState,
const ShaderWrapper tessellationControlShader,
const ShaderWrapper tessellationEvalShader,
const ShaderWrapper geometryShader,
const VkSpecializationInfo *specializationInfo,
VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState,
PipelineRenderingCreateInfoWrapper rendering,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
{
return setupPreRasterizationShaderState2(viewports,
scissors,
layout,
renderPass,
subpass,
vertexShader,
rasterizationState,
tessellationControlShader,
tessellationEvalShader,
geometryShader,
// Reuse the same specialization info for all stages.
specializationInfo,
specializationInfo,
specializationInfo,
specializationInfo,
fragmentShadingRateState,
rendering,
partPipelineCache,
partCreationFeedback);
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState2(const std::vector<VkViewport>& viewports,
const std::vector<VkRect2D>& scissors,
const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper vertexShader,
const VkPipelineRasterizationStateCreateInfo* rasterizationState,
const ShaderWrapper tessellationControlShader,
const ShaderWrapper tessellationEvalShader,
const ShaderWrapper geometryShader,
const VkSpecializationInfo* vertSpecializationInfo,
const VkSpecializationInfo* tescSpecializationInfo,
const VkSpecializationInfo* teseSpecializationInfo,
const VkSpecializationInfo* geomSpecializationInfo,
VkPipelineFragmentShadingRateStateCreateInfoKHR*fragmentShadingRateState,
PipelineRenderingCreateInfoWrapper rendering,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
{
return setupPreRasterizationShaderState3(viewports,
scissors,
layout,
renderPass,
subpass,
vertexShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
rasterizationState,
tessellationControlShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
tessellationEvalShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
geometryShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
vertSpecializationInfo,
tescSpecializationInfo,
teseSpecializationInfo,
geomSpecializationInfo,
fragmentShadingRateState,
rendering,
partPipelineCache,
partCreationFeedback);
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationShaderState3(const std::vector<VkViewport>& viewports,
const std::vector<VkRect2D>& scissors,
const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper vertexShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId,
const VkPipelineRasterizationStateCreateInfo* rasterizationState,
const ShaderWrapper tessellationControlShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId,
const ShaderWrapper tessellationEvalShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId,
const ShaderWrapper geometryShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId,
const VkSpecializationInfo* vertSpecializationInfo,
const VkSpecializationInfo* tescSpecializationInfo,
const VkSpecializationInfo* teseSpecializationInfo,
const VkSpecializationInfo* geomSpecializationInfo,
VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState,
PipelineRenderingCreateInfoWrapper rendering,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
{
// make sure pipeline was not already build
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set second
DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_VERTEX_INPUT_INTERFACE));
// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
DE_UNREF(partPipelineCache);
DE_UNREF(partCreationFeedback);
DE_UNREF(vertShaderModuleId);
DE_UNREF(tescShaderModuleId);
DE_UNREF(teseShaderModuleId);
DE_UNREF(geomShaderModuleId);
m_internalData->setupState |= PSS_PRE_RASTERIZATION_SHADERS;
m_internalData->pFragmentShadingRateState = fragmentShadingRateState;
m_internalData->pRenderingState.ptr = rendering.ptr;
const bool hasTesc = (tessellationControlShader.isSet() || tescShaderModuleId.ptr);
const bool hasTese = (tessellationEvalShader.isSet() || teseShaderModuleId.ptr);
const bool hasGeom = (geometryShader.isSet() || geomShaderModuleId.ptr);
const auto pRasterizationState = rasterizationState ? rasterizationState
: (m_internalData->useDefaultRasterizationState ? &m_internalData->defaultRasterizationState : DE_NULL);
const bool forceNullTessState = (m_internalData->tessellationState.patchControlPoints == std::numeric_limits<uint32_t>::max());
const auto pTessellationState = ((hasTesc || hasTese) && !forceNullTessState) ? &m_internalData->tessellationState : nullptr;
const auto pViewportState = m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
VkPipelineCreateFlags shaderModuleIdFlags = 0u;
m_internalData->vertexShader = vertexShader;
m_internalData->vertexShader.setLayoutAndSpecialization(&layout, vertSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->vertexShader.createModule();
// reserve space for all stages including fragment - this is needed when we create monolithic pipeline
m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(2u + hasTesc + hasTese + hasGeom,
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
0u, // VkPipelineShaderStageCreateFlags flags
VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage
m_internalData->vertexShader.getModule(), // VkShaderModule module
"main", // const char* pName
vertSpecializationInfo // const VkSpecializationInfo* pSpecializationInfo
});
#ifndef CTS_USES_VULKANSC
if (vertShaderModuleId.ptr)
{
m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(vertShaderModuleId.ptr));
m_internalData->pipelineShaderStages[0].pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
if (!vertexShader.isSet())
shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
#endif // CTS_USES_VULKANSC
std::vector<VkPipelineShaderStageCreateInfo>::iterator currStage = m_internalData->pipelineShaderStages.begin() + 1;
if (hasTesc)
{
m_internalData->tessellationControlShader = tessellationControlShader;
m_internalData->tessellationControlShader.setLayoutAndSpecialization(&layout, tescSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->tessellationControlShader.createModule();
currStage->stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
currStage->module = m_internalData->tessellationControlShader.getModule();
currStage->pSpecializationInfo = tescSpecializationInfo;
#ifndef CTS_USES_VULKANSC
if (tescShaderModuleId.ptr)
{
m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(tescShaderModuleId.ptr));
currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
if (!tessellationControlShader.isSet())
shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
#endif // CTS_USES_VULKANSC
++currStage;
}
if (hasTese)
{
m_internalData->tessellationEvaluationShader = tessellationEvalShader;
m_internalData->tessellationEvaluationShader.setLayoutAndSpecialization(&layout, teseSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->tessellationEvaluationShader.createModule();
currStage->stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
currStage->module = m_internalData->tessellationEvaluationShader.getModule();
currStage->pSpecializationInfo = teseSpecializationInfo;
#ifndef CTS_USES_VULKANSC
if (teseShaderModuleId.ptr)
{
m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(teseShaderModuleId.ptr));
currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
if (!tessellationEvalShader.isSet())
shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
#endif // CTS_USES_VULKANSC
++currStage;
}
if (hasGeom)
{
m_internalData->geometryShader = geometryShader;
m_internalData->geometryShader.setLayoutAndSpecialization(&layout, geomSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->geometryShader.createModule();
currStage->stage = VK_SHADER_STAGE_GEOMETRY_BIT;
currStage->module = m_internalData->geometryShader.getModule();
currStage->pSpecializationInfo = geomSpecializationInfo;
#ifndef CTS_USES_VULKANSC
if (geomShaderModuleId.ptr)
{
m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(geomShaderModuleId.ptr));
currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
if (!geometryShader.isSet())
shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
#endif // CTS_USES_VULKANSC
}
if (pViewportState)
{
if (!viewports.empty())
{
pViewportState->viewportCount = (deUint32)viewports.size();
pViewportState->pViewports = &viewports[0];
}
if (!scissors.empty())
{
pViewportState->scissorCount = (deUint32)scissors.size();
pViewportState->pScissors = &scissors[0];
}
}
// if pipeline layout was not specified with setupMonolithicPipelineLayout
// then use layout from setupPreRasterizationShaderState for link pipeline
if (!m_internalData->explicitLinkPipelineLayoutSet)
m_internalData->monolithicPipelineCreateInfo.layout = *layout;
if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
m_internalData->monolithicPipelineCreateInfo.renderPass = renderPass;
m_internalData->monolithicPipelineCreateInfo.subpass = subpass;
m_internalData->monolithicPipelineCreateInfo.pRasterizationState = pRasterizationState;
m_internalData->monolithicPipelineCreateInfo.pViewportState = pViewportState;
m_internalData->monolithicPipelineCreateInfo.stageCount = 1u + hasTesc + hasTese + hasGeom;
m_internalData->monolithicPipelineCreateInfo.pStages = m_internalData->pipelineShaderStages.data();
m_internalData->monolithicPipelineCreateInfo.pTessellationState = pTessellationState;
m_internalData->monolithicPipelineCreateInfo.flags |= shaderModuleIdFlags;
}
#ifndef CTS_USES_VULKANSC
// note we could just use else to if statement above but sinc
// this section is cut out for Vulkan SC its cleaner with separate if
if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
void* firstStructInChain = reinterpret_cast<void*>(&libraryCreateInfo);
addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
addToChain(&firstStructInChain, partCreationFeedback.ptr);
VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
std::vector<VkDynamicState> states;
if(m_internalData->pDynamicState)
{
states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
pickedDynamicStateInfo.pDynamicStates = states.data();
pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
}
VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
pipelinePartCreateInfo.pNext = firstStructInChain;
pipelinePartCreateInfo.flags = (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
pipelinePartCreateInfo.layout = *layout;
pipelinePartCreateInfo.renderPass = renderPass;
pipelinePartCreateInfo.subpass = subpass;
pipelinePartCreateInfo.pRasterizationState = pRasterizationState;
pipelinePartCreateInfo.pViewportState = pViewportState;
pipelinePartCreateInfo.stageCount = 1u + hasTesc + hasTese + hasGeom;
pipelinePartCreateInfo.pStages = m_internalData->pipelineShaderStages.data();
pipelinePartCreateInfo.pTessellationState = pTessellationState;
pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
m_internalData->failOnCompileWhenLinking = true;
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pipelinePartCreateInfo.flags = 0u;
}
m_pipelineParts[1] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
}
#endif // CTS_USES_VULKANSC
return *this;
}
#ifndef CTS_USES_VULKANSC
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupPreRasterizationMeshShaderState(const std::vector<VkViewport>& viewports,
const std::vector<VkRect2D>& scissors,
const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper taskShader,
const ShaderWrapper meshShader,
const VkPipelineRasterizationStateCreateInfo* rasterizationState,
const VkSpecializationInfo *taskSpecializationInfo,
const VkSpecializationInfo *meshSpecializationInfo,
VkPipelineFragmentShadingRateStateCreateInfoKHR* fragmentShadingRateState,
PipelineRenderingCreateInfoWrapper rendering,
const VkPipelineCache partPipelineCache,
VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback)
{
// Make sure pipeline was not already built.
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// Make sure states are set in order - this state needs to be set first or second.
DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
// The vertex input interface is not needed for mesh shading pipelines, so we're going to mark it as ready here.
m_internalData->setupState |= (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS);
m_internalData->pFragmentShadingRateState = fragmentShadingRateState;
m_internalData->pRenderingState = rendering;
const bool hasTask = (taskShader.isSet());
const auto taskShaderCount = static_cast<uint32_t>(hasTask);
const auto pRasterizationState = rasterizationState
? rasterizationState
: (m_internalData->useDefaultRasterizationState
? &m_internalData->defaultRasterizationState
: nullptr);
const auto pTessellationState = nullptr;
const auto pViewportState = m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
// Reserve space for all stages including fragment. This is needed when we create monolithic pipeline.
m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(2u + taskShaderCount,
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
0u, // VkPipelineShaderStageCreateFlags flags
VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage
DE_NULL, // VkShaderModule module
"main", // const char* pName
nullptr, // const VkSpecializationInfo* pSpecializationInfo
});
// Mesh shader.
auto currStage = m_internalData->pipelineShaderStages.begin();
{
m_internalData->meshShader = meshShader;
m_internalData->meshShader.setLayoutAndSpecialization(&layout, meshSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->meshShader.createModule();
auto& stageInfo = *currStage;
stageInfo.stage = VK_SHADER_STAGE_MESH_BIT_EXT;
stageInfo.module = m_internalData->meshShader.getModule();
stageInfo.pSpecializationInfo = meshSpecializationInfo;
++currStage;
}
if (hasTask)
{
m_internalData->taskShader = taskShader;
m_internalData->taskShader.setLayoutAndSpecialization(&layout, taskSpecializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->taskShader.createModule();
auto& stageInfo = *currStage;
stageInfo.stage = VK_SHADER_STAGE_TASK_BIT_EXT;
stageInfo.module = m_internalData->taskShader.getModule();
stageInfo.pSpecializationInfo = taskSpecializationInfo;
++currStage;
}
if (pViewportState)
{
if (!viewports.empty())
{
pViewportState->viewportCount = (deUint32)viewports.size();
pViewportState->pViewports = &viewports[0];
}
if (!scissors.empty())
{
pViewportState->scissorCount = (deUint32)scissors.size();
pViewportState->pScissors = &scissors[0];
}
}
// if pipeline layout was not specified with setupMonolithicPipelineLayout
// then use layout from setupPreRasterizationMeshShaderState for link pipeline
if (!m_internalData->explicitLinkPipelineLayoutSet)
m_internalData->monolithicPipelineCreateInfo.layout = *layout;
if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
m_internalData->monolithicPipelineCreateInfo.renderPass = renderPass;
m_internalData->monolithicPipelineCreateInfo.subpass = subpass;
m_internalData->monolithicPipelineCreateInfo.pRasterizationState = pRasterizationState;
m_internalData->monolithicPipelineCreateInfo.pViewportState = pViewportState;
m_internalData->monolithicPipelineCreateInfo.stageCount = 1u + taskShaderCount;
m_internalData->monolithicPipelineCreateInfo.pStages = m_internalData->pipelineShaderStages.data();
m_internalData->monolithicPipelineCreateInfo.pTessellationState = pTessellationState;
}
else
{
auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
void* firstStructInChain = reinterpret_cast<void*>(&libraryCreateInfo);
addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
addToChain(&firstStructInChain, partCreationFeedback);
VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
std::vector<VkDynamicState> states;
if(m_internalData->pDynamicState)
{
states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
pickedDynamicStateInfo.pDynamicStates = states.data();
pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
}
VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
pipelinePartCreateInfo.pNext = firstStructInChain;
pipelinePartCreateInfo.flags = m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
pipelinePartCreateInfo.layout = *layout;
pipelinePartCreateInfo.renderPass = renderPass;
pipelinePartCreateInfo.subpass = subpass;
pipelinePartCreateInfo.pRasterizationState = pRasterizationState;
pipelinePartCreateInfo.pViewportState = pViewportState;
pipelinePartCreateInfo.stageCount = 1u + taskShaderCount;
pipelinePartCreateInfo.pStages = m_internalData->pipelineShaderStages.data();
pipelinePartCreateInfo.pTessellationState = pTessellationState;
pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pipelinePartCreateInfo.flags = 0u;
}
m_pipelineParts[1] = createGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
}
return *this;
}
#endif // CTS_USES_VULKANSC
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentShaderState(const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper fragmentShader,
const VkPipelineDepthStencilStateCreateInfo* depthStencilState,
const VkPipelineMultisampleStateCreateInfo* multisampleState,
const VkSpecializationInfo* specializationInfo,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)
{
return setupFragmentShaderState2(layout,
renderPass,
subpass,
fragmentShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
depthStencilState,
multisampleState,
specializationInfo,
partPipelineCache,
partCreationFeedback,
renderingInputAttachmentIndexInfo);
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentShaderState2(const PipelineLayoutWrapper& layout,
const VkRenderPass renderPass,
const deUint32 subpass,
const ShaderWrapper fragmentShader,
PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId,
const VkPipelineDepthStencilStateCreateInfo* depthStencilState,
const VkPipelineMultisampleStateCreateInfo* multisampleState,
const VkSpecializationInfo* specializationInfo,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)
{
// make sure pipeline was not already build
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set third
DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS)));
// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
DE_UNREF(layout);
DE_UNREF(renderPass);
DE_UNREF(subpass);
DE_UNREF(partPipelineCache);
DE_UNREF(partCreationFeedback);
DE_UNREF(fragmentShaderModuleId);
m_internalData->setupState |= PSS_FRAGMENT_SHADER;
m_internalData->pRenderingInputAttachmentIndex.ptr = renderingInputAttachmentIndexInfo.ptr;
const auto pDepthStencilState = depthStencilState ? depthStencilState
: (m_internalData->useDefaultDepthStencilState ? &defaultDepthStencilState : DE_NULL);
const auto pMultisampleState = multisampleState ? multisampleState
: (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
const bool hasFrag = (fragmentShader.isSet() || fragmentShaderModuleId.ptr);
VkPipelineCreateFlags shaderModuleIdFlags = 0u;
deUint32 stageIndex = 1;
if (hasFrag)
{
// find free space for fragment shader
for (; stageIndex < 5; ++stageIndex)
{
if (m_internalData->pipelineShaderStages[stageIndex].stage == VK_SHADER_STAGE_VERTEX_BIT)
{
m_internalData->fragmentShader = fragmentShader;
m_internalData->fragmentShader.setLayoutAndSpecialization(&layout, specializationInfo);
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
m_internalData->fragmentShader.createModule();
m_internalData->pipelineShaderStages[stageIndex].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
m_internalData->pipelineShaderStages[stageIndex].module = m_internalData->fragmentShader.getModule();
m_internalData->pipelineShaderStages[stageIndex].pSpecializationInfo = specializationInfo;
#ifndef CTS_USES_VULKANSC
if (fragmentShaderModuleId.ptr)
{
m_internalData->pipelineShaderIdentifiers.emplace_back(new PipelineShaderStageModuleIdentifierCreateInfoWrapper(fragmentShaderModuleId.ptr));
m_internalData->pipelineShaderStages[stageIndex].pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
if (!fragmentShader.isSet())
shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
#endif // CTS_USES_VULKANSC
break;
}
}
}
if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
m_internalData->monolithicPipelineCreateInfo.pDepthStencilState = pDepthStencilState;
m_internalData->monolithicPipelineCreateInfo.pMultisampleState = pMultisampleState;
m_internalData->monolithicPipelineCreateInfo.stageCount += (hasFrag ? 1u : 0u);
m_internalData->monolithicPipelineCreateInfo.flags |= shaderModuleIdFlags;
}
#ifndef CTS_USES_VULKANSC
// note we could just use else to if statement above but sinc
// this section is cut out for Vulkan SC its cleaner with separate if
if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
void* firstStructInChain = reinterpret_cast<void*>(&libraryCreateInfo);
addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
addToChain(&firstStructInChain, m_internalData->pRenderingInputAttachmentIndex.ptr);
addToChain(&firstStructInChain, partCreationFeedback.ptr);
addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
std::vector<VkDynamicState> states;
if(m_internalData->pDynamicState)
{
states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
pickedDynamicStateInfo.pDynamicStates = states.data();
pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
}
VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
pipelinePartCreateInfo.pNext = firstStructInChain;
pipelinePartCreateInfo.flags = (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
pipelinePartCreateInfo.layout = *layout;
pipelinePartCreateInfo.renderPass = renderPass;
pipelinePartCreateInfo.subpass = subpass;
pipelinePartCreateInfo.pDepthStencilState = pDepthStencilState;
pipelinePartCreateInfo.pMultisampleState = pMultisampleState;
pipelinePartCreateInfo.stageCount = hasFrag;
pipelinePartCreateInfo.pStages = hasFrag ? &m_internalData->pipelineShaderStages[stageIndex] : DE_NULL;
pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
m_internalData->failOnCompileWhenLinking = true;
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pipelinePartCreateInfo.flags = 0u;
}
m_pipelineParts[2] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
}
#endif // CTS_USES_VULKANSC
return *this;
}
GraphicsPipelineWrapper& GraphicsPipelineWrapper::setupFragmentOutputState(const VkRenderPass renderPass,
const deUint32 subpass,
const VkPipelineColorBlendStateCreateInfo* colorBlendState,
const VkPipelineMultisampleStateCreateInfo* multisampleState,
const VkPipelineCache partPipelineCache,
PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo)
{
// make sure pipeline was not already build
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set last
DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS | PSS_FRAGMENT_SHADER)));
m_internalData->setupState |= PSS_FRAGMENT_OUTPUT_INTERFACE;
m_internalData->pRenderingAttachmentLocation.ptr = renderingAttachmentLocationInfo.ptr;
// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
DE_UNREF(renderPass);
DE_UNREF(subpass);
DE_UNREF(partPipelineCache);
DE_UNREF(partCreationFeedback);
void* firstStructInChain = DE_NULL;
addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
#ifndef CTS_USES_VULKANSC
addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
#endif // CTS_USES_VULKANSC
const auto pColorBlendState = colorBlendState ? colorBlendState
: (m_internalData->useDefaultColorBlendState ? &defaultColorBlendState : DE_NULL);
const auto pMultisampleState = multisampleState ? multisampleState
: (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
m_internalData->monolithicPipelineCreateInfo.pNext = firstStructInChain;
m_internalData->monolithicPipelineCreateInfo.flags |= m_internalData->pipelineFlags;
m_internalData->monolithicPipelineCreateInfo.pColorBlendState = pColorBlendState;
m_internalData->monolithicPipelineCreateInfo.pMultisampleState = pMultisampleState;
}
#ifndef CTS_USES_VULKANSC
// note we could just use else to if statement above but sinc
// this section is cut out for Vulkan SC its cleaner with separate if
if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
auto libraryCreateInfo = makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
addToChain(&firstStructInChain, &libraryCreateInfo);
addToChain(&firstStructInChain, partCreationFeedback.ptr);
addToChain(&firstStructInChain, m_internalData->pRenderingAttachmentLocation.ptr);
VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
std::vector<VkDynamicState> states;
if(m_internalData->pDynamicState)
{
states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
pickedDynamicStateInfo.pDynamicStates = states.data();
pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
}
VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
pipelinePartCreateInfo.pNext = firstStructInChain;
pipelinePartCreateInfo.flags = (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
pipelinePartCreateInfo.renderPass = renderPass;
pipelinePartCreateInfo.subpass = subpass;
pipelinePartCreateInfo.pColorBlendState = pColorBlendState;
pipelinePartCreateInfo.pMultisampleState = pMultisampleState;
pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pipelinePartCreateInfo.flags = 0u;
}
m_pipelineParts[3] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache, &pipelinePartCreateInfo);
}
#endif // CTS_USES_VULKANSC
return *this;
}
#ifndef CTS_USES_VULKANSC
vk::VkShaderStageFlags GraphicsPipelineWrapper::getNextStages (vk::VkShaderStageFlagBits shaderStage, bool tessellationShaders, bool geometryShaders, bool link)
{
if (link)
{
if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
{
if (m_internalData->tessellationControlShader.isSet())
return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
if (m_internalData->geometryShader.isSet())
return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
if (m_internalData->fragmentShader.isSet())
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
{
if (m_internalData->geometryShader.isSet())
return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
if (m_internalData->fragmentShader.isSet())
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
{
if (m_internalData->fragmentShader.isSet())
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
if (shaderStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
{
if (m_internalData->meshShader.isSet())
return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
if (m_internalData->fragmentShader.isSet())
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
if (shaderStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
{
if (m_internalData->fragmentShader.isSet())
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
}
else
{
if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
{
VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
if (tessellationShaders)
flags |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
if (geometryShaders)
flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
return flags;
}
else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
{
return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
}
else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
{
VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
if (geometryShaders)
flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
return flags;
}
else if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
{
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
else if (shaderStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
{
return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
}
else if (shaderStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
{
return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
}
}
return 0;
}
vk::VkShaderCreateInfoEXT GraphicsPipelineWrapper::makeShaderCreateInfo (VkShaderStageFlagBits stage, ShaderWrapper& shader, bool link, bool binary, ShaderWrapper& other)
{
if (binary)
shader.getShaderBinary();
vk::VkShaderCreateInfoEXT shaderCreateInfo = vk::initVulkanStructure();
shaderCreateInfo.flags = link ? (vk::VkShaderCreateFlagsEXT)vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT : (vk::VkShaderCreateFlagsEXT)0u;
shaderCreateInfo.stage = stage;
shaderCreateInfo.nextStage = getNextStages(stage, m_internalData->tessellationShaderFeature, m_internalData->geometryShaderFeature, link);
if (binary)
{
shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
shaderCreateInfo.codeSize = shader.getShaderBinaryDataSize();
shaderCreateInfo.pCode = shader.getShaderBinaryData();
}
else
{
shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_SPIRV_EXT;
shaderCreateInfo.codeSize = shader.getCodeSize();
shaderCreateInfo.pCode = shader.getBinary();
}
shaderCreateInfo.pName = "main";
if (shader.getPipelineLayout() != DE_NULL)
{
shaderCreateInfo.setLayoutCount = shader.getPipelineLayout()->getSetLayoutCount();
shaderCreateInfo.pSetLayouts = shader.getPipelineLayout()->getSetLayouts();
shaderCreateInfo.pushConstantRangeCount = shader.getPipelineLayout()->getPushConstantRangeCount();
shaderCreateInfo.pPushConstantRanges = shader.getPipelineLayout()->getPushConstantRanges();
}
// Pipeline layouts and push constant ranges must match between shaders that are used together
if (other.isSet() && shaderCreateInfo.setLayoutCount == 0)
{
shaderCreateInfo.setLayoutCount = other.getPipelineLayout()->getSetLayoutCount();
shaderCreateInfo.pSetLayouts = other.getPipelineLayout()->getSetLayouts();
}
if (other.isSet() && shaderCreateInfo.pushConstantRangeCount == 0)
{
shaderCreateInfo.pushConstantRangeCount = other.getPipelineLayout()->getPushConstantRangeCount();
shaderCreateInfo.pPushConstantRanges = other.getPipelineLayout()->getPushConstantRanges();
}
shaderCreateInfo.pSpecializationInfo = shader.getSpecializationInfo();
return shaderCreateInfo;
}
void GraphicsPipelineWrapper::createShaders (bool linked, bool binary)
{
std::vector<vk::VkShaderCreateInfoEXT> createInfos;
if (m_internalData->vertexShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, m_internalData->vertexShader, linked, binary, m_internalData->fragmentShader));
if (m_internalData->tessellationControlShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_internalData->tessellationControlShader, linked, binary, m_internalData->fragmentShader));
if (m_internalData->tessellationEvaluationShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_internalData->tessellationEvaluationShader, linked, binary, m_internalData->fragmentShader));
if (m_internalData->geometryShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_internalData->geometryShader, linked, binary, m_internalData->fragmentShader));
if (m_internalData->fragmentShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, m_internalData->fragmentShader, linked, binary, m_internalData->vertexShader));
if (m_internalData->taskShader.isSet())
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, m_internalData->taskShader, linked, binary, m_internalData->fragmentShader));
if (m_internalData->meshShader.isSet())
{
createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, m_internalData->meshShader, linked, binary, m_internalData->fragmentShader));
if (!m_internalData->taskShader.isSet())
createInfos.back().flags |= vk::VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT;
}
std::vector<VkShaderEXT> shaders(createInfos.size());
m_internalData->vk.createShadersEXT(m_internalData->device, (deUint32)createInfos.size(), createInfos.data(), DE_NULL, shaders.data());
deUint32 shaderIndex = 0;
if (m_internalData->vertexShader.isSet())
m_internalData->vertexShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->tessellationControlShader.isSet())
m_internalData->tessellationControlShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->tessellationEvaluationShader.isSet())
m_internalData->tessellationEvaluationShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->geometryShader.isSet())
m_internalData->geometryShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->fragmentShader.isSet())
m_internalData->fragmentShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->taskShader.isSet())
m_internalData->taskShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
if (m_internalData->meshShader.isSet())
m_internalData->meshShader.setShader(Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]), Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
}
#endif
void GraphicsPipelineWrapper::buildPipeline(const VkPipelineCache pipelineCache,
const VkPipeline basePipelineHandle,
const deInt32 basePipelineIndex,
PipelineCreationFeedbackCreateInfoWrapper creationFeedback,
void* pNext)
{
// make sure we are not trying to build pipeline second time
DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
// make sure all states were set
DE_ASSERT(m_internalData && (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS |
PSS_FRAGMENT_SHADER | PSS_FRAGMENT_OUTPUT_INTERFACE)));
// Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
DE_UNREF(creationFeedback);
DE_UNREF(pNext);
VkGraphicsPipelineCreateInfo* pointerToCreateInfo = &m_internalData->monolithicPipelineCreateInfo;
if (isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
{
#ifndef CTS_USES_VULKANSC
// Dynamic states that don't require additional extensions
std::vector<vk::VkDynamicState> dynamicStates = {
vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT,
vk::VK_DYNAMIC_STATE_LINE_WIDTH,
vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS,
vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
vk::VK_DYNAMIC_STATE_CULL_MODE_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT,
vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT,
vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT,
vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT,
vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
};
vk::VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures = initVulkanStructure();
vk::VkPhysicalDeviceFeatures2 features = initVulkanStructure(&meshShaderFeatures);
m_internalData->vki.getPhysicalDeviceFeatures2(m_internalData->physicalDevice, &features);
m_internalData->tessellationShaderFeature = features.features.tessellationShader;
m_internalData->geometryShaderFeature = features.features.geometryShader;
m_internalData->taskShaderFeature = meshShaderFeatures.taskShader;
m_internalData->meshShaderFeature = meshShaderFeatures.meshShader;
DE_ASSERT(m_internalData->extensionEnabled("VK_EXT_shader_object"));
// Add dynamic states that are required for each enabled extension
if (m_internalData->extensionEnabled("VK_EXT_transform_feedback"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
if (m_internalData->extensionEnabled("VK_EXT_blend_operation_advanced"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
if (m_internalData->extensionEnabled("VK_EXT_conservative_rasterization"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_coverage_reduction_mode"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
if (m_internalData->extensionEnabled("VK_NV_fragment_coverage_to_color"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_fragment_coverage_to_color"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
if (m_internalData->extensionEnabled("VK_EXT_depth_clip_enable"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_depth_clip_control"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_color_write_enable"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_conservative_rasterization"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") || m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") ||m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") ||m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_KHR);
if (m_internalData->extensionEnabled("VK_EXT_provoking_vertex"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
if (m_internalData->extensionEnabled("VK_KHR_fragment_shading_rate"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
if (m_internalData->extensionEnabled("VK_NV_representative_fragment_test"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_EXT_sample_locations"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_sample_locations"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
// Not working with VK_KHR_fragment_shading_rate
/*if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);*/
if (m_internalData->extensionEnabled("VK_NV_viewport_swizzle"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
if (m_internalData->extensionEnabled("VK_NV_clip_space_w_scaling"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_clip_space_w_scaling"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
if (m_internalData->extensionEnabled("VK_NV_scissor_exclusive"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);
if (m_internalData->extensionEnabled("VK_NV_scissor_exclusive"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
if (m_internalData->extensionEnabled("VK_EXT_attachment_feedback_loop_dynamic_state"))
dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
// Remove dynamic states that were already set as dynamic for the pipeline
// These dynamic state will already be set in the tests
bool depthClampEnableDynamic = false;
if (pointerToCreateInfo->pDynamicState)
{
for (deUint32 i = 0; i < pointerToCreateInfo->pDynamicState->dynamicStateCount; ++i)
{
if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_VIEWPORT)
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT), dynamicStates.end());
else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_SCISSOR)
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT), dynamicStates.end());
else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT)
{
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT), dynamicStates.end());
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT), dynamicStates.end());
}
else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)
{
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT), dynamicStates.end());
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT), dynamicStates.end());
}
else
dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(), pointerToCreateInfo->pDynamicState->pDynamicStates[i]), dynamicStates.end());
if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT)
depthClampEnableDynamic = true;
}
}
m_internalData->shaderObjectDynamicStates = dynamicStates;
// Save state needed for setting shader object dynamic state
auto state = &m_internalData->pipelineCreateState;
if (pointerToCreateInfo->pViewportState)
{
if (pointerToCreateInfo->pViewportState->pViewports)
{
state->viewports.resize(pointerToCreateInfo->pViewportState->viewportCount);
for (deUint32 i = 0; i < pointerToCreateInfo->pViewportState->viewportCount; ++i)
state->viewports[i] = pointerToCreateInfo->pViewportState->pViewports[i];
}
if (pointerToCreateInfo->pViewportState->pScissors)
{
state->scissors.resize(pointerToCreateInfo->pViewportState->scissorCount);
for (deUint32 i = 0; i < pointerToCreateInfo->pViewportState->scissorCount; ++i)
state->scissors[i] = pointerToCreateInfo->pViewportState->pScissors[i];
}
const auto depthClipControl = findStructure<VkPipelineViewportDepthClipControlCreateInfoEXT>(pointerToCreateInfo->pViewportState->pNext);
if (depthClipControl)
state->negativeOneToOne = depthClipControl->negativeOneToOne;
const auto viewportShadingRate = findStructure<VkPipelineViewportShadingRateImageStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
if (viewportShadingRate)
{
state->shadingRateImageEnable = viewportShadingRate->shadingRateImageEnable;
state->shadingRatePaletteCount = viewportShadingRate->viewportCount;
state->shadingRatePalettes.resize(viewportShadingRate->viewportCount);
state->shadingRatePaletteEntries.resize(viewportShadingRate->viewportCount);
for (deUint32 i = 0; i < viewportShadingRate->viewportCount; ++i)
{
state->shadingRatePalettes[i] = viewportShadingRate->pShadingRatePalettes[i];
state->shadingRatePaletteEntries[i].resize(viewportShadingRate->pShadingRatePalettes[i].shadingRatePaletteEntryCount);
for (deUint32 j = 0; j < viewportShadingRate->pShadingRatePalettes[i].shadingRatePaletteEntryCount; ++j)
state->shadingRatePaletteEntries[i][j] = viewportShadingRate->pShadingRatePalettes[i].pShadingRatePaletteEntries[j];
state->shadingRatePalettes[i].pShadingRatePaletteEntries = state->shadingRatePaletteEntries[i].data();
}
}
const auto viewportSwizzle = findStructure<VkPipelineViewportSwizzleStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
if (viewportSwizzle)
{
state->viewportSwizzles.resize(viewportSwizzle->viewportCount);
for (deUint32 i = 0; i < viewportSwizzle->viewportCount; ++i)
state->viewportSwizzles[i] = viewportSwizzle->pViewportSwizzles[i];
}
const auto viewportWScaling = findStructure<VkPipelineViewportWScalingStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
if (viewportWScaling)
{
state->viewportWScalingEnable = viewportWScaling->viewportWScalingEnable;
state->viewportWScalingCount = viewportWScaling->viewportCount;
state->viewportWScalings.resize(viewportWScaling->viewportCount);
for (deUint32 i = 0; i < viewportWScaling->viewportCount; ++i)
state->viewportWScalings[i] = viewportWScaling->pViewportWScalings[i];
}
const auto coarseSampleOrder = findStructure<VkPipelineViewportCoarseSampleOrderStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
if (coarseSampleOrder)
{
state->coarseSampleOrderType = coarseSampleOrder->sampleOrderType;
state->coarseCustomSampleOrderCount = coarseSampleOrder->customSampleOrderCount;
state->coarseCustomSampleOrders.resize(coarseSampleOrder->customSampleOrderCount);
state->coarseSampleLocations.resize(coarseSampleOrder->customSampleOrderCount);
for (deUint32 i = 0; i < coarseSampleOrder->customSampleOrderCount; ++i)
{
state->coarseCustomSampleOrders[i] = coarseSampleOrder->pCustomSampleOrders[i];
state->coarseSampleLocations[i].resize(coarseSampleOrder->pCustomSampleOrders[i].sampleCount);
for (deUint32 j = 0; j < coarseSampleOrder->pCustomSampleOrders[i].sampleCount; ++j)
state->coarseSampleLocations[i][j] = coarseSampleOrder->pCustomSampleOrders[i].pSampleLocations[j];
state->coarseCustomSampleOrders[i].pSampleLocations = state->coarseSampleLocations[i].data();
}
}
}
if (pointerToCreateInfo->pRasterizationState)
{
state->lineWidth = pointerToCreateInfo->pRasterizationState->lineWidth;
state->depthBiasConstantFactor = pointerToCreateInfo->pRasterizationState->depthBiasConstantFactor;
state->depthBiasClamp = pointerToCreateInfo->pRasterizationState->depthBiasClamp;
state->depthBiasSlopeFactor = pointerToCreateInfo->pRasterizationState->depthBiasSlopeFactor;
state->cullMode = pointerToCreateInfo->pRasterizationState->cullMode;
state->frontFace = pointerToCreateInfo->pRasterizationState->frontFace;
state->depthBiasEnable = pointerToCreateInfo->pRasterizationState->depthBiasEnable;
state->rasterizerDiscardEnable = pointerToCreateInfo->pRasterizationState->rasterizerDiscardEnable;
const auto conservative = findStructure<VkPipelineRasterizationConservativeStateCreateInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (conservative)
{
state->conservativeRasterizationMode = conservative->conservativeRasterizationMode;
state->extraPrimitiveOverestimationSize = conservative->extraPrimitiveOverestimationSize;
}
state->depthClampEnable = pointerToCreateInfo->pRasterizationState->depthClampEnable;
const auto depthClip = findStructure<VkPipelineRasterizationDepthClipStateCreateInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (depthClip)
state->depthClipEnable = depthClip->depthClipEnable;
else
state->depthClipEnable = !pointerToCreateInfo->pRasterizationState->depthClampEnable && !depthClampEnableDynamic;
const auto rasterizationLine = findStructure<VkPipelineRasterizationLineStateCreateInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (rasterizationLine)
{
state->lineRasterizationMode = rasterizationLine->lineRasterizationMode;
state->stippledLineEnable = rasterizationLine->stippledLineEnable;
state->lineStippleFactor = rasterizationLine->lineStippleFactor;
state->lineStipplePattern = rasterizationLine->lineStipplePattern;
}
const auto rasterizationStream = findStructure<VkPipelineRasterizationStateStreamCreateInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (rasterizationStream)
state->rasterizationStream = rasterizationStream->rasterizationStream;
state->polygonMode = pointerToCreateInfo->pRasterizationState->polygonMode;
const auto provokingVertex = findStructure<VkPipelineRasterizationProvokingVertexStateCreateInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (provokingVertex)
state->provokingVertexMode = provokingVertex->provokingVertexMode;
const auto depthBiasRepresentationInfo = findStructure<VkDepthBiasRepresentationInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
if (depthBiasRepresentationInfo)
{
state->depthBiasRepresentation = depthBiasRepresentationInfo->depthBiasRepresentation;
state->depthBiasExact = depthBiasRepresentationInfo->depthBiasExact;
}
}
if (pointerToCreateInfo->pColorBlendState)
{
memcpy(&state->blendConstants, pointerToCreateInfo->pColorBlendState->blendConstants, sizeof(float) * 4);
state->logicOp = pointerToCreateInfo->pColorBlendState->logicOp;
const auto blendAdvancedState = findStructure<VkPipelineColorBlendAdvancedStateCreateInfoEXT>(pointerToCreateInfo->pColorBlendState->pNext);
if (blendAdvancedState)
{
state->colorBlendAdvanced.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
for (deUint32 i = 0; i < pointerToCreateInfo->pColorBlendState->attachmentCount; ++i)
{
if (pointerToCreateInfo->pColorBlendState->pAttachments)
state->colorBlendAdvanced[i].advancedBlendOp = pointerToCreateInfo->pColorBlendState->pAttachments[i].colorBlendOp;
state->colorBlendAdvanced[i].srcPremultiplied = blendAdvancedState->srcPremultiplied;
state->colorBlendAdvanced[i].dstPremultiplied = blendAdvancedState->dstPremultiplied;
state->colorBlendAdvanced[i].blendOverlap = blendAdvancedState->blendOverlap;
state->colorBlendAdvanced[i].clampResults = VK_FALSE;
}
}
state->colorBlendEnables.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
state->blendEquations.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
state->colorWriteMasks.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
for (deUint32 i = 0; i < (deUint32)pointerToCreateInfo->pColorBlendState->attachmentCount; ++i)
{
if (pointerToCreateInfo->pColorBlendState->pAttachments)
{
state->colorBlendEnables[i] = pointerToCreateInfo->pColorBlendState->pAttachments[i].blendEnable;
state->blendEquations[i].srcColorBlendFactor = pointerToCreateInfo->pColorBlendState->pAttachments[i].srcColorBlendFactor;
state->blendEquations[i].dstColorBlendFactor = pointerToCreateInfo->pColorBlendState->pAttachments[i].dstColorBlendFactor;
state->blendEquations[i].colorBlendOp = pointerToCreateInfo->pColorBlendState->pAttachments[i].colorBlendOp;
state->blendEquations[i].srcAlphaBlendFactor = pointerToCreateInfo->pColorBlendState->pAttachments[i].srcAlphaBlendFactor;
state->blendEquations[i].dstAlphaBlendFactor = pointerToCreateInfo->pColorBlendState->pAttachments[i].dstAlphaBlendFactor;
state->blendEquations[i].alphaBlendOp = pointerToCreateInfo->pColorBlendState->pAttachments[i].alphaBlendOp;
state->colorWriteMasks[i] = pointerToCreateInfo->pColorBlendState->pAttachments[i].colorWriteMask;
}
// colorBlendOp and alphaBlendOp must not be advanced blend operations and they will be set with colorBlendAdvanced
if (blendAdvancedState)
{
state->blendEquations[i].colorBlendOp = vk::VK_BLEND_OP_ADD;
state->blendEquations[i].alphaBlendOp = vk::VK_BLEND_OP_ADD;
}
}
state->logicOpEnable = pointerToCreateInfo->pColorBlendState->logicOpEnable;
const auto colorWrite = findStructure<VkPipelineColorWriteCreateInfoEXT>(pointerToCreateInfo->pColorBlendState->pNext);
if (colorWrite)
{
state->colorWriteEnableAttachmentCount = colorWrite->attachmentCount;
state->colorWriteEnables.resize(colorWrite->attachmentCount);
for (deUint32 i = 0; i < colorWrite->attachmentCount; ++i)
state->colorWriteEnables[i] = colorWrite->pColorWriteEnables[i];
}
}
if (pointerToCreateInfo->pDepthStencilState)
{
state->minDepthBounds = pointerToCreateInfo->pDepthStencilState->minDepthBounds;
state->maxDepthBounds = pointerToCreateInfo->pDepthStencilState->maxDepthBounds;
state->stencilFront = pointerToCreateInfo->pDepthStencilState->front;
state->stencilBack = pointerToCreateInfo->pDepthStencilState->back;
state->depthBoundsTestEnable = pointerToCreateInfo->pDepthStencilState->depthBoundsTestEnable;
state->depthCompareOp = pointerToCreateInfo->pDepthStencilState->depthCompareOp;
state->depthTestEnable = pointerToCreateInfo->pDepthStencilState->depthTestEnable;
state->depthWriteEnable = pointerToCreateInfo->pDepthStencilState->depthWriteEnable;
state->stencilTestEnable = pointerToCreateInfo->pDepthStencilState->stencilTestEnable;
}
if (pointerToCreateInfo->pInputAssemblyState)
{
state->topology = pointerToCreateInfo->pInputAssemblyState->topology;
state->primitiveRestartEnable = pointerToCreateInfo->pInputAssemblyState->primitiveRestartEnable;
}
if (pointerToCreateInfo->pVertexInputState)
{
state->attributes.resize(pointerToCreateInfo->pVertexInputState->vertexAttributeDescriptionCount);
state->bindings.resize(pointerToCreateInfo->pVertexInputState->vertexBindingDescriptionCount);
for (deUint32 i = 0; i < pointerToCreateInfo->pVertexInputState->vertexAttributeDescriptionCount; ++i)
{
state->attributes[i] = initVulkanStructure();
state->attributes[i].location = pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].location;
state->attributes[i].binding = pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].binding;
state->attributes[i].format = pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].format;
state->attributes[i].offset = pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].offset;
}
const auto divisorInfo = findStructure<VkPipelineVertexInputDivisorStateCreateInfoEXT>(pointerToCreateInfo->pVertexInputState->pNext);
for (deUint32 i = 0; i < pointerToCreateInfo->pVertexInputState->vertexBindingDescriptionCount; ++i)
{
state->bindings[i] = initVulkanStructure();
state->bindings[i].binding = pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].binding;
state->bindings[i].stride = pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].stride;
state->bindings[i].inputRate = pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].inputRate;
state->bindings[i].divisor = 1;
if (divisorInfo)
{
for (deUint32 j = 0; j < divisorInfo->vertexBindingDivisorCount; ++j)
{
if (state->bindings[i].binding == divisorInfo->pVertexBindingDivisors[j].binding)
{
state->bindings[i].divisor = divisorInfo->pVertexBindingDivisors[i].divisor;
}
}
}
}
}
if (pointerToCreateInfo->pTessellationState)
{
state->patchControlPoints = pointerToCreateInfo->pTessellationState->patchControlPoints;
const auto tessellationDomainOrigin = findStructure<VkPipelineTessellationDomainOriginStateCreateInfo>(pointerToCreateInfo->pTessellationState->pNext);
if (tessellationDomainOrigin)
state->domainOrigin = tessellationDomainOrigin->domainOrigin;
}
if (pointerToCreateInfo->pMultisampleState)
{
state->alphaToCoverageEnable = pointerToCreateInfo->pMultisampleState->alphaToCoverageEnable;
state->alphaToOneEnable = pointerToCreateInfo->pMultisampleState->alphaToOneEnable;
const auto coverageModulation = findStructure<VkPipelineCoverageModulationStateCreateInfoNV>(pointerToCreateInfo->pMultisampleState->pNext);
if (coverageModulation)
{
state->coverageModulationMode = coverageModulation->coverageModulationMode;
state->coverageModulationTableEnable = coverageModulation->coverageModulationTableEnable;
state->coverageModulationTable.resize(coverageModulation->coverageModulationTableCount);
for (deUint32 i = 0; i < (deUint32)coverageModulation->coverageModulationTableCount; ++i)
state->coverageModulationTable[i] = coverageModulation->pCoverageModulationTable[i];
}
const auto coverageReduction = findStructure<VkPipelineCoverageReductionStateCreateInfoNV>(pointerToCreateInfo->pMultisampleState->pNext);
if (coverageReduction)
state->coverageReductionMode = coverageReduction->coverageReductionMode;
const auto coverageToColor = findStructure<VkPipelineCoverageToColorStateCreateInfoNV>(pointerToCreateInfo->pMultisampleState->pNext);
if (coverageToColor)
{
state->coverageToColorEnable = coverageToColor->coverageToColorEnable;
state->coverageToColorLocation = coverageToColor->coverageToColorLocation;
}
state->rasterizationSamples = pointerToCreateInfo->pMultisampleState->rasterizationSamples;
const auto sampleLocations = findStructure<VkPipelineSampleLocationsStateCreateInfoEXT>(pointerToCreateInfo->pMultisampleState->pNext);
if (sampleLocations)
{
state->sampleLocationsEnable = sampleLocations->sampleLocationsEnable;
state->sampleLocationsInfo = sampleLocations->sampleLocationsInfo;
state->pSampleLocations.resize(sampleLocations->sampleLocationsInfo.sampleLocationsCount);
for (deUint32 i = 0; i < sampleLocations->sampleLocationsInfo.sampleLocationsCount; ++i)
state->pSampleLocations[i] = sampleLocations->sampleLocationsInfo.pSampleLocations[i];
state->sampleLocationsInfo.pSampleLocations = state->pSampleLocations.data();
}
state->rasterizationSamples = pointerToCreateInfo->pMultisampleState->rasterizationSamples;
deUint32 count = (pointerToCreateInfo->pMultisampleState->rasterizationSamples > vk::VK_SAMPLE_COUNT_32_BIT) ? 2 : 1;
state->sampleMasks.resize(count, 0);
for (deUint32 i = 0; i < count; ++i)
if (pointerToCreateInfo->pMultisampleState->pSampleMask)
state->sampleMasks[i] = pointerToCreateInfo->pMultisampleState->pSampleMask[i];
else
state->sampleMasks[i] = 0xFF; // If pSampleMask is NULL, it is treated as if the mask has all bits set to 1
}
const auto representativeFragment = findStructure<VkPipelineRepresentativeFragmentTestStateCreateInfoNV>(pointerToCreateInfo->pNext);
if (representativeFragment)
{
state->representativeFragmentTestEnable = representativeFragment->representativeFragmentTestEnable;
}
const auto fragmentShadingRate = findStructure<VkPipelineFragmentShadingRateStateCreateInfoKHR>(pointerToCreateInfo->pNext);
if (fragmentShadingRate)
{
state->fragmentShadingRateSize = fragmentShadingRate->fragmentSize;
state->combinerOps[0] = fragmentShadingRate->combinerOps[0];
state->combinerOps[1] = fragmentShadingRate->combinerOps[1];
}
const auto exclusiveScissor = findStructure<VkPipelineViewportExclusiveScissorStateCreateInfoNV>(pointerToCreateInfo->pNext);
if (exclusiveScissor)
{
state->exclusiveScissorCount = exclusiveScissor->exclusiveScissorCount;
state->exclussiveScissors.resize(exclusiveScissor->exclusiveScissorCount);
for (deUint32 i = 0; i < exclusiveScissor->exclusiveScissorCount; ++i)
state->exclussiveScissors[i] = exclusiveScissor->pExclusiveScissors[i];
}
const auto discardRectangle = findStructure<VkPipelineDiscardRectangleStateCreateInfoEXT>(pointerToCreateInfo->pNext);
if (discardRectangle)
{
state->discardRectangleEnable = discardRectangle->discardRectangleCount > 0;
state->discardRectangles.resize(discardRectangle->discardRectangleCount);
for (deUint32 i = 0; i < discardRectangle->discardRectangleCount; ++i)
state->discardRectangles[i] = discardRectangle->pDiscardRectangles[i];
state->discardRectangleMode = discardRectangle->discardRectangleMode;
}
if (pointerToCreateInfo->flags & VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
state->attachmentFeedbackLoopEnable |= VK_IMAGE_ASPECT_COLOR_BIT;
if (pointerToCreateInfo->flags & VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
state->attachmentFeedbackLoopEnable |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
bool linked = m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV ||
m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
bool binary = m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY ||
m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
createShaders(linked, false);
if (binary)
{
createShaders(linked, true);
}
#endif
}
else
{
#ifndef CTS_USES_VULKANSC
VkGraphicsPipelineCreateInfo linkedCreateInfo = initVulkanStructure();
std::vector<VkPipeline> rawPipelines;
VkPipelineLibraryCreateInfoKHR linkingInfo
{
VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType;
creationFeedback.ptr, // const void* pNext;
0u, // deUint32 libraryCount;
nullptr, // const VkPipeline* pLibraries;
};
if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
{
for (const auto& pipelinePtr : m_pipelineParts)
{
const auto& pipeline = pipelinePtr.get();
if (pipeline != DE_NULL)
rawPipelines.push_back(pipeline);
}
linkingInfo.libraryCount = static_cast<uint32_t>(rawPipelines.size());
linkingInfo.pLibraries = de::dataOrNull(rawPipelines);
// If a test hits the following assert, it's likely missing a call
// to the setMonolithicPipelineLayout() method. Related VUs:
// * VUID-VkGraphicsPipelineCreateInfo-flags-06642
// * VUID-VkGraphicsPipelineCreateInfo-None-07826
// * VUID-VkGraphicsPipelineCreateInfo-layout-07827
// * VUID-VkGraphicsPipelineCreateInfo-flags-06729
// * VUID-VkGraphicsPipelineCreateInfo-flags-06730
DE_ASSERT(m_internalData->monolithicPipelineCreateInfo.layout != VK_NULL_HANDLE);
linkedCreateInfo.layout = m_internalData->monolithicPipelineCreateInfo.layout;
linkedCreateInfo.flags = m_internalData->pipelineFlags;
linkedCreateInfo.pNext = &linkingInfo;
pointerToCreateInfo = &linkedCreateInfo;
if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
linkedCreateInfo.flags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
if (m_internalData->failOnCompileWhenLinking)
linkedCreateInfo.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
}
else
{
// note: there might be other structures in the chain already
void* firstStructInChain = static_cast<void*>(pointerToCreateInfo);
addToChain(&firstStructInChain, creationFeedback.ptr);
addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
addToChain(&firstStructInChain, m_internalData->pRenderingInputAttachmentIndex.ptr);
addToChain(&firstStructInChain, m_internalData->pRenderingAttachmentLocation.ptr);
addToChain(&firstStructInChain, pNext);
}
VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
if (m_internalData->pipelineFlags2)
{
void* firstStructInChain = static_cast<void*>(pointerToCreateInfo);
pipelineFlags2CreateInfo.flags = m_internalData->pipelineFlags2 | translateCreateFlag(pointerToCreateInfo->flags);
addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
pointerToCreateInfo->flags = 0u;
}
#endif // CTS_USES_VULKANSC
pointerToCreateInfo->basePipelineHandle = basePipelineHandle;
pointerToCreateInfo->basePipelineIndex = basePipelineIndex;
m_pipelineFinal = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, pipelineCache, pointerToCreateInfo);
}
}
bool GraphicsPipelineWrapper::isShaderObjectDynamic (vk::VkDynamicState dynamicState) const
{
return std::find(m_internalData->shaderObjectDynamicStates.begin(), m_internalData->shaderObjectDynamicStates.end(), dynamicState) != m_internalData->shaderObjectDynamicStates.end();
}
void GraphicsPipelineWrapper::setShaderObjectDynamicStates (vk::VkCommandBuffer cmdBuffer) const
{
DE_UNREF(cmdBuffer);
#ifndef CTS_USES_VULKANSC
const auto& vk = m_internalData->vk;
const auto state = &m_internalData->pipelineCreateState;
// Some dynamic state only need to be set when these conditions are met
const bool meshOrTask = m_internalData->meshShader.isSet() || m_internalData->taskShader.isSet();
const bool tese = m_internalData->tessellationEvaluationShader.isSet();
const bool topologyPatchList = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY) || state->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
const bool rasterizerDiscardDisabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE) || !state->rasterizerDiscardEnable;
const bool polygonModeLine = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT) || state->polygonMode == vk::VK_POLYGON_MODE_LINE;
const bool topologyLine = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY) ||
state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST || state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP || state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
const bool depthTestEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE) || state->depthTestEnable;
const bool depthBoundsTestEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE) || state->depthBoundsTestEnable;
const bool depthBiasEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE) || state->depthBiasEnable;
const bool stencilTestEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE) || state->stencilTestEnable;
const bool logicOpEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT) || state->logicOpEnable;
const bool discardRectangle = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT) || state->discardRectangleEnable;
const bool sampleLocationsEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT) || state->sampleLocationsEnable;
const bool stippledLineEnabled = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT) || state->stippledLineEnable;
bool blendFactorConstant = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
for (const auto& blend : state->blendEquations)
{
if (blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR || blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA || blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR || blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA || blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR || blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA || blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR || blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA || blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)
blendFactorConstant = true;
}
for (const auto dynamicState : m_internalData->shaderObjectDynamicStates)
{
switch (dynamicState)
{
case vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT:
if (!state->viewports.empty())
vk.cmdSetViewportWithCount(cmdBuffer, (deUint32)state->viewports.size(), state->viewports.data());
break;
case vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT:
if (!state->scissors.empty())
vk.cmdSetScissorWithCount(cmdBuffer, (deUint32)state->scissors.size(), state->scissors.data());
break;
case vk::VK_DYNAMIC_STATE_LINE_WIDTH:
if (polygonModeLine || topologyLine)
vk.cmdSetLineWidth(cmdBuffer, state->lineWidth);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_BIAS:
if (rasterizerDiscardDisabled && depthBiasEnabled)
{
if (m_internalData->extensionEnabled("VK_EXT_depth_bias_control")) {
VkDepthBiasRepresentationInfoEXT depthBiasRepresentationInfo = vk::initVulkanStructure();
depthBiasRepresentationInfo.depthBiasRepresentation = state->depthBiasRepresentation;
depthBiasRepresentationInfo.depthBiasExact = state->depthBiasExact;
vk::VkDepthBiasInfoEXT depthBiasInfo = vk::initVulkanStructure(&depthBiasRepresentationInfo);
depthBiasInfo.depthBiasConstantFactor = state->depthBiasConstantFactor;
depthBiasInfo.depthBiasClamp = state->depthBiasClamp;
depthBiasInfo.depthBiasSlopeFactor = state->depthBiasSlopeFactor;
vk.cmdSetDepthBias2EXT(cmdBuffer, &depthBiasInfo);
}
else
{
vk.cmdSetDepthBias(cmdBuffer, state->depthBiasConstantFactor, state->depthBiasClamp, state->depthBiasSlopeFactor);
}
}
break;
case vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS:
if (rasterizerDiscardDisabled && blendFactorConstant)
vk.cmdSetBlendConstants(cmdBuffer, state->blendConstants);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS:
if (rasterizerDiscardDisabled && depthBoundsTestEnabled)
vk.cmdSetDepthBounds(cmdBuffer, state->minDepthBounds, state->maxDepthBounds);
break;
case vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
{
vk.cmdSetStencilCompareMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.compareMask);
vk.cmdSetStencilCompareMask(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.compareMask);
}
break;
case vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
{
vk.cmdSetStencilWriteMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.writeMask);
vk.cmdSetStencilWriteMask(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.writeMask);
}
break;
case vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE:
{
vk.cmdSetStencilReference(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.reference);
vk.cmdSetStencilReference(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.reference);
}
break;
case vk::VK_DYNAMIC_STATE_CULL_MODE_EXT:
vk.cmdSetCullMode(cmdBuffer, state->cullMode);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetDepthBoundsTestEnable(cmdBuffer, state->depthBoundsTestEnable);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT:
if (rasterizerDiscardDisabled && depthTestEnabled)
vk.cmdSetDepthCompareOp(cmdBuffer, state->depthCompareOp);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetDepthTestEnable(cmdBuffer, state->depthTestEnable);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetDepthWriteEnable(cmdBuffer, state->depthWriteEnable);
break;
case vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT:
vk.cmdSetFrontFace(cmdBuffer, state->frontFace);
break;
case vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT:
if (!meshOrTask)
vk.cmdSetPrimitiveTopology(cmdBuffer, state->topology);
break;
case vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT:
if (rasterizerDiscardDisabled && stencilTestEnabled)
{
vk.cmdSetStencilOp(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.failOp, state->stencilFront.passOp, state->stencilFront.depthFailOp, state->stencilFront.compareOp);
vk.cmdSetStencilOp(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.failOp, state->stencilBack.passOp, state->stencilBack.depthFailOp, state->stencilBack.compareOp);
}
break;
case vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetStencilTestEnable(cmdBuffer, state->stencilTestEnable);
break;
case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
if (!meshOrTask)
vk.cmdSetVertexInputEXT(cmdBuffer, (deUint32)state->bindings.size(), state->bindings.data(), (deUint32)state->attributes.size(), state->attributes.data());
break;
case vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetDepthBiasEnable(cmdBuffer, state->depthBiasEnable);
break;
case vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT:
if (rasterizerDiscardDisabled && logicOpEnabled)
vk.cmdSetLogicOpEXT(cmdBuffer, state->logicOp);
break;
case vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
if (topologyPatchList && !meshOrTask && tese)
vk.cmdSetPatchControlPointsEXT(cmdBuffer, state->patchControlPoints);
break;
case vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT:
if (!meshOrTask)
vk.cmdSetPrimitiveRestartEnable(cmdBuffer, state->primitiveRestartEnable);
break;
case vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT:
vk.cmdSetRasterizerDiscardEnable(cmdBuffer, state->rasterizerDiscardEnable);
break;
case vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT:
vk.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, state->alphaToCoverageEnable);
break;
case vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT:
vk.cmdSetAlphaToOneEnableEXT(cmdBuffer, state->alphaToOneEnable);
break;
case vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT:
if (!state->colorBlendAdvanced.empty())
{
for (deUint32 i = 0; i < (deUint32)state->colorBlendAdvanced.size(); ++i)
if (!isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT) || state->colorBlendEnables[i])
vk.cmdSetColorBlendAdvancedEXT(cmdBuffer, i, 1, &state->colorBlendAdvanced[i]);
}
break;
case vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT:
if (rasterizerDiscardDisabled)
{
if (!state->colorBlendEnables.empty())
{
vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0, (deUint32)state->colorBlendEnables.size(), state->colorBlendEnables.data());
}
else
{
VkBool32 disable = VK_FALSE;
vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0, 1u, &disable);
}
}
break;
case vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT:
if (rasterizerDiscardDisabled)
{
if (!state->blendEquations.empty())
{
vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0, (deUint32)state->blendEquations.size(), state->blendEquations.data());
}
else
{
vk::VkColorBlendEquationEXT blendEquation = {
VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
VK_BLEND_FACTOR_DST_ALPHA, // VkBlendFactor dstColorBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
VK_BLEND_FACTOR_DST_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
};
vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0, 1u, &blendEquation);
}
}
break;
case vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT:
if (rasterizerDiscardDisabled)
{
if (!state->colorWriteMasks.empty())
{
vk.cmdSetColorWriteMaskEXT(cmdBuffer, 0, (deUint32)state->colorWriteMasks.size(), state->colorWriteMasks.data());
}
else
{
VkColorComponentFlags colorWriteMask = 0u;
vk.cmdSetColorWriteMaskEXT(cmdBuffer, 0, 1u, &colorWriteMask);
}
}
break;
case vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT:
vk.cmdSetConservativeRasterizationModeEXT(cmdBuffer, state->conservativeRasterizationMode);
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV:
vk.cmdSetCoverageModulationModeNV(cmdBuffer, state->coverageModulationMode);
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV:
vk.cmdSetCoverageModulationTableEnableNV(cmdBuffer, state->coverageModulationTableEnable);
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV:
if (!state->coverageModulationTable.empty())
vk.cmdSetCoverageModulationTableNV(cmdBuffer, (deUint32)state->coverageModulationTable.size(), state->coverageModulationTable.data());
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV:
vk.cmdSetCoverageReductionModeNV(cmdBuffer, state->coverageReductionMode);
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV:
vk.cmdSetCoverageToColorEnableNV(cmdBuffer, state->coverageToColorEnable);
break;
case vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV:
vk.cmdSetCoverageToColorLocationNV(cmdBuffer, state->coverageToColorLocation);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetDepthClampEnableEXT(cmdBuffer, state->depthClampEnable);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT:
vk.cmdSetDepthClipEnableEXT(cmdBuffer, state->depthClipEnable);
break;
case vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT:
vk.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer, state->negativeOneToOne);
break;
case vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
if (state->colorWriteEnableAttachmentCount > 0)
vk.cmdSetColorWriteEnableEXT(cmdBuffer, state->colorWriteEnableAttachmentCount, state->colorWriteEnables.data());
else
{
std::vector<VkBool32> enable(state->colorBlendEnables.empty() ? 1u : state->colorBlendEnables.size(), VK_TRUE);
vk.cmdSetColorWriteEnableEXT(cmdBuffer, (deUint32)enable.size(), enable.data());
}
break;
case vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT:
vk.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer, state->extraPrimitiveOverestimationSize);
break;
case vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT:
vk.cmdSetLineRasterizationModeEXT(cmdBuffer, state->lineRasterizationMode);
break;
case vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT:
vk.cmdSetLineStippleEnableEXT(cmdBuffer, state->stippledLineEnable);
break;
case vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
if (stippledLineEnabled)
vk.cmdSetLineStippleKHR(cmdBuffer, state->lineStippleFactor, state->lineStipplePattern);
break;
case vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT:
if (rasterizerDiscardDisabled)
vk.cmdSetLogicOpEnableEXT(cmdBuffer, state->logicOpEnable);
break;
case vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT:
vk.cmdSetPolygonModeEXT(cmdBuffer, state->polygonMode);
break;
case vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT:
vk.cmdSetProvokingVertexModeEXT(cmdBuffer, state->provokingVertexMode);
break;
case vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT:
vk.cmdSetRasterizationSamplesEXT(cmdBuffer, state->rasterizationSamples);
break;
case vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR:
vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &state->fragmentShadingRateSize, state->combinerOps);
break;
case vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT:
vk.cmdSetRasterizationStreamEXT(cmdBuffer, state->rasterizationStream);
break;
case vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV:
vk.cmdSetRepresentativeFragmentTestEnableNV(cmdBuffer, state->representativeFragmentTestEnable);
break;
case vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT:
vk.cmdSetSampleLocationsEnableEXT(cmdBuffer, state->sampleLocationsEnable);
break;
case vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
if (sampleLocationsEnabled)
vk.cmdSetSampleLocationsEXT(cmdBuffer, &state->sampleLocationsInfo);
break;
case vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT:
if (!state->sampleMasks.empty())
vk.cmdSetSampleMaskEXT(cmdBuffer, state->rasterizationSamples, state->sampleMasks.data());
break;
case vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV:
vk.cmdSetShadingRateImageEnableNV(cmdBuffer, state->shadingRateImageEnable);
break;
case vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT:
if (tese)
vk.cmdSetTessellationDomainOriginEXT(cmdBuffer, state->domainOrigin);
break;
case vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV:
if (!state->viewportSwizzles.empty())
{
vk.cmdSetViewportSwizzleNV(cmdBuffer, 0, (deUint32)state->viewportSwizzles.size(), state->viewportSwizzles.data());
}
else
{
std::vector<vk::VkViewportSwizzleNV> idSwizzles(4u);
for (auto& swizzle : idSwizzles)
{
swizzle = {
vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
};
}
vk.cmdSetViewportSwizzleNV(cmdBuffer, 0u, (deUint32)idSwizzles.size(), idSwizzles.data());
}
break;
case vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV:
vk.cmdSetViewportWScalingEnableNV(cmdBuffer, state->viewportWScalingEnable);
break;
case vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV:
if (state->viewportWScalingCount > 0)
vk.cmdSetViewportWScalingNV(cmdBuffer, 0, state->viewportWScalingCount, state->viewportWScalings.data());
break;
case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
if (!meshOrTask)
vk.cmdSetVertexInputEXT(cmdBuffer, (deUint32)state->bindings.size(), state->bindings.data(), (deUint32)state->attributes.size(), state->attributes.data());
break;
case vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV:
vk.cmdSetCoarseSampleOrderNV(cmdBuffer, state->coarseSampleOrderType, state->coarseCustomSampleOrderCount, state->coarseCustomSampleOrders.data());
break;
case vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV:
if (state->shadingRatePaletteCount > 0)
vk.cmdSetViewportShadingRatePaletteNV(cmdBuffer, 0, state->shadingRatePaletteCount, state->shadingRatePalettes.data());
break;
case vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV:
{
if (state->exclusiveScissorCount > 0)
{
std::vector<VkBool32> exclusiveScissorEnable(state->exclusiveScissorCount, VK_TRUE);
vk.cmdSetExclusiveScissorEnableNV(cmdBuffer, 0u, state->exclusiveScissorCount, exclusiveScissorEnable.data());
}
else
{
VkBool32 enable = VK_FALSE;
vk.cmdSetExclusiveScissorEnableNV(cmdBuffer, 0u, 1u, &enable);
}
break;
}
case vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV:
if (state->exclusiveScissorCount > 0)
vk.cmdSetExclusiveScissorNV(cmdBuffer, 0u, state->exclusiveScissorCount, state->exclussiveScissors.data());
break;
case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT:
vk.cmdSetDiscardRectangleEnableEXT(cmdBuffer, state->discardRectangleEnable);
break;
case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT:
if (discardRectangle)
vk.cmdSetDiscardRectangleEXT(cmdBuffer, 0, (deUint32)state->discardRectangles.size(), state->discardRectangles.data());
break;
case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT:
if (discardRectangle)
vk.cmdSetDiscardRectangleModeEXT(cmdBuffer, state->discardRectangleMode);
break;
case vk::VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT:
vk.cmdSetAttachmentFeedbackLoopEnableEXT(cmdBuffer, state->attachmentFeedbackLoopEnable);
break;
default:
break;
}
}
#endif // CTS_USES_VULKANSC
}
void GraphicsPipelineWrapper::bind (vk::VkCommandBuffer cmdBuffer) const
{
const auto& vk = m_internalData->vk;
if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
{
vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, getPipeline());
}
else
{
#ifndef CTS_USES_VULKANSC
const VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
VkShaderEXT vertShader = m_internalData->vertexShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &vertStage, &vertShader);
const VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
VkShaderEXT tescShader = m_internalData->tessellationControlShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &tescStage, &tescShader);
const VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
VkShaderEXT teseShader = m_internalData->tessellationEvaluationShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &teseStage, &teseShader);
const VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
VkShaderEXT geomShader = m_internalData->geometryShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &geomStage, &geomShader);
const VkShaderStageFlagBits fragStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
VkShaderEXT fragShader = m_internalData->fragmentShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &fragStage, &fragShader);
if (m_internalData->meshShaderFeature)
{
const VkShaderStageFlagBits meshStage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
VkShaderEXT meshShader = m_internalData->meshShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &meshStage, &meshShader);
}
if (m_internalData->taskShaderFeature)
{
const VkShaderStageFlagBits taskStage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
VkShaderEXT taskShader = m_internalData->taskShader.getShader();
vk.cmdBindShadersEXT(cmdBuffer, 1, &taskStage, &taskShader);
}
// Set all dynamic state that would otherwise have been set with the pipeline
setShaderObjectDynamicStates(cmdBuffer);
#endif
}
}
deBool GraphicsPipelineWrapper::wasBuild() const
{
return !!m_pipelineFinal.get();
}
deBool GraphicsPipelineWrapper::wasPipelineOrShaderObjectBuild (void) const
{
if (!!m_pipelineFinal.get())
return true;
#ifndef CTS_USES_VULKANSC
if (!!m_internalData->vertexShader.getShader() ||
!!m_internalData->tessellationControlShader.getShader() ||
!!m_internalData->tessellationEvaluationShader.getShader() ||
!!m_internalData->geometryShader.getShader() ||
!!m_internalData->fragmentShader.getShader() ||
!!m_internalData->taskShader.getShader() ||
!!m_internalData->meshShader.getShader())
return true;
#endif
return false;
}
VkPipeline GraphicsPipelineWrapper::getPipeline (void) const
{
DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
return m_pipelineFinal.get();
}
void GraphicsPipelineWrapper::destroyPipeline (void)
{
DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
m_pipelineFinal = Move<VkPipeline>();
}
} // vk