Commit c12c90bd by Sean Risser

Add VK_KHR_imageless_framebuffer

Under normal operations, a framebuffer is created with each VkImageView it will need to use. This extension allows users to specify a flag that tells the driver to wait until render pass begin time. The user must also request this feature during device creation, this behavior is not enabled by default. Bug: b/167223759 Tests: dEQP-VK.imageless_framebuffer.* Change-Id: I2be5cec4d8174e20372eb9e148a05034dd338341 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48488Tested-by: 's avatarSean Risser <srisser@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
parent 9c6e9a45
......@@ -1405,10 +1405,18 @@ void CommandBuffer::addCommand(Args &&... args)
}
void CommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents)
uint32_t clearValueCount, const VkClearValue *clearValues, VkSubpassContents contents,
const VkRenderPassAttachmentBeginInfo *attachmentInfo)
{
ASSERT(state == RECORDING);
if(attachmentInfo)
{
for(uint32_t i = 0; i < attachmentInfo->attachmentCount; i++)
{
framebuffer->setAttachment(vk::Cast(attachmentInfo->pAttachments[i]), i);
}
}
addCommand<::CmdBeginRenderPass>(renderPass, framebuffer, renderArea, clearValueCount, clearValues);
}
......
......@@ -61,7 +61,8 @@ public:
VkResult reset(VkCommandPoolResetFlags flags);
void beginRenderPass(RenderPass *renderPass, Framebuffer *framebuffer, VkRect2D renderArea,
uint32_t clearValueCount, const VkClearValue *pClearValues, VkSubpassContents contents);
uint32_t clearValueCount, const VkClearValue *pClearValues, VkSubpassContents contents,
const VkRenderPassAttachmentBeginInfo *attachmentBeginInfo);
void nextSubpass(VkSubpassContents contents);
void endRenderPass();
void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers);
......
......@@ -13,21 +13,54 @@
// limitations under the License.
#include "VkFramebuffer.hpp"
#include "VkImageView.hpp"
#include "VkRenderPass.hpp"
#include "VkStringify.hpp"
#include <memory.h>
#include <algorithm>
namespace vk {
Framebuffer::Framebuffer(const VkFramebufferCreateInfo *pCreateInfo, void *mem)
: attachmentCount(pCreateInfo->attachmentCount)
, attachments(reinterpret_cast<ImageView **>(mem))
: attachments(reinterpret_cast<ImageView **>(mem))
, extent{ pCreateInfo->width, pCreateInfo->height, pCreateInfo->layers }
{
for(uint32_t i = 0; i < attachmentCount; i++)
const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
const VkFramebufferAttachmentsCreateInfo *attachmentsCreateInfo = nullptr;
while(curInfo)
{
switch(curInfo->sType)
{
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
attachmentsCreateInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
break;
default:
LOG_TRAP("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
break;
}
curInfo = curInfo->pNext;
}
if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
{
attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
// If flags includes VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, the pNext chain **must**
// include a VkFramebufferAttachmentsCreateInfo.
ASSERT(attachmentsCreateInfo != nullptr);
attachmentCount = attachmentsCreateInfo->attachmentImageInfoCount;
for(uint32_t i = 0; i < attachmentCount; i++)
{
attachments[i] = nullptr;
}
}
else
{
attachmentCount = pCreateInfo->attachmentCount;
for(uint32_t i = 0; i < attachmentCount; i++)
{
attachments[i] = vk::Cast(pCreateInfo->pAttachments[i]);
}
}
}
......@@ -115,6 +148,13 @@ void Framebuffer::clearAttachment(const RenderPass *renderPass, uint32_t subpass
}
}
void Framebuffer::setAttachment(ImageView *imageView, uint32_t index)
{
ASSERT(index < attachmentCount);
ASSERT(attachments[index] == nullptr);
attachments[index] = imageView;
}
ImageView *Framebuffer::getAttachment(uint32_t index) const
{
return attachments[index];
......@@ -147,7 +187,32 @@ void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex)
size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo)
{
return pCreateInfo->attachmentCount * sizeof(void *);
const VkBaseInStructure *curInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
const VkFramebufferAttachmentsCreateInfo *attachmentsInfo = nullptr;
while(curInfo)
{
switch(curInfo->sType)
{
case VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO:
attachmentsInfo = reinterpret_cast<const VkFramebufferAttachmentsCreateInfo *>(curInfo);
break;
default:
LOG_TRAP("pFramebufferCreateInfo->pNext->sType = %s", vk::Stringify(curInfo->sType).c_str());
break;
}
curInfo = curInfo->pNext;
}
if(pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT)
{
ASSERT(attachmentsInfo != nullptr);
return attachmentsInfo->attachmentImageInfoCount * sizeof(void *);
}
else
{
return pCreateInfo->attachmentCount * sizeof(void *);
}
}
} // namespace vk
......@@ -32,6 +32,7 @@ public:
void clearAttachment(const RenderPass *renderPass, uint32_t subpassIndex, const VkClearAttachment &attachment, const VkClearRect &rect);
static size_t ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo);
void setAttachment(ImageView *imageView, uint32_t index);
ImageView *getAttachment(uint32_t index) const;
void resolve(const RenderPass *renderPass, uint32_t subpassIndex);
......
......@@ -226,6 +226,12 @@ static void getPhysicalDeviceVulkan11Features(T *features)
}
template<typename T>
static void getPhysicalDeviceImagelessFramebufferFeatures(T *features)
{
features->imagelessFramebuffer = VK_TRUE;
}
template<typename T>
static void getPhysicalDeviceVulkan12Features(T *features)
{
features->samplerMirrorClampToEdge = VK_FALSE;
......@@ -257,7 +263,7 @@ static void getPhysicalDeviceVulkan12Features(T *features)
features->runtimeDescriptorArray = VK_FALSE;
features->samplerFilterMinmax = VK_FALSE;
features->scalarBlockLayout = VK_FALSE;
features->imagelessFramebuffer = VK_FALSE;
getPhysicalDeviceImagelessFramebufferFeatures(features);
features->uniformBufferStandardLayout = VK_FALSE;
features->shaderSubgroupExtendedTypes = VK_FALSE;
getPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR(features);
......@@ -322,6 +328,9 @@ void PhysicalDevice::getFeatures2(VkPhysicalDeviceFeatures2 *features) const
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT:
getPhysicalDeviceProvokingVertexFeaturesEXT(reinterpret_cast<VkPhysicalDeviceProvokingVertexFeaturesEXT *>(curExtension));
break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES:
getPhysicalDeviceImagelessFramebufferFeatures(reinterpret_cast<VkPhysicalDeviceImagelessFramebufferFeatures *>(curExtension));
break;
default:
WARN("curExtension->pNext->sType = %s", vk::Stringify(curExtension->sType).c_str());
break;
......
......@@ -379,7 +379,9 @@ static const VkExtensionProperties deviceExtensionProperties[] = {
{ VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, VK_EXT_PROVOKING_VERTEX_SPEC_VERSION },
{ VK_GOOGLE_SAMPLER_FILTERING_PRECISION_EXTENSION_NAME, VK_GOOGLE_SAMPLER_FILTERING_PRECISION_SPEC_VERSION },
{ VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, VK_EXT_DEPTH_RANGE_UNRESTRICTED_SPEC_VERSION },
{ VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION }
// Vulkan 1.2 promoted extensions
{ VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION },
{ VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME, VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION }
};
static bool hasExtension(const char *extensionName, const VkExtensionProperties *extensionProperties, uint32_t extensionPropertiesCount)
......@@ -828,6 +830,13 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, c
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT:
ASSERT(!hasDeviceExtension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME));
break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR:
{
const VkPhysicalDeviceImagelessFramebufferFeaturesKHR *imagelessFramebufferFeatures = reinterpret_cast<const VkPhysicalDeviceImagelessFramebufferFeaturesKHR *>(extensionCreateInfo);
// Always provide Imageless Framebuffers
(void)imagelessFramebufferFeatures->imagelessFramebuffer;
}
break;
default:
// "the [driver] must skip over, without processing (other than reading the sType and pNext members) any structures in the chain with sType values not defined by [supported extenions]"
LOG_TRAP("pCreateInfo->pNext sType = %s", vk::Stringify(extensionCreateInfo->sType).c_str());
......@@ -2145,18 +2154,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice device, const VkFram
TRACE("(VkDevice device = %p, const VkFramebufferCreateInfo* pCreateInfo = %p, const VkAllocationCallbacks* pAllocator = %p, VkFramebuffer* pFramebuffer = %p)",
device, pCreateInfo, pAllocator, pFramebuffer);
if(pCreateInfo->flags != 0)
{
UNSUPPORTED("pCreateInfo->flags %d", int(pCreateInfo->flags));
}
auto *nextInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
while(nextInfo)
{
LOG_TRAP("pCreateInfo->pNext sType = %s", vk::Stringify(nextInfo->sType).c_str());
nextInfo = nextInfo->pNext;
}
return vk::Framebuffer::Create(pAllocator, pCreateInfo, pFramebuffer);
}
......@@ -2626,6 +2623,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, c
commandBuffer, pRenderPassBegin, contents);
const VkBaseInStructure *renderPassBeginInfo = reinterpret_cast<const VkBaseInStructure *>(pRenderPassBegin->pNext);
const VkRenderPassAttachmentBeginInfo *attachmentBeginInfo = nullptr;
while(renderPassBeginInfo)
{
switch(renderPassBeginInfo->sType)
......@@ -2635,6 +2633,9 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, c
// in order to distribute rendering between multiple physical devices.
// SwiftShader only has a single physical device, so this extension does nothing in this case.
break;
case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO:
attachmentBeginInfo = reinterpret_cast<const VkRenderPassAttachmentBeginInfo *>(renderPassBeginInfo);
break;
default:
LOG_TRAP("pRenderPassBegin->pNext sType = %s", vk::Stringify(renderPassBeginInfo->sType).c_str());
break;
......@@ -2643,7 +2644,7 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, c
renderPassBeginInfo = renderPassBeginInfo->pNext;
}
vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, contents);
vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, contents, attachmentBeginInfo);
}
VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, const VkSubpassBeginInfoKHR *pSubpassBeginInfo)
......@@ -2651,7 +2652,29 @@ VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffe
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);
const VkBaseInStructure *renderPassBeginInfo = reinterpret_cast<const VkBaseInStructure *>(pRenderPassBegin->pNext);
const VkRenderPassAttachmentBeginInfo *attachmentBeginInfo = nullptr;
while(renderPassBeginInfo)
{
switch(renderPassBeginInfo->sType)
{
case VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO:
// This extension controls which render area is used on which physical device,
// in order to distribute rendering between multiple physical devices.
// SwiftShader only has a single physical device, so this extension does nothing in this case.
break;
case VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO:
attachmentBeginInfo = reinterpret_cast<const VkRenderPassAttachmentBeginInfo *>(renderPassBeginInfo);
break;
default:
LOG_TRAP("pRenderPassBegin->pNext sType = %s", vk::Stringify(renderPassBeginInfo->sType).c_str());
break;
}
renderPassBeginInfo = renderPassBeginInfo->pNext;
}
vk::Cast(commandBuffer)->beginRenderPass(vk::Cast(pRenderPassBegin->renderPass), vk::Cast(pRenderPassBegin->framebuffer), pRenderPassBegin->renderArea, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues, pSubpassBeginInfo->contents, attachmentBeginInfo);
}
VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment