Commit 2eba823b by Shahbaz Youssefi

[M90] Vulkan: Use VK_EXT_multisampled_render_to_single_sampled

Additionally, makes the emulation path not require independentResolveNone. This was only used to select the NONE resolve mode when the attachment format doesn't have either of depth or stencil aspects, but it's ok to specify the same resolve mode for both aspects even if one aspect is missing. cherry-picked from commits d1462228 and 86a86a7d. Bug: chromium:1088005 Change-Id: Ie4affc3f6f97789e9ea327272e308d19a609f19e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2810801Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 0297dd80
......@@ -208,6 +208,13 @@ struct FeaturesVk : FeatureSetBase
"extension with the independentResolveNone feature",
&members, "http://anglebug.com/4836"};
// Whether the VkDevice supports the VK_EXT_multisampled_render_to_single_sampled extension.
// http://anglebug.com/4836
Feature supportsMultisampledRenderToSingleSampled = {
"supportsMultisampledRenderToSingleSampled", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_EXT_multisampled_render_to_single_sampled extension", &members,
"http://anglebug.com/4836"};
// VK_PRESENT_MODE_FIFO_KHR causes random timeouts on Linux Intel. http://anglebug.com/3153
Feature disableFifoPresentMode = {"disableFifoPresentMode", FeatureCategory::VulkanWorkarounds,
"VK_PRESENT_MODE_FIFO_KHR causes random timeouts", &members,
......
......@@ -16,6 +16,36 @@
# include <vulkan/vulkan.h>
#endif
// For the unreleased VK_EXT_multisampled_render_to_single_sampled
#if !defined(VK_EXT_multisampled_render_to_single_sampled)
# define VK_EXT_multisampled_render_to_single_sampled 1
# define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1
# define VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME \
"VK_GOOGLEX_multisampled_render_to_single_sampled"
# define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT \
((VkStructureType)(1000376000))
# define VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT \
((VkStructureType)(1000376001))
typedef struct VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT
{
VkStructureType sType;
const void *pNext;
VkBool32 multisampledRenderToSingleSampled;
} VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT;
typedef struct VkMultisampledRenderToSingleSampledInfoEXT
{
VkStructureType sType;
const void *pNext;
VkBool32 multisampledRenderToSingleSampledEnable;
VkSampleCountFlagBits rasterizationSamples;
VkResolveModeFlagBits depthResolveMode;
VkResolveModeFlagBits stencilResolveMode;
} VkMultisampledRenderToSingleSampledInfoEXT;
#endif /* VK_EXT_multisampled_render_to_single_sampled */
#if !defined(ANGLE_SHARED_LIBVULKAN)
namespace rx
......
......@@ -117,6 +117,10 @@ class FramebufferAttachment final
bool isMultiview() const;
GLint getBaseViewIndex() const;
bool isRenderToTexture() const
{
return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
}
GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
// The size of the underlying resource the attachment points to. The 'depth' value will
......
......@@ -1919,11 +1919,7 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
// 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);
mRenderPassDesc.packDepthStencilResolveAttachment();
}
}
......@@ -1943,6 +1939,31 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
mRenderPassDesc.setFramebufferFetchMode(programUsesFramebufferFetch);
}
if (contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled)
{
// Update descriptions regarding multisampled-render-to-texture use.
bool isRenderToTexture = false;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
ASSERT(color);
if (color->isRenderToTexture())
{
isRenderToTexture = true;
break;
}
}
const gl::FramebufferAttachment *depthStencil = mState.getDepthStencilAttachment();
if (depthStencil && depthStencil->isRenderToTexture())
{
isRenderToTexture = true;
}
mCurrentFramebufferDesc.updateRenderToTexture(isRenderToTexture);
mRenderPassDesc.updateRenderToTexture(isRenderToTexture);
}
mCurrentFramebufferDesc.updateUnresolveMask({});
}
......@@ -2696,23 +2717,35 @@ gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk)
return rotatedScissoredArea;
}
RenderTargetVk *FramebufferVk::getFirstRenderTarget() const
GLint FramebufferVk::getSamples() const
{
for (auto *renderTarget : mRenderTargetCache.getColors())
const gl::FramebufferAttachment *lastAttachment = nullptr;
for (size_t colorIndexGL : mState.getEnabledDrawBuffers())
{
if (renderTarget)
const gl::FramebufferAttachment *color = mState.getColorAttachment(colorIndexGL);
ASSERT(color);
if (color->isRenderToTexture())
{
return renderTarget;
return color->getSamples();
}
}
return getDepthStencilRenderTarget();
}
lastAttachment = color;
}
const gl::FramebufferAttachment *depthStencil = mState.getDepthOrStencilAttachment();
if (depthStencil)
{
if (depthStencil->isRenderToTexture())
{
return depthStencil->getSamples();
}
lastAttachment = depthStencil;
}
GLint FramebufferVk::getSamples() const
{
RenderTargetVk *firstRT = getFirstRenderTarget();
return firstRT ? firstRT->getImageForRenderPass().getSamples() : 1;
// If none of the attachments are multisampled-render-to-texture, take the sample count from the
// last attachment (any would have worked, as they would all have the same sample count).
return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1);
}
angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
......
......@@ -141,7 +141,6 @@ class FramebufferVk : public FramebufferImpl
vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut);
RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const;
const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
......
......@@ -88,13 +88,15 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
const bool isRenderToTexture =
mode == gl::MultisamplingMode::MultisampledRenderToTexture &&
(!isDepthStencilFormat || renderer->getFeatures().supportsDepthStencilResolve.enabled);
const bool hasRenderToTextureEXT =
renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
const VkImageUsageFlags usage =
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
(isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) |
(isRenderToTexture ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : 0);
(isRenderToTexture && !hasRenderToTextureEXT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : 0);
const uint32_t imageSamples = isRenderToTexture ? 1 : samples;
......@@ -112,7 +114,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
// If multisampled render to texture, an implicit multisampled image is created which is used as
// the color or depth/stencil attachment. At the end of the render pass, this image is
// automatically resolved into |mImage| and its contents are discarded.
if (isRenderToTexture)
if (isRenderToTexture && !hasRenderToTextureEXT)
{
mMultisampledImageViews.init(renderer);
......
......@@ -1121,6 +1121,10 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
mDepthStencilResolveProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
mMultisampledRenderToSingleSampledFeatures = {};
mMultisampledRenderToSingleSampledFeatures.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT;
mDriverProperties = {};
mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
......@@ -1207,6 +1211,13 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
vk::AddToPNextChain(&deviceProperties, &mDepthStencilResolveProperties);
}
// Query multisampled render to single-sampled properties
if (ExtensionFound(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME,
deviceExtensionNames))
{
vk::AddToPNextChain(&deviceFeatures, &mMultisampledRenderToSingleSampledFeatures);
}
// Query driver properties
if (ExtensionFound(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, deviceExtensionNames))
{
......@@ -1242,19 +1253,20 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
}
// Clean up pNext chains
mLineRasterizationFeatures.pNext = nullptr;
mMemoryReportFeatures.pNext = nullptr;
mProvokingVertexFeatures.pNext = nullptr;
mVertexAttributeDivisorFeatures.pNext = nullptr;
mVertexAttributeDivisorProperties.pNext = nullptr;
mTransformFeedbackFeatures.pNext = nullptr;
mIndexTypeUint8Features.pNext = nullptr;
mSubgroupProperties.pNext = nullptr;
mExternalMemoryHostProperties.pNext = nullptr;
mShaderFloat16Int8Features.pNext = nullptr;
mDepthStencilResolveProperties.pNext = nullptr;
mDriverProperties.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr;
mLineRasterizationFeatures.pNext = nullptr;
mMemoryReportFeatures.pNext = nullptr;
mProvokingVertexFeatures.pNext = nullptr;
mVertexAttributeDivisorFeatures.pNext = nullptr;
mVertexAttributeDivisorProperties.pNext = nullptr;
mTransformFeedbackFeatures.pNext = nullptr;
mIndexTypeUint8Features.pNext = nullptr;
mSubgroupProperties.pNext = nullptr;
mExternalMemoryHostProperties.pNext = nullptr;
mShaderFloat16Int8Features.pNext = nullptr;
mDepthStencilResolveProperties.pNext = nullptr;
mMultisampledRenderToSingleSampledFeatures.pNext = nullptr;
mDriverProperties.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr;
}
angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueFamilyIndex)
......@@ -1599,6 +1611,13 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
}
if (getFeatures().supportsMultisampledRenderToSingleSampled.enabled)
{
enabledDeviceExtensions.push_back(
VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
vk::AddToPNextChain(&createInfo, &mMultisampledRenderToSingleSampledFeatures);
}
if (mMemoryReportFeatures.deviceMemoryReport &&
(getFeatures().logMemoryReportCallbacks.enabled ||
getFeatures().logMemoryReportStats.enabled))
......@@ -2156,7 +2175,13 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve,
mFeatures.supportsRenderpass2.enabled &&
mDepthStencilResolveProperties.independentResolveNone == VK_TRUE);
mDepthStencilResolveProperties.supportedDepthResolveModes != 0);
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsMultisampledRenderToSingleSampled,
mFeatures.supportsRenderpass2.enabled && mFeatures.supportsDepthStencilResolve.enabled &&
mMultisampledRenderToSingleSampledFeatures.multisampledRenderToSingleSampled ==
VK_TRUE);
ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
(!mFeatures.supportsTransformFeedbackExtension.enabled &&
......@@ -2252,8 +2277,10 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
// - Swiftshader on mac: http://anglebug.com/4937
// - Intel on windows: http://anglebug.com/5032
// - AMD on windows: http://crbug.com/1132366
ANGLE_FEATURE_CONDITION(&mFeatures, enableMultisampledRenderToTexture,
!(IsApple() && isSwiftShader) && !(IsWindows() && (isIntel || isAMD)));
ANGLE_FEATURE_CONDITION(
&mFeatures, enableMultisampledRenderToTexture,
mFeatures.supportsMultisampledRenderToSingleSampled.enabled ||
!(IsApple() && isSwiftShader) && !(IsWindows() && (isIntel || isAMD)));
// Feature disabled due to driver bugs:
//
......
......@@ -418,6 +418,8 @@ class RendererVk : angle::NonCopyable
VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT
mMultisampledRenderToSingleSampledFeatures;
VkPhysicalDeviceDriverPropertiesKHR mDriverProperties;
VkExternalFenceProperties mExternalFenceProperties;
VkExternalSemaphoreProperties mExternalSemaphoreProperties;
......
......@@ -2114,13 +2114,18 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
levelCount));
}
const bool hasRenderToTextureEXT =
contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
// If samples > 1 here, we have a singlesampled texture that's being multisampled rendered to.
// In this case, create a multisampled image that is otherwise identical to the single sampled
// image. That multisampled image is used as color or depth/stencil attachment, while the
// original image is used as the resolve attachment.
const gl::RenderToTextureImageIndex renderToTextureIndex =
static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));
if (samples > 1 && !mMultisampledImages[renderToTextureIndex].valid())
hasRenderToTextureEXT
? gl::RenderToTextureImageIndex::Default
: static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));
if (samples > 1 && !mMultisampledImages[renderToTextureIndex].valid() && !hasRenderToTextureEXT)
{
ASSERT(mState.getBaseLevelDesc().samples <= 1);
vk::ImageHelper *multisampledImage = &mMultisampledImages[renderToTextureIndex];
......
......@@ -161,7 +161,7 @@ class alignas(4) RenderPassDesc final
void packColorUnresolveAttachment(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);
void packDepthStencilResolveAttachment();
// Indicate that a depth/stencil attachment should take its data from the resolve attachment
// initially.
void packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil);
......@@ -189,15 +189,7 @@ class alignas(4) RenderPassDesc final
}
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;
return (mAttachmentFormats.back() & kResolveDepthStencilFlag) != 0;
}
bool hasDepthStencilUnresolveAttachment() const
{
......@@ -223,6 +215,9 @@ class alignas(4) RenderPassDesc final
void setFramebufferFetchMode(bool hasFramebufferFetch);
bool getFramebufferFetchMode() const { return mHasFramebufferFetch; }
void updateRenderToTexture(bool isRenderToTexture);
bool isRenderToTexture() const { return (mAttachmentFormats.back() & kIsRenderToTexture) != 0; }
angle::FormatID operator[](size_t index) const
{
ASSERT(index < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1);
......@@ -244,17 +239,14 @@ class alignas(4) RenderPassDesc final
// Whether each color attachment has a corresponding resolve attachment. Color resolve
// attachments can be used to optimize resolve through glBlitFramebuffer() as well as support
// GL_EXT_multisampled_render_to_texture and GL_EXT_multisampled_render_to_texture2.
//
// Note that depth/stencil resolve attachments require VK_KHR_depth_stencil_resolve which is
// currently not well supported, so ANGLE always takes a fallback path for them. When a resolve
// path is implemented for depth/stencil attachments, another bit must be made free
// (mAttachmentFormats is one element too large, so there are 8 bits there to take).
gl::DrawBufferMask mColorResolveAttachmentMask;
// Whether each color attachment with a corresponding resolve attachment should be initialized
// with said resolve attachment in an initial subpass. This is an optimization to avoid
// loadOp=LOAD on the implicit multisampled image used with multisampled-render-to-texture
// render targets. This operation is referred to as "unresolve".
//
// Unused when VK_EXT_multisampled_render_to_single_sampled is available.
gl::DrawBufferMask mColorUnresolveAttachmentMask;
// Color attachment formats are stored with their GL attachment indices. The depth/stencil
......@@ -289,10 +281,10 @@ class alignas(4) RenderPassDesc final
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;
static constexpr uint8_t kUnresolveDepthFlag = 0x20;
static constexpr uint8_t kUnresolveStencilFlag = 0x10;
static constexpr uint8_t kIsRenderToTexture = 0x80;
static constexpr uint8_t kResolveDepthStencilFlag = 0x40;
static constexpr uint8_t kUnresolveDepthFlag = 0x20;
static constexpr uint8_t kUnresolveStencilFlag = 0x10;
};
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
......@@ -1181,6 +1173,8 @@ class FramebufferDesc
uint32_t getLayerCount() const { return mLayerCount; }
void updateFramebufferFetchMode(bool hasFramebufferFetch);
void updateRenderToTexture(bool isRenderToTexture);
private:
void reset();
void update(uint32_t index, ImageOrBufferViewSubresourceSerial serial);
......@@ -1195,7 +1189,11 @@ class FramebufferDesc
// If the render pass contains an initial subpass to unresolve a number of attachments, the
// subpass description is derived from the following mask, specifying which attachments need
// to be unresolved. Includes both color and depth/stencil attachments.
FramebufferNonResolveAttachmentMask mUnresolveAttachmentMask;
uint16_t mUnresolveAttachmentMask : kMaxFramebufferNonResolveAttachments;
// Whether this is a multisampled-render-to-single-sampled framebuffer. Only used when using
// VK_EXT_multisampled_render_to_single_sampled. Only one bit is used and the rest is padding.
uint16_t mIsRenderToTexture : 16 - kMaxFramebufferNonResolveAttachments;
FramebufferAttachmentArray<ImageOrBufferViewSubresourceSerial> mSerials;
};
......
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