Commit a76b6836 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Support MSRTT depth/stencil resolve

VK_KHR_depth_stencil_resolve is used by this change to resolve depth/stencil multisampled-render-to-texture renderbuffers. This extension is not widely supported yet. If it's not present, the depth/stencil resolve operation is silently ignored and the renderbuffer acts as a normal multisampled one. This is not correct, but our primary user (Chrome), and most applications don't care for the resolved depth/stencil data. In fact, it's recommended for the depth/stencil attachment to be invalidated after rendering. Exposing EXT_multisampled_render_to_texture even in the absence of depth/stencil resolve allows the majority of the applications to still take advantage of MSRTT color attachments. Bug: angleproject:4836 Change-Id: I6ba4187344a0c9330d2c77bdc5e2c6fc5483c299 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2417645 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent f0b02054
...@@ -73,6 +73,10 @@ struct FeaturesVk : FeatureSetBase ...@@ -73,6 +73,10 @@ struct FeaturesVk : FeatureSetBase
"vertex shader that reads from it is ineffective", "vertex shader that reads from it is ineffective",
&members, "http://anglebug.com/3016"}; &members, "http://anglebug.com/3016"};
Feature supportsRenderpass2 = {"supports_renderpass2", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_create_renderpass2 extension",
&members};
// Whether the VkDevice supports the VK_KHR_incremental_present extension, on which the // Whether the VkDevice supports the VK_KHR_incremental_present extension, on which the
// EGL_KHR_swap_buffers_with_damage extension can be layered. // EGL_KHR_swap_buffers_with_damage extension can be layered.
Feature supportsIncrementalPresent = { Feature supportsIncrementalPresent = {
...@@ -184,6 +188,15 @@ struct FeaturesVk : FeatureSetBase ...@@ -184,6 +188,15 @@ struct FeaturesVk : FeatureSetBase
"VkDevice supports the VK_EXT_index_type_uint8 extension", "VkDevice supports the VK_EXT_index_type_uint8 extension",
&members, "http://anglebug.com/4405"}; &members, "http://anglebug.com/4405"};
// Whether the VkDevice supports the VK_KHR_depth_stencil_resolve extension with the
// independentResolveNone feature.
// http://anglebug.com/4836
Feature supportsDepthStencilResolve = {"supports_depth_stencil_resolve",
FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_depth_stencil_resolve "
"extension with the independentResolveNone feature",
&members, "http://anglebug.com/4836"};
// VK_PRESENT_MODE_FIFO_KHR causes random timeouts on Linux Intel. http://anglebug.com/3153 // VK_PRESENT_MODE_FIFO_KHR causes random timeouts on Linux Intel. http://anglebug.com/3153
Feature disableFifoPresentMode = { Feature disableFifoPresentMode = {
"disable_fifo_present_mode", FeatureCategory::VulkanWorkarounds, "disable_fifo_present_mode", FeatureCategory::VulkanWorkarounds,
......
...@@ -74,6 +74,9 @@ extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR ...@@ -74,6 +74,9 @@ extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
// VK_KHR_create_renderpass2
extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR;
# if defined(ANGLE_PLATFORM_FUCHSIA) # if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
......
...@@ -1600,6 +1600,16 @@ void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk) ...@@ -1600,6 +1600,16 @@ void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
{ {
mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageViewSubresourceSerial); mCurrentFramebufferDesc.updateDepthStencil(vk::kInvalidImageViewSubresourceSerial);
} }
if (depthStencilRT != nullptr && depthStencilRT->hasResolveAttachment())
{
mCurrentFramebufferDesc.updateDepthStencilResolve(
depthStencilRT->getResolveSubresourceSerial());
}
else
{
mCurrentFramebufferDesc.updateDepthStencilResolve(vk::kInvalidImageViewSubresourceSerial);
}
} }
angle::Result FramebufferVk::syncState(const gl::Context *context, angle::Result FramebufferVk::syncState(const gl::Context *context,
...@@ -1793,6 +1803,16 @@ void FramebufferVk::updateRenderPassDesc() ...@@ -1793,6 +1803,16 @@ void FramebufferVk::updateRenderPassDesc()
mRenderPassDesc.packDepthStencilAttachment( mRenderPassDesc.packDepthStencilAttachment(
depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID, depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID,
dsAccess); dsAccess);
// Add the resolve attachment, if any.
if (depthStencilRenderTarget->hasResolveAttachment())
{
const vk::Format &format = depthStencilRenderTarget->getImageFormat();
bool hasDepth = format.intendedFormat().depthBits > 0;
bool hasStencil = format.intendedFormat().stencilBits > 0;
mRenderPassDesc.packDepthStencilResolveAttachment(hasDepth, hasStencil);
}
} }
} }
...@@ -1894,6 +1914,17 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk, ...@@ -1894,6 +1914,17 @@ angle::Result FramebufferVk::getFramebuffer(ContextVk *contextVk,
} }
} }
// Depth/stencil resolve attachment.
if (depthStencilRenderTarget && depthStencilRenderTarget->hasResolveAttachment())
{
const vk::ImageView *imageView = nullptr;
ANGLE_TRY(depthStencilRenderTarget->getResolveImageView(contextVk, &imageView));
attachments.push_back(imageView->getHandle());
ASSERT(!attachmentsSize.empty());
}
if (attachmentsSize.empty()) if (attachmentsSize.empty())
{ {
// No attachments, so use the default values. // No attachments, so use the default values.
...@@ -2265,7 +2296,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2265,7 +2296,7 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget(); RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
// depth stencil attachment always immediately follow color attachment // depth stencil attachment always immediately follows color attachment
depthStencilAttachmentIndex = colorIndexVk; depthStencilAttachmentIndex = colorIndexVk;
VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; VkAttachmentLoadOp depthLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
...@@ -2286,8 +2317,14 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk, ...@@ -2286,8 +2317,14 @@ angle::Result FramebufferVk::startNewRenderPass(ContextVk *contextVk,
if (depthStencilRenderTarget->isImageTransient()) if (depthStencilRenderTarget->isImageTransient())
{ {
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // TODO(syoussefi): currently, depth/stencil unresolve is not implemented. Until then,
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // don't change storeOp to DONT_CARE, unless the attachment is entirely transient (i.e.
// depth textures from EXT_multisampled_render_to_texture2. http://anglebug.com/4836
if (depthStencilRenderTarget->isEntirelyTransient())
{
depthStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
} }
vk::ImageLayout dsLayout = isReadOnlyDepthMode() ? vk::ImageLayout::DepthStencilReadOnly vk::ImageLayout dsLayout = isReadOnlyDepthMode() ? vk::ImageLayout::DepthStencilReadOnly
......
...@@ -115,7 +115,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget ...@@ -115,7 +115,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
void restoreEntireContent() { mContentDefined = true; } void restoreEntireContent() { mContentDefined = true; }
// See the description of mTransience for details of how the following two can interact. // See the description of mTransience for details of how the following two can interact.
bool hasResolveAttachment() const { return mResolveImage != nullptr; } bool hasResolveAttachment() const { return mResolveImage != nullptr && !isEntirelyTransient(); }
bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; } bool isImageTransient() const { return mTransience != RenderTargetTransience::Default; }
bool isEntirelyTransient() const bool isEntirelyTransient() const
{ {
......
...@@ -81,11 +81,12 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, ...@@ -81,11 +81,12 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
const bool isDepthStencilFormat = textureFormat.hasDepthOrStencilBits(); const bool isDepthStencilFormat = textureFormat.hasDepthOrStencilBits();
ASSERT(textureFormat.redBits > 0 || isDepthStencilFormat); ASSERT(textureFormat.redBits > 0 || isDepthStencilFormat);
// TODO(syoussefi): Currently not supported for depth/stencil images. Tests (and Chromium) only // TODO(syoussefi): Currently not supported for depth/stencil images if
// use this for depth/stencil buffers and don't attempt to read from it. This needs to be fixed // VK_KHR_depth_stencil_resolve is not supported. Chromium only uses this for depth/stencil
// and tests added. http://anglebug.com/4836 // buffers and doesn't attempt to read from it. http://anglebug.com/5065
const bool isRenderToTexture = const bool isRenderToTexture =
mode == gl::MultisamplingMode::MultisampledRenderToTexture && !isDepthStencilFormat; mode == gl::MultisamplingMode::MultisampledRenderToTexture &&
(!isDepthStencilFormat || renderer->getFeatures().supportsDepthStencilResolve.enabled);
const VkImageUsageFlags usage = const VkImageUsageFlags usage =
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
......
...@@ -935,6 +935,10 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -935,6 +935,10 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mShaderFloat16Int8Features.sType = mShaderFloat16Int8Features.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
mDepthStencilResolveProperties = {};
mDepthStencilResolveProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
mExternalFenceProperties = {}; mExternalFenceProperties = {};
mExternalFenceProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES; mExternalFenceProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
...@@ -1006,6 +1010,12 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -1006,6 +1010,12 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
vk::AddToPNextChain(&deviceFeatures, &mShaderFloat16Int8Features); vk::AddToPNextChain(&deviceFeatures, &mShaderFloat16Int8Features);
} }
// Query depth/stencil resolve properties
if (ExtensionFound(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, deviceExtensionNames))
{
vk::AddToPNextChain(&deviceProperties, &mDepthStencilResolveProperties);
}
// Query subgroup properties // Query subgroup properties
vk::AddToPNextChain(&deviceProperties, &mSubgroupProperties); vk::AddToPNextChain(&deviceProperties, &mSubgroupProperties);
...@@ -1043,14 +1053,9 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt ...@@ -1043,14 +1053,9 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
mIndexTypeUint8Features.pNext = nullptr; mIndexTypeUint8Features.pNext = nullptr;
mSubgroupProperties.pNext = nullptr; mSubgroupProperties.pNext = nullptr;
mExternalMemoryHostProperties.pNext = nullptr; mExternalMemoryHostProperties.pNext = nullptr;
mLineRasterizationFeatures.pNext = nullptr;
mProvokingVertexFeatures.pNext = nullptr;
mVertexAttributeDivisorFeatures.pNext = nullptr;
mVertexAttributeDivisorProperties.pNext = nullptr;
mTransformFeedbackFeatures.pNext = nullptr;
mIndexTypeUint8Features.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr;
mShaderFloat16Int8Features.pNext = nullptr; mShaderFloat16Int8Features.pNext = nullptr;
mDepthStencilResolveProperties.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr;
} }
angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex) angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
...@@ -1169,6 +1174,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1169,6 +1174,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
} }
if (getFeatures().supportsRenderpass2.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
}
if (getFeatures().supportsIncrementalPresent.enabled) if (getFeatures().supportsIncrementalPresent.enabled)
{ {
enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
...@@ -1357,6 +1367,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1357,6 +1367,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
vk::AddToPNextChain(&createInfo, &mIndexTypeUint8Features); vk::AddToPNextChain(&createInfo, &mIndexTypeUint8Features);
} }
if (getFeatures().supportsDepthStencilResolve.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
}
if (getFeatures().supportsExternalMemoryHost.enabled) if (getFeatures().supportsExternalMemoryHost.enabled)
{ {
enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
...@@ -1434,6 +1449,10 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1434,6 +1449,10 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
{ {
InitSamplerYcbcrKHRFunctions(mDevice); InitSamplerYcbcrKHRFunctions(mDevice);
} }
if (getFeatures().supportsRenderpass2.enabled)
{
InitRenderPass2KHRFunctions(mDevice);
}
#endif // !defined(ANGLE_SHARED_LIBVULKAN) #endif // !defined(ANGLE_SHARED_LIBVULKAN)
if (getFeatures().forceMaxUniformBufferSize16KB.enabled) if (getFeatures().forceMaxUniformBufferSize16KB.enabled)
...@@ -1712,6 +1731,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1712,6 +1731,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
mPhysicalDeviceProperties.deviceID)); mPhysicalDeviceProperties.deviceID));
ANGLE_FEATURE_CONDITION( ANGLE_FEATURE_CONDITION(
&mFeatures, supportsRenderpass2,
ExtensionFound(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsIncrementalPresent, &mFeatures, supportsIncrementalPresent,
ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames)); ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames));
...@@ -1791,6 +1814,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1791,6 +1814,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ANGLE_FEATURE_CONDITION(&mFeatures, supportsIndexTypeUint8, ANGLE_FEATURE_CONDITION(&mFeatures, supportsIndexTypeUint8,
mIndexTypeUint8Features.indexTypeUint8 == VK_TRUE); mIndexTypeUint8Features.indexTypeUint8 == VK_TRUE);
ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve,
mFeatures.supportsRenderpass2.enabled &&
mDepthStencilResolveProperties.independentResolveNone == VK_TRUE);
ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback, ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
(!mFeatures.supportsTransformFeedbackExtension.enabled && (!mFeatures.supportsTransformFeedbackExtension.enabled &&
mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics == VK_TRUE)); mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics == VK_TRUE));
......
...@@ -317,6 +317,7 @@ class RendererVk : angle::NonCopyable ...@@ -317,6 +317,7 @@ class RendererVk : angle::NonCopyable
VkPhysicalDeviceSubgroupProperties mSubgroupProperties; VkPhysicalDeviceSubgroupProperties mSubgroupProperties;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties; VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
VkExternalFenceProperties mExternalFenceProperties; VkExternalFenceProperties mExternalFenceProperties;
VkExternalSemaphoreProperties mExternalSemaphoreProperties; VkExternalSemaphoreProperties mExternalSemaphoreProperties;
VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures; VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures;
......
...@@ -108,10 +108,12 @@ inline void UpdateAccess(ResourceAccess *oldAccess, ResourceAccess newAccess) ...@@ -108,10 +108,12 @@ inline void UpdateAccess(ResourceAccess *oldAccess, ResourceAccess newAccess)
} }
// There can be a maximum of IMPLEMENTATION_MAX_DRAW_BUFFERS color and resolve attachments, plus one // There can be a maximum of IMPLEMENTATION_MAX_DRAW_BUFFERS color and resolve attachments, plus one
// depth/stencil attachment. // depth/stencil attachment and one depth/stencil resolve attachment.
constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 + 1; constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 + 2;
template <typename T> template <typename T>
using FramebufferAttachmentArray = std::array<T, kMaxFramebufferAttachments>; using FramebufferAttachmentArray = std::array<T, kMaxFramebufferAttachments>;
template <typename T>
using FramebufferAttachmentsVector = angle::FixedVector<T, kMaxFramebufferAttachments>;
constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1; constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
template <typename T> template <typename T>
...@@ -140,6 +142,8 @@ class alignas(4) RenderPassDesc final ...@@ -140,6 +142,8 @@ class alignas(4) RenderPassDesc final
// Indicate that a color attachment should take its data from the resolve attachment initially. // Indicate that a color attachment should take its data from the resolve attachment initially.
void packColorUnresolveAttachment(size_t colorIndexGL); void packColorUnresolveAttachment(size_t colorIndexGL);
void removeColorUnresolveAttachment(size_t colorIndexGL); void removeColorUnresolveAttachment(size_t colorIndexGL);
// Indicate that a depth/stencil attachment should have a corresponding resolve attachment.
void packDepthStencilResolveAttachment(bool resolveDepth, bool resolveStencil);
size_t hash() const; size_t hash() const;
...@@ -165,6 +169,18 @@ class alignas(4) RenderPassDesc final ...@@ -165,6 +169,18 @@ class alignas(4) RenderPassDesc final
{ {
return mColorUnresolveAttachmentMask.test(colorIndexGL); return mColorUnresolveAttachmentMask.test(colorIndexGL);
} }
bool hasDepthStencilResolveAttachment() const
{
return (mAttachmentFormats.back() & (kResolveDepthFlag | kResolveStencilFlag)) != 0;
}
bool hasDepthResolveAttachment() const
{
return (mAttachmentFormats.back() & kResolveDepthFlag) != 0;
}
bool hasStencilResolveAttachment() const
{
return (mAttachmentFormats.back() & kResolveStencilFlag) != 0;
}
// Get the number of attachments in the Vulkan render pass, i.e. after removing disabled // Get the number of attachments in the Vulkan render pass, i.e. after removing disabled
// color attachments. // color attachments.
...@@ -241,6 +257,10 @@ class alignas(4) RenderPassDesc final ...@@ -241,6 +257,10 @@ class alignas(4) RenderPassDesc final
// Depth/stencil format is stored in 3 bits. // Depth/stencil format is stored in 3 bits.
static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7; static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7;
// Flags stored in the upper 5 bits of mAttachmentFormats.back().
static constexpr uint8_t kResolveDepthFlag = 0x80;
static constexpr uint8_t kResolveStencilFlag = 0x40;
}; };
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs); bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
...@@ -1016,11 +1036,15 @@ class UniformsAndXfbDesc ...@@ -1016,11 +1036,15 @@ class UniformsAndXfbDesc
// In the FramebufferDesc object: // In the FramebufferDesc object:
// - Depth/stencil serial is at index 0 // - Depth/stencil serial is at index 0
// - Color serials are at indices [1:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] // - Color serials are at indices [1:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]
// - Resolve attachments are at indices [gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+1, // - Depth/stencil resolve attachment is at index gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+1
// gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2] // - Resolve attachments are at indices [gl::IMPLEMENTATION_MAX_DRAW_BUFFERS+2,
constexpr size_t kFramebufferDescDepthStencilIndex = 0; // gl::IMPLEMENTATION_MAX_DRAW_BUFFERS*2+1]
constexpr size_t kFramebufferDescColorIndexOffset = 1; constexpr size_t kFramebufferDescDepthStencilIndex = 0;
constexpr size_t kFramebufferDescResolveIndexOffset = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1; constexpr size_t kFramebufferDescColorIndexOffset = kFramebufferDescDepthStencilIndex + 1;
constexpr size_t kFramebufferDescDepthStencilResolveIndexOffset =
kFramebufferDescColorIndexOffset + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
constexpr size_t kFramebufferDescColorResolveIndexOffset =
kFramebufferDescDepthStencilResolveIndexOffset + 1;
class FramebufferDesc class FramebufferDesc
{ {
...@@ -1035,6 +1059,7 @@ class FramebufferDesc ...@@ -1035,6 +1059,7 @@ class FramebufferDesc
void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial); void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial);
void updateColorUnresolveMask(gl::DrawBufferMask colorUnresolveMask); void updateColorUnresolveMask(gl::DrawBufferMask colorUnresolveMask);
void updateDepthStencil(ImageViewSubresourceSerial serial); void updateDepthStencil(ImageViewSubresourceSerial serial);
void updateDepthStencilResolve(ImageViewSubresourceSerial serial);
void updateReadOnlyDepth(bool readOnlyDepth); void updateReadOnlyDepth(bool readOnlyDepth);
size_t hash() const; size_t hash() const;
void reset(); void reset();
......
...@@ -833,6 +833,9 @@ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR ...@@ -833,6 +833,9 @@ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR = nullptr; PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR = nullptr;
PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR = nullptr; PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR = nullptr;
// VK_KHR_create_renderpass2
PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = nullptr;
# if defined(ANGLE_PLATFORM_FUCHSIA) # if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr; PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
...@@ -900,6 +903,12 @@ void InitSamplerYcbcrKHRFunctions(VkDevice device) ...@@ -900,6 +903,12 @@ void InitSamplerYcbcrKHRFunctions(VkDevice device)
GET_DEVICE_FUNC(vkDestroySamplerYcbcrConversionKHR); GET_DEVICE_FUNC(vkDestroySamplerYcbcrConversionKHR);
} }
// VK_KHR_create_renderpass2
void InitRenderPass2KHRFunctions(VkDevice device)
{
GET_DEVICE_FUNC(vkCreateRenderPass2KHR);
}
# if defined(ANGLE_PLATFORM_FUCHSIA) # if defined(ANGLE_PLATFORM_FUCHSIA)
void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance) void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
{ {
......
...@@ -802,6 +802,7 @@ void InitDebugReportEXTFunctions(VkInstance instance); ...@@ -802,6 +802,7 @@ void InitDebugReportEXTFunctions(VkInstance instance);
void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance); void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance);
void InitTransformFeedbackEXTFunctions(VkDevice device); void InitTransformFeedbackEXTFunctions(VkDevice device);
void InitSamplerYcbcrKHRFunctions(VkDevice device); void InitSamplerYcbcrKHRFunctions(VkDevice device);
void InitRenderPass2KHRFunctions(VkDevice device);
# if defined(ANGLE_PLATFORM_FUCHSIA) # if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
......
...@@ -513,6 +513,7 @@ class RenderPass final : public WrappedObject<RenderPass, VkRenderPass> ...@@ -513,6 +513,7 @@ class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
void destroy(VkDevice device); void destroy(VkDevice device);
VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo); VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
VkResult init2(VkDevice device, const VkRenderPassCreateInfo2 &createInfo);
}; };
enum class StagingUsage enum class StagingUsage
...@@ -1501,6 +1502,12 @@ ANGLE_INLINE VkResult RenderPass::init(VkDevice device, const VkRenderPassCreate ...@@ -1501,6 +1502,12 @@ ANGLE_INLINE VkResult RenderPass::init(VkDevice device, const VkRenderPassCreate
return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle); return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle);
} }
ANGLE_INLINE VkResult RenderPass::init2(VkDevice device, const VkRenderPassCreateInfo2 &createInfo)
{
ASSERT(!valid());
return vkCreateRenderPass2KHR(device, &createInfo, nullptr, &mHandle);
}
// Buffer implementation. // Buffer implementation.
ANGLE_INLINE void Buffer::destroy(VkDevice device) ANGLE_INLINE void Buffer::destroy(VkDevice device)
{ {
......
...@@ -142,7 +142,6 @@ class MultisampledRenderToTextureTest : public ANGLETest ...@@ -142,7 +142,6 @@ class MultisampledRenderToTextureTest : public ANGLETest
void drawCopyThenBlendCommon(bool useRenderbuffer); void drawCopyThenBlendCommon(bool useRenderbuffer);
void clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer); void clearDrawCopyThenBlendSameProgramCommon(bool useRenderbuffer);
void clearThenBlendCommon(bool useRenderbuffer); void clearThenBlendCommon(bool useRenderbuffer);
void depthStencilClearThenDrawCommon(bool useRenderbuffer);
GLProgram mCopyTextureProgram; GLProgram mCopyTextureProgram;
GLint mCopyTextureUniformLocation = -1; GLint mCopyTextureUniformLocation = -1;
...@@ -153,6 +152,7 @@ class MultisampledRenderToTextureES3Test : public MultisampledRenderToTextureTes ...@@ -153,6 +152,7 @@ class MultisampledRenderToTextureES3Test : public MultisampledRenderToTextureTes
protected: protected:
void readPixelsTestCommon(bool useRenderbuffer); void readPixelsTestCommon(bool useRenderbuffer);
void blitFramebufferTestCommon(bool useRenderbuffer); void blitFramebufferTestCommon(bool useRenderbuffer);
void depthStencilClearThenDrawCommon(bool useRenderbuffer);
void colorAttachment1Common(bool useRenderbuffer); void colorAttachment1Common(bool useRenderbuffer);
void colorAttachments0And3Common(bool useRenderbuffer); void colorAttachments0And3Common(bool useRenderbuffer);
void blitFramebufferMixedColorAndDepthCommon(bool useRenderbuffer); void blitFramebufferMixedColorAndDepthCommon(bool useRenderbuffer);
...@@ -1176,13 +1176,17 @@ TEST_P(MultisampledRenderToTextureTest, RenderbufferClearThenBlend) ...@@ -1176,13 +1176,17 @@ TEST_P(MultisampledRenderToTextureTest, RenderbufferClearThenBlend)
clearThenBlendCommon(true); clearThenBlendCommon(true);
} }
void MultisampledRenderToTextureTest::depthStencilClearThenDrawCommon(bool useRenderbuffer) void MultisampledRenderToTextureES3Test::depthStencilClearThenDrawCommon(bool useRenderbuffer)
{ {
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
if (!useRenderbuffer) if (!useRenderbuffer)
{ {
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture2"));
} }
// http://anglebug.com/5083
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
constexpr GLsizei kSize = 64; constexpr GLsizei kSize = 64;
setupCopyTexProgram(); setupCopyTexProgram();
...@@ -1211,7 +1215,7 @@ void MultisampledRenderToTextureTest::depthStencilClearThenDrawCommon(bool useRe ...@@ -1211,7 +1215,7 @@ void MultisampledRenderToTextureTest::depthStencilClearThenDrawCommon(bool useRe
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
// If stencil is not clear to 0x55, rendering would fail. // If stencil is not cleared to 0x55, rendering would fail.
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF); glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
...@@ -1238,15 +1242,104 @@ void MultisampledRenderToTextureTest::depthStencilClearThenDrawCommon(bool useRe ...@@ -1238,15 +1242,104 @@ void MultisampledRenderToTextureTest::depthStencilClearThenDrawCommon(bool useRe
} }
// Clear depth stencil, then draw. The clear should be applied correctly. // Clear depth stencil, then draw. The clear should be applied correctly.
TEST_P(MultisampledRenderToTextureTest, DepthStencilClearThenDraw) TEST_P(MultisampledRenderToTextureES3Test, DepthStencilClearThenDraw)
{ {
clearThenBlendCommon(false); depthStencilClearThenDrawCommon(false);
} }
// Clear depth stencil, then draw. The clear should be applied correctly. Uses renderbuffer. // Clear depth stencil, then draw. The clear should be applied correctly. Uses renderbuffer.
TEST_P(MultisampledRenderToTextureTest, RenderbufferDepthStencilClearThenDraw) TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearThenDraw)
{ {
clearThenBlendCommon(true); depthStencilClearThenDrawCommon(true);
}
// Clear&Draw, copy, then blend similarly to RenderbufferClearDrawCopyThenBlendSameProgram. This
// tests uses a depth/stencil buffer and makes sure the second draw (in the second render pass)
// succeeds (i.e. depth/stencil data is not lost). Note that this test doesn't apply to
// depth/stencil textures as they are explicitly autoinvalidated between render passes.
TEST_P(MultisampledRenderToTextureES3Test, RenderbufferDepthStencilClearDrawCopyThenBlend)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
// http://anglebug.com/5083
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
constexpr GLsizei kSize = 64;
setupCopyTexProgram();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Create framebuffer to draw into, with both color and depth attachments.
GLTexture color;
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color,
0, 4);
GLRenderbuffer depthStencil;
glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
ASSERT_GL_NO_ERROR();
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Set viewport and clear depth/stencil
glViewport(0, 0, kSize, kSize);
glClearDepthf(1);
glClearStencil(0x55);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// If stencil is not cleared to 0x55, rendering would fail.
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF);
// Set up program
ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
glUseProgram(drawColor);
GLint colorUniformLocation =
glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
ASSERT_NE(colorUniformLocation, -1);
// Draw red
glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.25f);
ASSERT_GL_NO_ERROR();
// Create a texture and copy into it.
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ASSERT_GL_NO_ERROR();
// Draw again into the framebuffer, this time blending. This tests that both the color and
// depth/stencil data are preserved after the resolve incurred by the copy above.
glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 0.5f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
// Verify that the texture is now yellow
const GLColor kExpected(127, 127, 0, 191);
EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(kSize - 1, 0, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(0, kSize - 1, kExpected, 1);
EXPECT_PIXEL_COLOR_NEAR(kSize - 1, kSize - 1, kExpected, 1);
// For completeness, verify that the texture used as copy target is red.
const GLColor expectedCopyResult(255, 0, 0, 255);
verifyResults(texture, expectedCopyResult, kSize, 0, 0, kSize, kSize);
} }
void MultisampledRenderToTextureES3Test::colorAttachment1Common(bool useRenderbuffer) void MultisampledRenderToTextureES3Test::colorAttachment1Common(bool useRenderbuffer)
......
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