Support for VK_KHR_create_renderpass2
This cl adds support for the VK_KHR_create_renderpass2. It doesn't
add any new functionality and ignores any new performance hints
that are part of this extension, but it properly supports the new
API entries that are part of this extension.
Bug: b/148884281
Tests: dEQP-VK.*
Change-Id: I15d9d00658e65380f4e93e59299a8c5e5212f95e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/40988
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index 796596b..f293ca5 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -320,6 +320,15 @@
{
MAKE_VULKAN_DEVICE_ENTRY(vkGetDescriptorSetLayoutSupportKHR),
} },
+ // VK_KHR_create_renderpass2
+ {
+ VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME,
+ {
+ MAKE_VULKAN_DEVICE_ENTRY(vkCreateRenderPass2KHR),
+ MAKE_VULKAN_DEVICE_ENTRY(vkCmdBeginRenderPass2KHR),
+ MAKE_VULKAN_DEVICE_ENTRY(vkCmdNextSubpass2KHR),
+ MAKE_VULKAN_DEVICE_ENTRY(vkCmdEndRenderPass2KHR),
+ } },
// VK_EXT_line_rasterization
{
VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME,
diff --git a/src/Vulkan/VkRenderPass.cpp b/src/Vulkan/VkRenderPass.cpp
index 914c1d7..0830709 100644
--- a/src/Vulkan/VkRenderPass.cpp
+++ b/src/Vulkan/VkRenderPass.cpp
@@ -16,6 +16,112 @@
#include "VkStringify.hpp"
#include <cstring>
+namespace {
+
+template<class T>
+size_t ComputeRequiredAllocationSizeT(const T *pCreateInfo)
+{
+ size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) + pCreateInfo->attachmentCount * sizeof(int) // first use
+ + pCreateInfo->attachmentCount * sizeof(uint32_t); // union of subpass view masks, per attachment
+ size_t subpassesSize = 0;
+ for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+ {
+ const auto &subpass = pCreateInfo->pSubpasses[i];
+ uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
+ if(subpass.pResolveAttachments)
+ {
+ nbAttachments += subpass.colorAttachmentCount;
+ }
+ if(subpass.pDepthStencilAttachment)
+ {
+ nbAttachments += 1;
+ }
+ subpassesSize += sizeof(VkSubpassDescription) +
+ sizeof(VkAttachmentReference) * nbAttachments +
+ sizeof(uint32_t) * subpass.preserveAttachmentCount +
+ sizeof(uint32_t); // view mask
+ }
+ size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+
+ return attachmentSize + subpassesSize + dependenciesSize;
+}
+
+template<class T>
+void CopySubpasses(VkSubpassDescription *dst, const T *src, uint32_t count)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ dst[i].flags = src[i].flags;
+ dst[i].pipelineBindPoint = src[i].pipelineBindPoint;
+ dst[i].inputAttachmentCount = src[i].inputAttachmentCount;
+ dst[i].pInputAttachments = nullptr;
+ dst[i].colorAttachmentCount = src[i].colorAttachmentCount;
+ dst[i].pColorAttachments = nullptr;
+ dst[i].pResolveAttachments = nullptr;
+ dst[i].pDepthStencilAttachment = nullptr;
+ dst[i].preserveAttachmentCount = src[i].preserveAttachmentCount;
+ dst[i].pPreserveAttachments = nullptr;
+ }
+}
+
+template<class T>
+void CopyAttachmentDescriptions(VkAttachmentDescription *dst, const T *src, uint32_t count)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ dst[i].flags = src[i].flags;
+ dst[i].format = src[i].format;
+ dst[i].samples = src[i].samples;
+ dst[i].loadOp = src[i].loadOp;
+ dst[i].storeOp = src[i].storeOp;
+ dst[i].stencilLoadOp = src[i].stencilLoadOp;
+ dst[i].stencilStoreOp = src[i].stencilStoreOp;
+ dst[i].initialLayout = src[i].initialLayout;
+ dst[i].finalLayout = src[i].finalLayout;
+ }
+}
+
+template<class T>
+void CopyAttachmentReferences(VkAttachmentReference *dst, const T *src, uint32_t count)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ dst[i].attachment = src[i].attachment;
+ dst[i].layout = src[i].layout;
+ }
+}
+
+template<class T>
+void CopySubpassDependencies(VkSubpassDependency *dst, const T *src, uint32_t count)
+{
+ for(uint32_t i = 0; i < count; ++i)
+ {
+ dst[i].srcSubpass = src[i].srcSubpass;
+ dst[i].dstSubpass = src[i].dstSubpass;
+ dst[i].srcStageMask = src[i].srcStageMask;
+ dst[i].dstStageMask = src[i].dstStageMask;
+ dst[i].srcAccessMask = src[i].srcAccessMask;
+ dst[i].dstAccessMask = src[i].dstAccessMask;
+ dst[i].dependencyFlags = src[i].dependencyFlags;
+ }
+}
+
+bool GetViewMasks(const VkRenderPassCreateInfo *pCreateInfo, uint32_t *masks)
+{
+ return false;
+}
+
+bool GetViewMasks(const VkRenderPassCreateInfo2KHR *pCreateInfo, uint32_t *masks)
+{
+ for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
+ {
+ masks[i] = pCreateInfo->pSubpasses[i].viewMask;
+ }
+ return true;
+}
+
+} // namespace
+
namespace vk {
RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem)
@@ -23,6 +129,25 @@
, subpassCount(pCreateInfo->subpassCount)
, dependencyCount(pCreateInfo->dependencyCount)
{
+ init(pCreateInfo, mem);
+}
+
+RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem)
+ : attachmentCount(pCreateInfo->attachmentCount)
+ , subpassCount(pCreateInfo->subpassCount)
+ , dependencyCount(pCreateInfo->dependencyCount)
+{
+ init(pCreateInfo, mem);
+ // Note: the init function above ignores:
+ // - pCorrelatedViewMasks: This provides a potential performance optimization
+ // - VkAttachmentReference2::aspectMask : This specifies which aspects may be used
+ // - VkSubpassDependency2::viewOffset : This is the same as VkRenderPassMultiviewCreateInfo::pViewOffsets, which is currently ignored
+ // - Any pNext pointer in VkRenderPassCreateInfo2KHR's internal structures
+}
+
+template<class T>
+void RenderPass::init(const T *pCreateInfo, void *mem)
+{
char *hostMemory = reinterpret_cast<char *>(mem);
// subpassCount must be greater than 0
@@ -30,16 +155,16 @@
size_t subpassesSize = pCreateInfo->subpassCount * sizeof(VkSubpassDescription);
subpasses = reinterpret_cast<VkSubpassDescription *>(hostMemory);
- memcpy(subpasses, pCreateInfo->pSubpasses, subpassesSize);
+ CopySubpasses(subpasses, pCreateInfo->pSubpasses, pCreateInfo->subpassCount);
hostMemory += subpassesSize;
uint32_t *masks = reinterpret_cast<uint32_t *>(hostMemory);
- hostMemory += pCreateInfo->subpassCount * sizeof(uint32_t);
+ hostMemory += subpassCount * sizeof(uint32_t);
- if(pCreateInfo->attachmentCount > 0)
+ if(attachmentCount > 0)
{
size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription);
attachments = reinterpret_cast<VkAttachmentDescription *>(hostMemory);
- memcpy(attachments, pCreateInfo->pAttachments, attachmentSize);
+ CopyAttachmentDescriptions(attachments, pCreateInfo->pAttachments, pCreateInfo->attachmentCount);
hostMemory += attachmentSize;
size_t firstUseSize = pCreateInfo->attachmentCount * sizeof(int);
@@ -70,7 +195,9 @@
masks[i] = multiviewCreateInfo->pViewMasks[i];
// This is now a multiview renderpass, so make the masks available
if(masks[i])
+ {
viewMasks = masks;
+ }
}
break;
@@ -83,22 +210,28 @@
extensionCreateInfo = extensionCreateInfo->pNext;
}
+ if(!viewMasks && (GetViewMasks(pCreateInfo, masks)))
+ {
+ for(auto i = 0u; i < pCreateInfo->subpassCount; i++)
+ {
+ if(masks[i])
+ {
+ viewMasks = masks;
+ }
+ }
+ }
+
// Deep copy subpasses
for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
{
const auto &subpass = pCreateInfo->pSubpasses[i];
- subpasses[i].pInputAttachments = nullptr;
- subpasses[i].pColorAttachments = nullptr;
- subpasses[i].pResolveAttachments = nullptr;
- subpasses[i].pDepthStencilAttachment = nullptr;
- subpasses[i].pPreserveAttachments = nullptr;
if(subpass.inputAttachmentCount > 0)
{
size_t inputAttachmentsSize = subpass.inputAttachmentCount * sizeof(VkAttachmentReference);
subpasses[i].pInputAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
- memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
- pCreateInfo->pSubpasses[i].pInputAttachments, inputAttachmentsSize);
+ CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pInputAttachments),
+ pCreateInfo->pSubpasses[i].pInputAttachments, subpass.inputAttachmentCount);
hostMemory += inputAttachmentsSize;
for(auto j = 0u; j < subpasses[i].inputAttachmentCount; j++)
@@ -112,15 +245,15 @@
{
size_t colorAttachmentsSize = subpass.colorAttachmentCount * sizeof(VkAttachmentReference);
subpasses[i].pColorAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
- memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
- subpass.pColorAttachments, colorAttachmentsSize);
+ CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pColorAttachments),
+ subpass.pColorAttachments, subpass.colorAttachmentCount);
hostMemory += colorAttachmentsSize;
if(subpass.pResolveAttachments)
{
subpasses[i].pResolveAttachments = reinterpret_cast<VkAttachmentReference *>(hostMemory);
- memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
- subpass.pResolveAttachments, colorAttachmentsSize);
+ CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pResolveAttachments),
+ subpass.pResolveAttachments, subpass.colorAttachmentCount);
hostMemory += colorAttachmentsSize;
}
@@ -137,8 +270,8 @@
if(subpass.pDepthStencilAttachment)
{
subpasses[i].pDepthStencilAttachment = reinterpret_cast<VkAttachmentReference *>(hostMemory);
- memcpy(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
- subpass.pDepthStencilAttachment, sizeof(VkAttachmentReference));
+ CopyAttachmentReferences(const_cast<VkAttachmentReference *>(subpasses[i].pDepthStencilAttachment),
+ subpass.pDepthStencilAttachment, 1);
hostMemory += sizeof(VkAttachmentReference);
if(subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)
@@ -149,8 +282,10 @@
{
size_t preserveAttachmentSize = subpass.preserveAttachmentCount * sizeof(uint32_t);
subpasses[i].pPreserveAttachments = reinterpret_cast<uint32_t *>(hostMemory);
- memcpy(const_cast<uint32_t *>(subpasses[i].pPreserveAttachments),
- pCreateInfo->pSubpasses[i].pPreserveAttachments, preserveAttachmentSize);
+ for(uint32_t j = 0u; j < subpass.preserveAttachmentCount; j++)
+ {
+ const_cast<uint32_t *>(subpasses[i].pPreserveAttachments)[j] = pCreateInfo->pSubpasses[i].pPreserveAttachments[j];
+ }
hostMemory += preserveAttachmentSize;
for(auto j = 0u; j < subpasses[i].preserveAttachmentCount; j++)
@@ -163,9 +298,8 @@
if(pCreateInfo->dependencyCount > 0)
{
- size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
- memcpy(dependencies, pCreateInfo->pDependencies, dependenciesSize);
+ CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
}
}
@@ -176,29 +310,12 @@
size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo)
{
- size_t attachmentSize = pCreateInfo->attachmentCount * sizeof(VkAttachmentDescription) + pCreateInfo->attachmentCount * sizeof(int) // first use
- + pCreateInfo->attachmentCount * sizeof(uint32_t); // union of subpass view masks, per attachment
- size_t subpassesSize = 0;
- for(uint32_t i = 0; i < pCreateInfo->subpassCount; ++i)
- {
- const auto &subpass = pCreateInfo->pSubpasses[i];
- uint32_t nbAttachments = subpass.inputAttachmentCount + subpass.colorAttachmentCount;
- if(subpass.pResolveAttachments)
- {
- nbAttachments += subpass.colorAttachmentCount;
- }
- if(subpass.pDepthStencilAttachment)
- {
- nbAttachments += 1;
- }
- subpassesSize += sizeof(VkSubpassDescription) +
- sizeof(VkAttachmentReference) * nbAttachments +
- sizeof(uint32_t) * subpass.preserveAttachmentCount +
- sizeof(uint32_t); // view mask
- }
- size_t dependenciesSize = pCreateInfo->dependencyCount * sizeof(VkSubpassDependency);
+ return ComputeRequiredAllocationSizeT(pCreateInfo);
+}
- return attachmentSize + subpassesSize + dependenciesSize;
+size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
+{
+ return ComputeRequiredAllocationSizeT(pCreateInfo);
}
void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
diff --git a/src/Vulkan/VkRenderPass.hpp b/src/Vulkan/VkRenderPass.hpp
index 2c2fe85..3f02f6b 100644
--- a/src/Vulkan/VkRenderPass.hpp
+++ b/src/Vulkan/VkRenderPass.hpp
@@ -25,9 +25,11 @@
{
public:
RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem);
+ RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem);
void destroy(const VkAllocationCallbacks *pAllocator);
static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *pCreateInfo);
+ static size_t ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo);
void getRenderAreaGranularity(VkExtent2D *pGranularity) const;
@@ -93,6 +95,8 @@
uint32_t *attachmentViewMasks = nullptr;
void MarkFirstUse(int attachment, int subpass);
+ template<class T>
+ void init(const T *pCreateInfo, void *mem);
};
static inline RenderPass *Cast(VkRenderPass object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 1d93641..beddc54 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -165,6 +165,92 @@
(void)doOnce;
}
+template<class T>
+void ValidateRenderPassPNextChain(VkDevice device, const T *pCreateInfo)
+{
+ const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
+
+ while(extensionCreateInfo)
+ {
+ switch(extensionCreateInfo->sType)
+ {
+ case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
+ {
+ const VkRenderPassInputAttachmentAspectCreateInfo *inputAttachmentAspectCreateInfo = reinterpret_cast<const VkRenderPassInputAttachmentAspectCreateInfo *>(extensionCreateInfo);
+
+ for(uint32_t i = 0; i < inputAttachmentAspectCreateInfo->aspectReferenceCount; i++)
+ {
+ const auto &aspectReference = inputAttachmentAspectCreateInfo->pAspectReferences[i];
+ ASSERT(aspectReference.subpass < pCreateInfo->subpassCount);
+ const auto &subpassDescription = pCreateInfo->pSubpasses[aspectReference.subpass];
+ ASSERT(aspectReference.inputAttachmentIndex < subpassDescription.inputAttachmentCount);
+ const auto &attachmentReference = subpassDescription.pInputAttachments[aspectReference.inputAttachmentIndex];
+ if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
+ {
+ // If the pNext chain includes an instance of VkRenderPassInputAttachmentAspectCreateInfo, for any
+ // element of the pInputAttachments member of any element of pSubpasses where the attachment member
+ // is not VK_ATTACHMENT_UNUSED, the aspectMask member of the corresponding element of
+ // VkRenderPassInputAttachmentAspectCreateInfo::pAspectReferences must only include aspects that are
+ // present in images of the format specified by the element of pAttachments at attachment
+ vk::Format format(pCreateInfo->pAttachments[attachmentReference.attachment].format);
+ bool isDepth = format.isDepth();
+ bool isStencil = format.isStencil();
+ ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) || (!isDepth && !isStencil));
+ ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || isDepth);
+ ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) || isStencil);
+ }
+ }
+ }
+ break;
+ case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
+ {
+ const VkRenderPassMultiviewCreateInfo *multiviewCreateInfo = reinterpret_cast<const VkRenderPassMultiviewCreateInfo *>(extensionCreateInfo);
+ ASSERT((multiviewCreateInfo->subpassCount == 0) || (multiviewCreateInfo->subpassCount == pCreateInfo->subpassCount));
+ ASSERT((multiviewCreateInfo->dependencyCount == 0) || (multiviewCreateInfo->dependencyCount == pCreateInfo->dependencyCount));
+
+ bool zeroMask = (multiviewCreateInfo->pViewMasks[0] == 0);
+ for(uint32_t i = 1; i < multiviewCreateInfo->subpassCount; i++)
+ {
+ ASSERT((multiviewCreateInfo->pViewMasks[i] == 0) == zeroMask);
+ }
+
+ if(zeroMask)
+ {
+ ASSERT(multiviewCreateInfo->correlationMaskCount == 0);
+ }
+
+ for(uint32_t i = 0; i < multiviewCreateInfo->dependencyCount; i++)
+ {
+ const auto &dependency = pCreateInfo->pDependencies[i];
+ if(multiviewCreateInfo->pViewOffsets[i] != 0)
+ {
+ ASSERT(dependency.srcSubpass != dependency.dstSubpass);
+ ASSERT(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT);
+ }
+ if(zeroMask)
+ {
+ ASSERT(!(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT));
+ }
+ }
+
+ // If the pNext chain includes an instance of VkRenderPassMultiviewCreateInfo,
+ // each element of its pViewMask member must not include a bit at a position
+ // greater than the value of VkPhysicalDeviceLimits::maxFramebufferLayers
+ // pViewMask is a 32 bit value. If maxFramebufferLayers > 32, it's impossible
+ // for pViewMask to contain a bit at an illegal position
+ // Note: Verify pViewMask values instead if we hit this assert
+ ASSERT(vk::Cast(device)->getPhysicalDevice()->getProperties().limits.maxFramebufferLayers >= 32);
+ }
+ break;
+ default:
+ WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
+ break;
+ }
+
+ extensionCreateInfo = extensionCreateInfo->pNext;
+ }
+}
+
} // namespace
extern "C" {
@@ -212,6 +298,7 @@
// Vulkan 1.1 promoted extensions
{ VK_KHR_16BIT_STORAGE_EXTENSION_NAME, VK_KHR_16BIT_STORAGE_SPEC_VERSION },
{ VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_BIND_MEMORY_2_SPEC_VERSION },
+ { VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION },
{ VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION },
{ VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION },
{ VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_KHR_DEVICE_GROUP_SPEC_VERSION },
@@ -1884,88 +1971,24 @@
UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
}
- const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
+ ValidateRenderPassPNextChain(device, pCreateInfo);
- while(extensionCreateInfo)
+ return vk::RenderPass::Create(pAllocator, pCreateInfo, pRenderPass);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2KHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass)
+{
+ TRACE("(VkDevice device = %p, const VkRenderPassCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkRenderPass* pRenderPass = %p)",
+ device, pCreateInfo, pAllocator, pRenderPass);
+
+ if(pCreateInfo->flags != 0)
{
- switch(extensionCreateInfo->sType)
- {
- case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
- {
- const VkRenderPassInputAttachmentAspectCreateInfo *inputAttachmentAspectCreateInfo = reinterpret_cast<const VkRenderPassInputAttachmentAspectCreateInfo *>(extensionCreateInfo);
-
- for(uint32_t i = 0; i < inputAttachmentAspectCreateInfo->aspectReferenceCount; i++)
- {
- const VkInputAttachmentAspectReference &aspectReference = inputAttachmentAspectCreateInfo->pAspectReferences[i];
- ASSERT(aspectReference.subpass < pCreateInfo->subpassCount);
- const VkSubpassDescription &subpassDescription = pCreateInfo->pSubpasses[aspectReference.subpass];
- ASSERT(aspectReference.inputAttachmentIndex < subpassDescription.inputAttachmentCount);
- const VkAttachmentReference &attachmentReference = subpassDescription.pInputAttachments[aspectReference.inputAttachmentIndex];
- if(attachmentReference.attachment != VK_ATTACHMENT_UNUSED)
- {
- // If the pNext chain includes an instance of VkRenderPassInputAttachmentAspectCreateInfo, for any
- // element of the pInputAttachments member of any element of pSubpasses where the attachment member
- // is not VK_ATTACHMENT_UNUSED, the aspectMask member of the corresponding element of
- // VkRenderPassInputAttachmentAspectCreateInfo::pAspectReferences must only include aspects that are
- // present in images of the format specified by the element of pAttachments at attachment
- vk::Format format(pCreateInfo->pAttachments[attachmentReference.attachment].format);
- bool isDepth = format.isDepth();
- bool isStencil = format.isStencil();
- ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) || (!isDepth && !isStencil));
- ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || isDepth);
- ASSERT(!(aspectReference.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) || isStencil);
- }
- }
- }
- break;
- case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
- {
- const VkRenderPassMultiviewCreateInfo *multiviewCreateInfo = reinterpret_cast<const VkRenderPassMultiviewCreateInfo *>(extensionCreateInfo);
- ASSERT((multiviewCreateInfo->subpassCount == 0) || (multiviewCreateInfo->subpassCount == pCreateInfo->subpassCount));
- ASSERT((multiviewCreateInfo->dependencyCount == 0) || (multiviewCreateInfo->dependencyCount == pCreateInfo->dependencyCount));
-
- bool zeroMask = (multiviewCreateInfo->pViewMasks[0] == 0);
- for(uint32_t i = 1; i < multiviewCreateInfo->subpassCount; i++)
- {
- ASSERT((multiviewCreateInfo->pViewMasks[i] == 0) == zeroMask);
- }
-
- if(zeroMask)
- {
- ASSERT(multiviewCreateInfo->correlationMaskCount == 0);
- }
-
- for(uint32_t i = 0; i < multiviewCreateInfo->dependencyCount; i++)
- {
- const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
- if(multiviewCreateInfo->pViewOffsets[i] != 0)
- {
- ASSERT(dependency.srcSubpass != dependency.dstSubpass);
- ASSERT(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT);
- }
- if(zeroMask)
- {
- ASSERT(!(dependency.dependencyFlags & VK_DEPENDENCY_VIEW_LOCAL_BIT));
- }
- }
-
- // If the pNext chain includes an instance of VkRenderPassMultiviewCreateInfo,
- // each element of its pViewMask member must not include a bit at a position
- // greater than the value of VkPhysicalDeviceLimits::maxFramebufferLayers
- // pViewMask is a 32 bit value. If maxFramebufferLayers > 32, it's impossible
- // for pViewMask to contain a bit at an illegal position
- // Note: Verify pViewMask values instead if we hit this assert
- ASSERT(vk::Cast(device)->getPhysicalDevice()->getProperties().limits.maxFramebufferLayers >= 32);
- }
- break;
- default:
- WARN("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
- break;
- }
-
- extensionCreateInfo = extensionCreateInfo->pNext;
+ // Vulkan 1.2: "flags is reserved for future use." "flags must be 0"
+ UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
}
+ ValidateRenderPassPNextChain(device, pCreateInfo);
+
return vk::RenderPass::Create(pAllocator, pCreateInfo, pRenderPass);
}
@@ -2415,6 +2438,14 @@
vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, contents);
}
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
+{
+ TRACE("(VkCommandBuffer commandBuffer = %p, const VkRenderPassBeginInfo* pRenderPassBegin = %p, const VkSubpassBeginInfoKHR* pSubpassBeginInfo = %p)",
+ commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+
+ vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, pSubpassBeginInfo->contents);
+}
+
VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
{
TRACE("(VkCommandBuffer commandBuffer = %p, VkSubpassContents contents = %d)",
@@ -2423,6 +2454,14 @@
vk::Cast(commandBuffer)->nextSubpass(contents);
}
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const VkSubpassEndInfoKHR *pSubpassEndInfo)
+{
+ TRACE("(VkCommandBuffer commandBuffer = %p, const VkSubpassBeginInfoKHR* pSubpassBeginInfo = %p, const VkSubpassEndInfoKHR* pSubpassEndInfo = %p)",
+ commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
+
+ vk::Cast(commandBuffer)->nextSubpass(pSubpassBeginInfo->contents);
+}
+
VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
{
TRACE("(VkCommandBuffer commandBuffer = %p)", commandBuffer);
@@ -2430,6 +2469,13 @@
vk::Cast(commandBuffer)->endRenderPass();
}
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo)
+{
+ TRACE("(VkCommandBuffer commandBuffer = %p, const VkSubpassEndInfoKHR* pSubpassEndInfo = %p)", commandBuffer, pSubpassEndInfo);
+
+ vk::Cast(commandBuffer)->endRenderPass();
+}
+
VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
{
TRACE("(VkCommandBuffer commandBuffer = %p, uint32_t commandBufferCount = %d, const VkCommandBuffer* pCommandBuffers = %p)",