Implement VK_KHR_depth_stencil_resolve

This extension allows users to pass depthstencil attachments that vkCmdResolveImage will resolve to in addition to its other resolve operations. Only the mandatory resolve modes "VK_RESOLVE_MODE_SAMPLE_ZERO_BIT" and "VK_RESOLVE_MODE_NONE" are supported. It's trivial to support both independent resolve modes since we must resolve depth and stencil attachments separately due to how depth and stencil attachments are stored internally. Change-Id: I0f8ff7cddca5f5acbac1d991b11f0a4447956784 Bug: b/167558951 Test: dEQP-VK.renderpass2.depth_stencil_resolve.* Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48808Tested-by: 's avatarSean Risser <srisser@google.com> Commit-Queue: Sean Risser <srisser@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
parent 8642467d
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "System/Memory.hpp" #include "System/Memory.hpp"
#include "Vulkan/VkBuffer.hpp" #include "Vulkan/VkBuffer.hpp"
#include "Vulkan/VkImage.hpp" #include "Vulkan/VkImage.hpp"
#include "Vulkan/VkImageView.hpp"
#include <utility> #include <utility>
...@@ -1880,6 +1881,88 @@ void Blitter::blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkF ...@@ -1880,6 +1881,88 @@ void Blitter::blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkF
dst->contentsChanged(dstSubresRange); dst->contentsChanged(dstSubresRange);
} }
static void resolveDepth(const vk::ImageView *src, vk::ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsrDesc)
{
if(dsrDesc.depthResolveMode == VK_RESOLVE_MODE_NONE)
{
return;
}
vk::Format format = src->getFormat(VK_IMAGE_ASPECT_DEPTH_BIT);
VkExtent2D extent = src->getMipLevelExtent(0, VK_IMAGE_ASPECT_DEPTH_BIT);
int width = extent.width;
int height = extent.height;
int pitch = src->rowPitchBytes(VK_IMAGE_ASPECT_DEPTH_BIT, 0);
// To support other resolve modes, get the slice bytes and get a pointer to each sample plane.
// Then modify the loop below to include logic for handling each new mode.
uint8_t *source = (uint8_t *)src->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0);
uint8_t *dest = (uint8_t *)dst->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_DEPTH_BIT, 0, 0);
size_t formatSize = format.bytes();
// TODO(b/167558951) support other resolve modes.
ASSERT(dsrDesc.depthResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
for(int y = 0; y < height; y++)
{
memcpy(dest, source, formatSize * width);
source += pitch;
dest += pitch;
}
dst->contentsChanged();
}
static void resolveStencil(const vk::ImageView *src, vk::ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsrDesc)
{
if(dsrDesc.stencilResolveMode == VK_RESOLVE_MODE_NONE)
{
return;
}
VkExtent2D extent = src->getMipLevelExtent(0, VK_IMAGE_ASPECT_STENCIL_BIT);
int width = extent.width;
int height = extent.height;
int pitch = src->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
// To support other resolve modes, use src->slicePitchBytes() and get a pointer to each sample's slice.
// Then modify the loop below to include logic for handling each new mode.
uint8_t *source = reinterpret_cast<uint8_t *>(src->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0));
uint8_t *dest = reinterpret_cast<uint8_t *>(dst->getOffsetPointer({ 0, 0, 0 }, VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0));
// TODO(b/167558951) support other resolve modes.
ASSERT(dsrDesc.stencilResolveMode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT);
for(int y = 0; y < height; y++)
{
// Stencil is always 8 bits, so the width of the resource we're resolving is
// the number of bytes in each row we need to copy during for SAMPLE_ZERO
memcpy(dest, source, width);
source += pitch;
dest += pitch;
}
dst->contentsChanged();
}
void Blitter::resolveDepthStencil(const vk::ImageView *src, vk::ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsrDesc)
{
VkImageSubresourceRange srcRange = src->getSubresourceRange();
VkImageSubresourceRange dstRange = src->getSubresourceRange();
ASSERT(src->getFormat() == dst->getFormat());
ASSERT(srcRange.layerCount == 1 && dstRange.layerCount == 1);
ASSERT(srcRange.aspectMask == dstRange.aspectMask);
if(srcRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
{
resolveDepth(src, dst, dsrDesc);
}
if(srcRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
{
resolveStencil(src, dst, dsrDesc);
}
}
void Blitter::resolve(const vk::Image *src, vk::Image *dst, VkImageResolve region) void Blitter::resolve(const vk::Image *src, vk::Image *dst, VkImageResolve region)
{ {
// "The aspectMask member of srcSubresource and dstSubresource must only contain VK_IMAGE_ASPECT_COLOR_BIT" // "The aspectMask member of srcSubresource and dstSubresource must only contain VK_IMAGE_ASPECT_COLOR_BIT"
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
namespace vk { namespace vk {
class Image; class Image;
class ImageView;
class Buffer; class Buffer;
} // namespace vk } // namespace vk
...@@ -145,6 +146,7 @@ public: ...@@ -145,6 +146,7 @@ public:
void blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter); void blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter);
void resolve(const vk::Image *src, vk::Image *dst, VkImageResolve region); void resolve(const vk::Image *src, vk::Image *dst, VkImageResolve region);
void resolveDepthStencil(const vk::ImageView *src, vk::ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsrDesc);
void copy(const vk::Image *src, uint8_t *dst, unsigned int dstPitch); void copy(const vk::Image *src, uint8_t *dst, unsigned int dstPitch);
void updateBorders(vk::Image *image, const VkImageSubresource &subresource); void updateBorders(vk::Image *image, const VkImageSubresource &subresource);
......
...@@ -183,6 +183,17 @@ void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex) ...@@ -183,6 +183,17 @@ void Framebuffer::resolve(const RenderPass *renderPass, uint32_t subpassIndex)
} }
} }
} }
if(renderPass->hasDepthStencilResolve() && subpass.pDepthStencilAttachment != nullptr)
{
VkSubpassDescriptionDepthStencilResolve dsResolve = renderPass->getSubpassDepthStencilResolve(subpassIndex);
uint32_t depthStencilAttachment = subpass.pDepthStencilAttachment->attachment;
if(depthStencilAttachment != VK_ATTACHMENT_UNUSED)
{
ImageView *imageView = attachments[depthStencilAttachment];
imageView->resolveDepthStencil(attachments[dsResolve.pDepthStencilResolveAttachment->attachment], dsResolve);
}
}
} }
size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo) size_t Framebuffer::ComputeRequiredAllocationSize(const VkFramebufferCreateInfo *pCreateInfo)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "VkBuffer.hpp" #include "VkBuffer.hpp"
#include "VkDevice.hpp" #include "VkDevice.hpp"
#include "VkDeviceMemory.hpp" #include "VkDeviceMemory.hpp"
#include "VkImageView.hpp"
#include "VkStringify.hpp" #include "VkStringify.hpp"
#include "Device/ASTC_Decoder.hpp" #include "Device/ASTC_Decoder.hpp"
#include "Device/BC_Decoder.hpp" #include "Device/BC_Decoder.hpp"
...@@ -992,6 +993,11 @@ void Image::resolveTo(Image *dstImage, const VkImageResolve &region) const ...@@ -992,6 +993,11 @@ void Image::resolveTo(Image *dstImage, const VkImageResolve &region) const
device->getBlitter()->resolve(this, dstImage, region); device->getBlitter()->resolve(this, dstImage, region);
} }
void Image::resolveDepthStencilTo(const ImageView *src, ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsResolve) const
{
device->getBlitter()->resolveDepthStencil(src, dst, dsResolve);
}
VkFormat Image::getClearFormat() const VkFormat Image::getClearFormat() const
{ {
// Set the proper format for the clear value, as described here: // Set the proper format for the clear value, as described here:
......
...@@ -31,6 +31,7 @@ namespace vk { ...@@ -31,6 +31,7 @@ namespace vk {
class Buffer; class Buffer;
class Device; class Device;
class DeviceMemory; class DeviceMemory;
class ImageView;
#ifdef __ANDROID__ #ifdef __ANDROID__
struct BackingMemory struct BackingMemory
...@@ -65,6 +66,7 @@ public: ...@@ -65,6 +66,7 @@ public:
void blitTo(Image *dstImage, const VkImageBlit &region, VkFilter filter) const; void blitTo(Image *dstImage, const VkImageBlit &region, VkFilter filter) const;
void copyTo(uint8_t *dst, unsigned int dstPitch) const; void copyTo(uint8_t *dst, unsigned int dstPitch) const;
void resolveTo(Image *dstImage, const VkImageResolve &region) const; void resolveTo(Image *dstImage, const VkImageResolve &region) const;
void resolveDepthStencilTo(const ImageView *src, ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve) const;
void clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange); void clear(const VkClearValue &clearValue, const vk::Format &viewFormat, const VkRect2D &renderArea, const VkImageSubresourceRange &subresourceRange);
void clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange); void clear(const VkClearColorValue &color, const VkImageSubresourceRange &subresourceRange);
void clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange); void clear(const VkClearDepthStencilValue &color, const VkImageSubresourceRange &subresourceRange);
......
...@@ -262,6 +262,17 @@ void ImageView::resolveWithLayerMask(ImageView *resolveAttachment, uint32_t laye ...@@ -262,6 +262,17 @@ void ImageView::resolveWithLayerMask(ImageView *resolveAttachment, uint32_t laye
} }
} }
void ImageView::resolveDepthStencil(ImageView *resolveAttachment, const VkSubpassDescriptionDepthStencilResolve &dsResolve)
{
ASSERT(subresourceRange.levelCount == 1 && resolveAttachment->subresourceRange.levelCount == 1);
if((subresourceRange.layerCount != 1) || (resolveAttachment->subresourceRange.layerCount != 1))
{
UNIMPLEMENTED("b/148242443: layerCount != 1"); // FIXME(b/148242443)
}
image->resolveDepthStencilTo(this, resolveAttachment, dsResolve);
}
const Image *ImageView::getImage(Usage usage) const const Image *ImageView::getImage(Usage usage) const
{ {
switch(usage) switch(usage)
...@@ -310,6 +321,13 @@ VkExtent2D ImageView::getMipLevelExtent(uint32_t mipLevel) const ...@@ -310,6 +321,13 @@ VkExtent2D ImageView::getMipLevelExtent(uint32_t mipLevel) const
return { extent.width, extent.height }; return { extent.width, extent.height };
} }
VkExtent2D ImageView::getMipLevelExtent(uint32_t mipLevel, VkImageAspectFlagBits aspect) const
{
VkExtent3D extent = image->getMipLevelExtent(aspect, subresourceRange.baseMipLevel + mipLevel);
return { extent.width, extent.height };
}
int ImageView::getDepthOrLayerCount(uint32_t mipLevel) const int ImageView::getDepthOrLayerCount(uint32_t mipLevel) const
{ {
VkExtent3D extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask), VkExtent3D extent = image->getMipLevelExtent(static_cast<VkImageAspectFlagBits>(subresourceRange.aspectMask),
......
...@@ -79,6 +79,7 @@ public: ...@@ -79,6 +79,7 @@ public:
void resolve(ImageView *resolveAttachment); void resolve(ImageView *resolveAttachment);
void resolve(ImageView *resolveAttachment, int layer); void resolve(ImageView *resolveAttachment, int layer);
void resolveWithLayerMask(ImageView *resolveAttachment, uint32_t layerMask); void resolveWithLayerMask(ImageView *resolveAttachment, uint32_t layerMask);
void resolveDepthStencil(ImageView *resolveAttachment, const VkSubpassDescriptionDepthStencilResolve &dsResolve);
VkImageViewType getType() const { return viewType; } VkImageViewType getType() const { return viewType; }
Format getFormat(Usage usage = RAW) const; Format getFormat(Usage usage = RAW) const;
...@@ -88,6 +89,7 @@ public: ...@@ -88,6 +89,7 @@ public:
int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const; int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const; int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const;
VkExtent2D getMipLevelExtent(uint32_t mipLevel) const; VkExtent2D getMipLevelExtent(uint32_t mipLevel) const;
VkExtent2D getMipLevelExtent(uint32_t mipLevel, VkImageAspectFlagBits aspect) const;
int getDepthOrLayerCount(uint32_t mipLevel) const; int getDepthOrLayerCount(uint32_t mipLevel) const;
int getSampleCount() const int getSampleCount() const
......
...@@ -838,8 +838,8 @@ static void getDepthStencilResolveProperties(T *properties) ...@@ -838,8 +838,8 @@ static void getDepthStencilResolveProperties(T *properties)
{ {
properties->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE; properties->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE;
properties->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE; properties->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_NONE;
properties->independentResolveNone = VK_FALSE; properties->independentResolveNone = VK_TRUE;
properties->independentResolve = VK_FALSE; properties->independentResolve = VK_TRUE;
} }
void PhysicalDevice::getProperties(VkPhysicalDeviceDepthStencilResolveProperties *properties) const void PhysicalDevice::getProperties(VkPhysicalDeviceDepthStencilResolveProperties *properties) const
......
...@@ -129,7 +129,7 @@ RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem) ...@@ -129,7 +129,7 @@ RenderPass::RenderPass(const VkRenderPassCreateInfo *pCreateInfo, void *mem)
, subpassCount(pCreateInfo->subpassCount) , subpassCount(pCreateInfo->subpassCount)
, dependencyCount(pCreateInfo->dependencyCount) , dependencyCount(pCreateInfo->dependencyCount)
{ {
init(pCreateInfo, mem); init(pCreateInfo, &mem);
} }
RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem) RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem)
...@@ -137,18 +137,76 @@ RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem) ...@@ -137,18 +137,76 @@ RenderPass::RenderPass(const VkRenderPassCreateInfo2KHR *pCreateInfo, void *mem)
, subpassCount(pCreateInfo->subpassCount) , subpassCount(pCreateInfo->subpassCount)
, dependencyCount(pCreateInfo->dependencyCount) , dependencyCount(pCreateInfo->dependencyCount)
{ {
init(pCreateInfo, mem); init(pCreateInfo, &mem);
// Note: the init function above ignores: // Note: the init function above ignores:
// - pCorrelatedViewMasks: This provides a potential performance optimization // - pCorrelatedViewMasks: This provides a potential performance optimization
// - VkAttachmentReference2::aspectMask : This specifies which aspects may be used // - VkAttachmentReference2::aspectMask : This specifies which aspects may be used
// - VkSubpassDependency2::viewOffset : This is the same as VkRenderPassMultiviewCreateInfo::pViewOffsets, which is currently ignored // - VkSubpassDependency2::viewOffset : This is the same as VkRenderPassMultiviewCreateInfo::pViewOffsets, which is currently ignored
// - Any pNext pointer in VkRenderPassCreateInfo2KHR's internal structures // - Any pNext pointer in VkRenderPassCreateInfo2KHR's internal structures
char *hostMemory = reinterpret_cast<char *>(mem);
// Handle the extensions in each subpass
for(uint32_t i = 0; i < subpassCount; i++)
{
auto const &subpass = pCreateInfo->pSubpasses[i];
const VkBaseInStructure *extension = reinterpret_cast<const VkBaseInStructure *>(subpass.pNext);
while(extension)
{
switch(extension->sType)
{
case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE:
{
const auto *ext = reinterpret_cast<const VkSubpassDescriptionDepthStencilResolve *>(extension);
// If any subpass includes depthStencilResolve, allocate a DSR struct for each subpass
// This allows us to index into subpassDepthStencilResolves using the subpass index.
if(ext->pDepthStencilResolveAttachment != nullptr && ext->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED)
{
if(subpassDepthStencilResolves == nullptr)
{
subpassDepthStencilResolves = reinterpret_cast<VkSubpassDescriptionDepthStencilResolve *>(hostMemory);
hostMemory += subpassCount * sizeof(VkSubpassDescriptionDepthStencilResolve);
for(uint32_t subpass = 0; subpass < subpassCount; subpass++)
{
subpassDepthStencilResolves[subpass].sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
subpassDepthStencilResolves[subpass].pNext = nullptr;
subpassDepthStencilResolves[subpass].depthResolveMode = VK_RESOLVE_MODE_NONE;
subpassDepthStencilResolves[subpass].stencilResolveMode = VK_RESOLVE_MODE_NONE;
subpassDepthStencilResolves[subpass].pDepthStencilResolveAttachment = nullptr;
}
}
VkAttachmentReference2 *reference = reinterpret_cast<VkAttachmentReference2 *>(hostMemory);
hostMemory += sizeof(VkAttachmentReference2);
subpassDepthStencilResolves[i].depthResolveMode = ext->depthResolveMode;
subpassDepthStencilResolves[i].stencilResolveMode = ext->stencilResolveMode;
reference->pNext = nullptr;
reference->sType = ext->pDepthStencilResolveAttachment->sType;
reference->attachment = ext->pDepthStencilResolveAttachment->attachment;
reference->layout = ext->pDepthStencilResolveAttachment->layout;
reference->aspectMask = ext->pDepthStencilResolveAttachment->aspectMask;
subpassDepthStencilResolves[i].pDepthStencilResolveAttachment = reinterpret_cast<const VkAttachmentReference2 *>(reference);
MarkFirstUse(reference->attachment, i);
}
}
break;
default:
LOG_TRAP("VkRenderPassCreateInfo2KHR->subpass[%d]->pNext sType: %s",
i, vk::Stringify(extension->sType).c_str());
break;
}
extension = extension->pNext;
}
}
} }
template<class T> template<class T>
void RenderPass::init(const T *pCreateInfo, void *mem) void RenderPass::init(const T *pCreateInfo, void **mem)
{ {
char *hostMemory = reinterpret_cast<char *>(mem); char *hostMemory = reinterpret_cast<char *>(*mem);
// subpassCount must be greater than 0 // subpassCount must be greater than 0
ASSERT(pCreateInfo->subpassCount > 0); ASSERT(pCreateInfo->subpassCount > 0);
...@@ -300,7 +358,9 @@ void RenderPass::init(const T *pCreateInfo, void *mem) ...@@ -300,7 +358,9 @@ void RenderPass::init(const T *pCreateInfo, void *mem)
{ {
dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory); dependencies = reinterpret_cast<VkSubpassDependency *>(hostMemory);
CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount); CopySubpassDependencies(dependencies, pCreateInfo->pDependencies, pCreateInfo->dependencyCount);
hostMemory += dependencyCount * sizeof(VkSubpassDependency);
} }
*mem = hostMemory;
} }
void RenderPass::destroy(const VkAllocationCallbacks *pAllocator) void RenderPass::destroy(const VkAllocationCallbacks *pAllocator)
...@@ -315,7 +375,46 @@ size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *p ...@@ -315,7 +375,46 @@ size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo *p
size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo) size_t RenderPass::ComputeRequiredAllocationSize(const VkRenderPassCreateInfo2KHR *pCreateInfo)
{ {
return ComputeRequiredAllocationSizeT(pCreateInfo); size_t requiredMemory = ComputeRequiredAllocationSizeT(pCreateInfo);
// Calculate the memory required to handle depth stencil resolves
bool usesDSR = false;
for(uint32_t i = 0; i < pCreateInfo->subpassCount; i++)
{
auto const &subpass = pCreateInfo->pSubpasses[i];
const VkBaseInStructure *extension = reinterpret_cast<const VkBaseInStructure *>(subpass.pNext);
while(extension)
{
switch(extension->sType)
{
case VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE:
{
const auto *ext = reinterpret_cast<const VkSubpassDescriptionDepthStencilResolve *>(extension);
if(ext->pDepthStencilResolveAttachment != nullptr && ext->pDepthStencilResolveAttachment->attachment != VK_ATTACHMENT_UNUSED)
{
if(!usesDSR)
{
// If any subpass uses DSR, then allocate a VkSubpassDescriptionDepthStencilResolve
// for all subpasses. This allows us to index into our DSR structs using the subpass index.
requiredMemory += sizeof(VkSubpassDescriptionDepthStencilResolve) * pCreateInfo->subpassCount;
usesDSR = true;
}
// For each subpass that actually uses DSR, allocate a VkAttachmentReference2.
requiredMemory += sizeof(VkAttachmentReference2);
}
}
break;
default:
LOG_TRAP("VkRenderPassCreateInfo2KHR->subpass[%d]->pNext sType: %s",
i, vk::Stringify(extension->sType).c_str());
break;
}
extension = extension->pNext;
}
}
return requiredMemory;
} }
void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const void RenderPass::getRenderAreaGranularity(VkExtent2D *pGranularity) const
......
...@@ -53,6 +53,16 @@ public: ...@@ -53,6 +53,16 @@ public:
return subpasses[subpassIndex]; return subpasses[subpassIndex];
} }
bool hasDepthStencilResolve() const
{
return subpassDepthStencilResolves != nullptr;
}
VkSubpassDescriptionDepthStencilResolve getSubpassDepthStencilResolve(uint32_t subpassIndex) const
{
return subpassDepthStencilResolves[subpassIndex];
}
uint32_t getDependencyCount() const uint32_t getDependencyCount() const
{ {
return dependencyCount; return dependencyCount;
...@@ -88,6 +98,7 @@ private: ...@@ -88,6 +98,7 @@ private:
VkAttachmentDescription *attachments = nullptr; VkAttachmentDescription *attachments = nullptr;
uint32_t subpassCount = 0; uint32_t subpassCount = 0;
VkSubpassDescription *subpasses = nullptr; VkSubpassDescription *subpasses = nullptr;
VkSubpassDescriptionDepthStencilResolve *subpassDepthStencilResolves = nullptr;
uint32_t dependencyCount = 0; uint32_t dependencyCount = 0;
VkSubpassDependency *dependencies = nullptr; VkSubpassDependency *dependencies = nullptr;
int *attachmentFirstUse = nullptr; int *attachmentFirstUse = nullptr;
...@@ -96,7 +107,7 @@ private: ...@@ -96,7 +107,7 @@ private:
void MarkFirstUse(int attachment, int subpass); void MarkFirstUse(int attachment, int subpass);
template<class T> template<class T>
void init(const T *pCreateInfo, void *mem); void init(const T *pCreateInfo, void **mem);
}; };
static inline RenderPass *Cast(VkRenderPass object) static inline RenderPass *Cast(VkRenderPass object)
...@@ -106,4 +117,4 @@ static inline RenderPass *Cast(VkRenderPass object) ...@@ -106,4 +117,4 @@ static inline RenderPass *Cast(VkRenderPass object)
} // namespace vk } // namespace vk
#endif // VK_RENDER_PASS_HPP_ #endif // VK_RENDER_PASS_HPP_
\ No newline at end of file
...@@ -408,6 +408,7 @@ static const VkExtensionProperties deviceExtensionProperties[] = { ...@@ -408,6 +408,7 @@ static const VkExtensionProperties deviceExtensionProperties[] = {
{ VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_EXT_HOST_QUERY_RESET_SPEC_VERSION }, { VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_EXT_HOST_QUERY_RESET_SPEC_VERSION },
{ VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION }, { VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME, VK_EXT_SCALAR_BLOCK_LAYOUT_SPEC_VERSION },
{ VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME, VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION }, { VK_EXT_SEPARATE_STENCIL_USAGE_EXTENSION_NAME, VK_EXT_SEPARATE_STENCIL_USAGE_SPEC_VERSION },
{ VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, VK_KHR_DEPTH_STENCIL_RESOLVE_SPEC_VERSION },
{ VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, VK_KHR_IMAGE_FORMAT_LIST_SPEC_VERSION }, { 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 }, { VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME, VK_KHR_IMAGELESS_FRAMEBUFFER_SPEC_VERSION },
{ VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION }, { VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION },
......
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