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 ...@@ -208,6 +208,13 @@ struct FeaturesVk : FeatureSetBase
"extension with the independentResolveNone feature", "extension with the independentResolveNone feature",
&members, "http://anglebug.com/4836"}; &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 // VK_PRESENT_MODE_FIFO_KHR causes random timeouts on Linux Intel. http://anglebug.com/3153
Feature disableFifoPresentMode = {"disableFifoPresentMode", FeatureCategory::VulkanWorkarounds, Feature disableFifoPresentMode = {"disableFifoPresentMode", FeatureCategory::VulkanWorkarounds,
"VK_PRESENT_MODE_FIFO_KHR causes random timeouts", &members, "VK_PRESENT_MODE_FIFO_KHR causes random timeouts", &members,
......
...@@ -16,6 +16,36 @@ ...@@ -16,6 +16,36 @@
# include <vulkan/vulkan.h> # include <vulkan/vulkan.h>
#endif #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) #if !defined(ANGLE_SHARED_LIBVULKAN)
namespace rx namespace rx
......
...@@ -117,6 +117,10 @@ class FramebufferAttachment final ...@@ -117,6 +117,10 @@ class FramebufferAttachment final
bool isMultiview() const; bool isMultiview() const;
GLint getBaseViewIndex() const; GLint getBaseViewIndex() const;
bool isRenderToTexture() const
{
return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
}
GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; } GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
// The size of the underlying resource the attachment points to. The 'depth' value will // The size of the underlying resource the attachment points to. The 'depth' value will
......
...@@ -1919,11 +1919,7 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk) ...@@ -1919,11 +1919,7 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
// Add the resolve attachment, if any. // Add the resolve attachment, if any.
if (depthStencilRenderTarget->hasResolveAttachment()) if (depthStencilRenderTarget->hasResolveAttachment())
{ {
const vk::Format &format = depthStencilRenderTarget->getImageFormat(); mRenderPassDesc.packDepthStencilResolveAttachment();
bool hasDepth = format.intendedFormat().depthBits > 0;
bool hasStencil = format.intendedFormat().stencilBits > 0;
mRenderPassDesc.packDepthStencilResolveAttachment(hasDepth, hasStencil);
} }
} }
...@@ -1943,6 +1939,31 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk) ...@@ -1943,6 +1939,31 @@ void FramebufferVk::updateRenderPassDesc(ContextVk *contextVk)
mRenderPassDesc.setFramebufferFetchMode(programUsesFramebufferFetch); 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({}); mCurrentFramebufferDesc.updateUnresolveMask({});
} }
...@@ -2696,23 +2717,35 @@ gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk) ...@@ -2696,23 +2717,35 @@ gl::Rectangle FramebufferVk::getRotatedScissoredRenderArea(ContextVk *contextVk)
return rotatedScissoredArea; 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 // 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).
RenderTargetVk *firstRT = getFirstRenderTarget(); return std::max(lastAttachment ? lastAttachment->getSamples() : 1, 1);
return firstRT ? firstRT->getImageForRenderPass().getSamples() : 1;
} }
angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk) angle::Result FramebufferVk::flushDeferredClears(ContextVk *contextVk)
......
...@@ -141,7 +141,6 @@ class FramebufferVk : public FramebufferImpl ...@@ -141,7 +141,6 @@ class FramebufferVk : public FramebufferImpl
vk::CommandBuffer **commandBufferOut, vk::CommandBuffer **commandBufferOut,
bool *renderPassDescChangedOut); bool *renderPassDescChangedOut);
RenderTargetVk *getFirstRenderTarget() const;
GLint getSamples() const; GLint getSamples() const;
const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; } const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
......
...@@ -88,13 +88,15 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, ...@@ -88,13 +88,15 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context,
const bool isRenderToTexture = const bool isRenderToTexture =
mode == gl::MultisamplingMode::MultisampledRenderToTexture && mode == gl::MultisamplingMode::MultisampledRenderToTexture &&
(!isDepthStencilFormat || renderer->getFeatures().supportsDepthStencilResolve.enabled); (!isDepthStencilFormat || renderer->getFeatures().supportsDepthStencilResolve.enabled);
const bool hasRenderToTextureEXT =
renderer->getFeatures().supportsMultisampledRenderToSingleSampled.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 |
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
(isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT (isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
: VK_IMAGE_USAGE_COLOR_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; const uint32_t imageSamples = isRenderToTexture ? 1 : samples;
...@@ -112,7 +114,7 @@ angle::Result RenderbufferVk::setStorageImpl(const gl::Context *context, ...@@ -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 // 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 // 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. // automatically resolved into |mImage| and its contents are discarded.
if (isRenderToTexture) if (isRenderToTexture && !hasRenderToTextureEXT)
{ {
mMultisampledImageViews.init(renderer); mMultisampledImageViews.init(renderer);
......
...@@ -1121,6 +1121,10 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic ...@@ -1121,6 +1121,10 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
mDepthStencilResolveProperties.sType = mDepthStencilResolveProperties.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES; 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 = {};
mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; mDriverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
...@@ -1207,6 +1211,13 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic ...@@ -1207,6 +1211,13 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
vk::AddToPNextChain(&deviceProperties, &mDepthStencilResolveProperties); 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 // Query driver properties
if (ExtensionFound(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, deviceExtensionNames)) if (ExtensionFound(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, deviceExtensionNames))
{ {
...@@ -1253,6 +1264,7 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic ...@@ -1253,6 +1264,7 @@ void RendererVk::queryDeviceExtensionFeatures(const vk::ExtensionNameList &devic
mExternalMemoryHostProperties.pNext = nullptr; mExternalMemoryHostProperties.pNext = nullptr;
mShaderFloat16Int8Features.pNext = nullptr; mShaderFloat16Int8Features.pNext = nullptr;
mDepthStencilResolveProperties.pNext = nullptr; mDepthStencilResolveProperties.pNext = nullptr;
mMultisampledRenderToSingleSampledFeatures.pNext = nullptr;
mDriverProperties.pNext = nullptr; mDriverProperties.pNext = nullptr;
mSamplerYcbcrConversionFeatures.pNext = nullptr; mSamplerYcbcrConversionFeatures.pNext = nullptr;
} }
...@@ -1599,6 +1611,13 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1599,6 +1611,13 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME); 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 && if (mMemoryReportFeatures.deviceMemoryReport &&
(getFeatures().logMemoryReportCallbacks.enabled || (getFeatures().logMemoryReportCallbacks.enabled ||
getFeatures().logMemoryReportStats.enabled)) getFeatures().logMemoryReportStats.enabled))
...@@ -2156,7 +2175,13 @@ void RendererVk::initFeatures(DisplayVk *displayVk, ...@@ -2156,7 +2175,13 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve, ANGLE_FEATURE_CONDITION(&mFeatures, supportsDepthStencilResolve,
mFeatures.supportsRenderpass2.enabled && 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, ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
(!mFeatures.supportsTransformFeedbackExtension.enabled && (!mFeatures.supportsTransformFeedbackExtension.enabled &&
...@@ -2252,7 +2277,9 @@ void RendererVk::initFeatures(DisplayVk *displayVk, ...@@ -2252,7 +2277,9 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
// - Swiftshader on mac: http://anglebug.com/4937 // - Swiftshader on mac: http://anglebug.com/4937
// - Intel on windows: http://anglebug.com/5032 // - Intel on windows: http://anglebug.com/5032
// - AMD on windows: http://crbug.com/1132366 // - AMD on windows: http://crbug.com/1132366
ANGLE_FEATURE_CONDITION(&mFeatures, enableMultisampledRenderToTexture, ANGLE_FEATURE_CONDITION(
&mFeatures, enableMultisampledRenderToTexture,
mFeatures.supportsMultisampledRenderToSingleSampled.enabled ||
!(IsApple() && isSwiftShader) && !(IsWindows() && (isIntel || isAMD))); !(IsApple() && isSwiftShader) && !(IsWindows() && (isIntel || isAMD)));
// Feature disabled due to driver bugs: // Feature disabled due to driver bugs:
......
...@@ -418,6 +418,8 @@ class RendererVk : angle::NonCopyable ...@@ -418,6 +418,8 @@ class RendererVk : angle::NonCopyable
VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties; VkPhysicalDeviceExternalMemoryHostPropertiesEXT mExternalMemoryHostProperties;
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR mShaderFloat16Int8Features;
VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties; VkPhysicalDeviceDepthStencilResolvePropertiesKHR mDepthStencilResolveProperties;
VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT
mMultisampledRenderToSingleSampledFeatures;
VkPhysicalDeviceDriverPropertiesKHR mDriverProperties; VkPhysicalDeviceDriverPropertiesKHR mDriverProperties;
VkExternalFenceProperties mExternalFenceProperties; VkExternalFenceProperties mExternalFenceProperties;
VkExternalSemaphoreProperties mExternalSemaphoreProperties; VkExternalSemaphoreProperties mExternalSemaphoreProperties;
......
...@@ -2114,13 +2114,18 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context, ...@@ -2114,13 +2114,18 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
levelCount)); levelCount));
} }
const bool hasRenderToTextureEXT =
contextVk->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
// If samples > 1 here, we have a singlesampled texture that's being multisampled rendered to. // 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 // 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 // image. That multisampled image is used as color or depth/stencil attachment, while the
// original image is used as the resolve attachment. // original image is used as the resolve attachment.
const gl::RenderToTextureImageIndex renderToTextureIndex = const gl::RenderToTextureImageIndex renderToTextureIndex =
static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples)); hasRenderToTextureEXT
if (samples > 1 && !mMultisampledImages[renderToTextureIndex].valid()) ? gl::RenderToTextureImageIndex::Default
: static_cast<gl::RenderToTextureImageIndex>(PackSampleCount(samples));
if (samples > 1 && !mMultisampledImages[renderToTextureIndex].valid() && !hasRenderToTextureEXT)
{ {
ASSERT(mState.getBaseLevelDesc().samples <= 1); ASSERT(mState.getBaseLevelDesc().samples <= 1);
vk::ImageHelper *multisampledImage = &mMultisampledImages[renderToTextureIndex]; vk::ImageHelper *multisampledImage = &mMultisampledImages[renderToTextureIndex];
......
...@@ -651,6 +651,8 @@ angle::Result CreateRenderPass2(Context *context, ...@@ -651,6 +651,8 @@ angle::Result CreateRenderPass2(Context *context,
const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve, const VkSubpassDescriptionDepthStencilResolve &depthStencilResolve,
bool unresolveDepth, bool unresolveDepth,
bool unresolveStencil, bool unresolveStencil,
bool isRenderToTexture,
uint8_t renderToTextureSamples,
RenderPass *renderPass) RenderPass *renderPass)
{ {
// Convert the attachments to VkAttachmentDescription2. // Convert the attachments to VkAttachmentDescription2.
...@@ -735,9 +737,25 @@ angle::Result CreateRenderPass2(Context *context, ...@@ -735,9 +737,25 @@ angle::Result CreateRenderPass2(Context *context,
&subpassDescriptions[subpass]); &subpassDescriptions[subpass]);
} }
// Append the depth/stencil resolve attachment to the pNext chain of last subpass. VkMultisampledRenderToSingleSampledInfoEXT renderToTextureInfo = {};
ASSERT(depthStencilResolve.pDepthStencilResolveAttachment != nullptr); renderToTextureInfo.sType = VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT;
renderToTextureInfo.multisampledRenderToSingleSampledEnable = true;
renderToTextureInfo.rasterizationSamples = gl_vk::GetSamples(renderToTextureSamples);
renderToTextureInfo.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
renderToTextureInfo.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
// Append the depth/stencil resolve attachment to the pNext chain of last subpass, if any.
if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr)
{
ASSERT(!isRenderToTexture);
subpassDescriptions.back().pNext = &depthStencilResolve; subpassDescriptions.back().pNext = &depthStencilResolve;
}
else
{
ASSERT(isRenderToTexture);
ASSERT(subpassDescriptions.size() == 1);
subpassDescriptions.back().pNext = &renderToTextureInfo;
}
// Convert subpass dependencies to VkSubpassDependency2. // Convert subpass dependencies to VkSubpassDependency2.
std::vector<VkSubpassDependency2KHR> subpassDependencies(createInfo.dependencyCount); std::vector<VkSubpassDependency2KHR> subpassDependencies(createInfo.dependencyCount);
...@@ -909,7 +927,12 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk, ...@@ -909,7 +927,12 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED, VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED,
VK_IMAGE_LAYOUT_UNDEFINED, 0}; VK_IMAGE_LAYOUT_UNDEFINED, 0};
bool needInputAttachments = desc.getFramebufferFetchMode(); const bool needInputAttachments = desc.getFramebufferFetchMode();
const bool isRenderToTexture = desc.isRenderToTexture();
const uint8_t descSamples = desc.samples();
const uint8_t attachmentSamples = isRenderToTexture ? 1 : descSamples;
const uint8_t renderToTextureSamples = isRenderToTexture ? descSamples : 1;
// Unpack the packed and split representation into the format required by Vulkan. // Unpack the packed and split representation into the format required by Vulkan.
gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs; gl::DrawBuffersVector<VkAttachmentReference> colorAttachmentRefs;
...@@ -960,7 +983,7 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk, ...@@ -960,7 +983,7 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
colorAttachmentRefs.push_back(colorRef); colorAttachmentRefs.push_back(colorRef);
UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, desc.samples(), UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
ops[attachmentCount]); ops[attachmentCount]);
isColorInvalidated.set(colorIndexGL, ops[attachmentCount].isInvalidated); isColorInvalidated.set(colorIndexGL, ops[attachmentCount].isInvalidated);
...@@ -981,7 +1004,7 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk, ...@@ -981,7 +1004,7 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
depthStencilAttachmentRef.layout = ConvertImageLayoutToVkImageLayout( depthStencilAttachmentRef.layout = ConvertImageLayoutToVkImageLayout(
static_cast<ImageLayout>(ops[attachmentCount].initialLayout)); static_cast<ImageLayout>(ops[attachmentCount].initialLayout));
UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, desc.samples(), UnpackAttachmentDesc(&attachmentDescs[attachmentCount.get()], format, attachmentSamples,
ops[attachmentCount]); ops[attachmentCount]);
isDepthInvalidated = ops[attachmentCount].isInvalidated; isDepthInvalidated = ops[attachmentCount].isInvalidated;
...@@ -1113,12 +1136,8 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk, ...@@ -1113,12 +1136,8 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
if (desc.hasDepthStencilResolveAttachment()) if (desc.hasDepthStencilResolveAttachment())
{ {
depthStencilResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE; depthStencilResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
depthStencilResolve.depthResolveMode = desc.hasDepthResolveAttachment() depthStencilResolve.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT depthStencilResolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
: VK_RESOLVE_MODE_NONE;
depthStencilResolve.stencilResolveMode = desc.hasStencilResolveAttachment()
? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT
: VK_RESOLVE_MODE_NONE;
// If depth/stencil attachment is invalidated, try to remove its resolve attachment // If depth/stencil attachment is invalidated, try to remove its resolve attachment
// altogether. // altogether.
...@@ -1160,13 +1179,18 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk, ...@@ -1160,13 +1179,18 @@ angle::Result InitializeRenderPassFromDesc(ContextVk *contextVk,
createInfo.pDependencies = subpassDependencies.data(); createInfo.pDependencies = subpassDependencies.data();
} }
const bool hasRenderToTextureEXT =
renderer->getFeatures().supportsMultisampledRenderToSingleSampled.enabled;
// If depth/stencil resolve is used, we need to create the render pass with // If depth/stencil resolve is used, we need to create the render pass with
// vkCreateRenderPass2KHR. // vkCreateRenderPass2KHR. Same when using the VK_EXT_multisampled_render_to_single_sampled
if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr) // extension.
if (depthStencilResolve.pDepthStencilResolveAttachment != nullptr || hasRenderToTextureEXT)
{ {
ANGLE_TRY(CreateRenderPass2( ANGLE_TRY(CreateRenderPass2(contextVk, createInfo, depthStencilResolve,
contextVk, createInfo, depthStencilResolve, desc.hasDepthUnresolveAttachment(), desc.hasDepthUnresolveAttachment(),
desc.hasStencilUnresolveAttachment(), &renderPassHelper->getRenderPass())); desc.hasStencilUnresolveAttachment(), desc.isRenderToTexture(),
renderToTextureSamples, &renderPassHelper->getRenderPass()));
} }
else else
{ {
...@@ -1339,6 +1363,18 @@ void RenderPassDesc::setFramebufferFetchMode(bool hasFramebufferFetch) ...@@ -1339,6 +1363,18 @@ void RenderPassDesc::setFramebufferFetchMode(bool hasFramebufferFetch)
SetBitField(mHasFramebufferFetch, hasFramebufferFetch); SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
} }
void RenderPassDesc::updateRenderToTexture(bool isRenderToTexture)
{
if (isRenderToTexture)
{
mAttachmentFormats.back() |= kIsRenderToTexture;
}
else
{
mAttachmentFormats.back() &= ~kIsRenderToTexture;
}
}
void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID) void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
{ {
ASSERT(colorIndexGL < mAttachmentFormats.size()); ASSERT(colorIndexGL < mAttachmentFormats.size());
...@@ -1411,22 +1447,15 @@ void RenderPassDesc::removeColorUnresolveAttachment(size_t colorIndexGL) ...@@ -1411,22 +1447,15 @@ void RenderPassDesc::removeColorUnresolveAttachment(size_t colorIndexGL)
mColorUnresolveAttachmentMask.reset(colorIndexGL); mColorUnresolveAttachmentMask.reset(colorIndexGL);
} }
void RenderPassDesc::packDepthStencilResolveAttachment(bool resolveDepth, bool resolveStencil) void RenderPassDesc::packDepthStencilResolveAttachment()
{ {
ASSERT(hasDepthStencilAttachment()); ASSERT(hasDepthStencilAttachment());
ASSERT(!hasDepthStencilResolveAttachment()); ASSERT(!hasDepthStencilResolveAttachment());
static_assert((kDepthStencilFormatStorageMask & (kResolveDepthFlag | kResolveStencilFlag)) == 0, static_assert((kDepthStencilFormatStorageMask & kResolveDepthStencilFlag) == 0,
"Collision in depth/stencil format and flag bits"); "Collision in depth/stencil format and flag bits");
if (resolveDepth) mAttachmentFormats.back() |= kResolveDepthStencilFlag;
{
mAttachmentFormats.back() |= kResolveDepthFlag;
}
if (resolveStencil)
{
mAttachmentFormats.back() |= kResolveStencilFlag;
}
} }
void RenderPassDesc::packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil) void RenderPassDesc::packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil)
...@@ -2999,7 +3028,7 @@ void FramebufferDesc::updateColorResolve(uint32_t index, ImageOrBufferViewSubres ...@@ -2999,7 +3028,7 @@ void FramebufferDesc::updateColorResolve(uint32_t index, ImageOrBufferViewSubres
void FramebufferDesc::updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask) void FramebufferDesc::updateUnresolveMask(FramebufferNonResolveAttachmentMask unresolveMask)
{ {
mUnresolveAttachmentMask = unresolveMask; SetBitField(mUnresolveAttachmentMask, unresolveMask.bits());
} }
void FramebufferDesc::updateDepthStencil(ImageOrBufferViewSubresourceSerial serial) void FramebufferDesc::updateDepthStencil(ImageOrBufferViewSubresourceSerial serial)
...@@ -3015,7 +3044,8 @@ void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSeri ...@@ -3015,7 +3044,8 @@ void FramebufferDesc::updateDepthStencilResolve(ImageOrBufferViewSubresourceSeri
size_t FramebufferDesc::hash() const size_t FramebufferDesc::hash() const
{ {
return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^ return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * mMaxIndex) ^
mHasFramebufferFetch << 25 ^ mLayerCount << 16 ^ mUnresolveAttachmentMask.bits(); mHasFramebufferFetch << 26 ^ mIsRenderToTexture << 25 ^ mLayerCount << 16 ^
mUnresolveAttachmentMask;
} }
void FramebufferDesc::reset() void FramebufferDesc::reset()
...@@ -3023,7 +3053,8 @@ void FramebufferDesc::reset() ...@@ -3023,7 +3053,8 @@ void FramebufferDesc::reset()
mMaxIndex = 0; mMaxIndex = 0;
mHasFramebufferFetch = false; mHasFramebufferFetch = false;
mLayerCount = 0; mLayerCount = 0;
mUnresolveAttachmentMask.reset(); mUnresolveAttachmentMask = 0;
mIsRenderToTexture = 0;
memset(&mSerials, 0, sizeof(mSerials)); memset(&mSerials, 0, sizeof(mSerials));
} }
...@@ -3031,7 +3062,8 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const ...@@ -3031,7 +3062,8 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const
{ {
if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount || if (mMaxIndex != other.mMaxIndex || mLayerCount != other.mLayerCount ||
mUnresolveAttachmentMask != other.mUnresolveAttachmentMask || mUnresolveAttachmentMask != other.mUnresolveAttachmentMask ||
mHasFramebufferFetch != other.mHasFramebufferFetch) mHasFramebufferFetch != other.mHasFramebufferFetch ||
mIsRenderToTexture != other.mIsRenderToTexture)
{ {
return false; return false;
} }
...@@ -3055,7 +3087,7 @@ uint32_t FramebufferDesc::attachmentCount() const ...@@ -3055,7 +3087,7 @@ uint32_t FramebufferDesc::attachmentCount() const
FramebufferNonResolveAttachmentMask FramebufferDesc::getUnresolveAttachmentMask() const FramebufferNonResolveAttachmentMask FramebufferDesc::getUnresolveAttachmentMask() const
{ {
return mUnresolveAttachmentMask; return FramebufferNonResolveAttachmentMask(mUnresolveAttachmentMask);
} }
void FramebufferDesc::updateLayerCount(uint32_t layerCount) void FramebufferDesc::updateLayerCount(uint32_t layerCount)
...@@ -3068,6 +3100,11 @@ void FramebufferDesc::updateFramebufferFetchMode(bool hasFramebufferFetch) ...@@ -3068,6 +3100,11 @@ void FramebufferDesc::updateFramebufferFetchMode(bool hasFramebufferFetch)
SetBitField(mHasFramebufferFetch, hasFramebufferFetch); SetBitField(mHasFramebufferFetch, hasFramebufferFetch);
} }
void FramebufferDesc::updateRenderToTexture(bool isRenderToTexture)
{
SetBitField(mIsRenderToTexture, isRenderToTexture);
}
// SamplerDesc implementation. // SamplerDesc implementation.
SamplerDesc::SamplerDesc() SamplerDesc::SamplerDesc()
{ {
......
...@@ -161,7 +161,7 @@ class alignas(4) RenderPassDesc final ...@@ -161,7 +161,7 @@ class alignas(4) RenderPassDesc final
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. // 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 // Indicate that a depth/stencil attachment should take its data from the resolve attachment
// initially. // initially.
void packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil); void packDepthStencilUnresolveAttachment(bool unresolveDepth, bool unresolveStencil);
...@@ -189,15 +189,7 @@ class alignas(4) RenderPassDesc final ...@@ -189,15 +189,7 @@ class alignas(4) RenderPassDesc final
} }
bool hasDepthStencilResolveAttachment() const bool hasDepthStencilResolveAttachment() const
{ {
return (mAttachmentFormats.back() & (kResolveDepthFlag | kResolveStencilFlag)) != 0; return (mAttachmentFormats.back() & kResolveDepthStencilFlag) != 0;
}
bool hasDepthResolveAttachment() const
{
return (mAttachmentFormats.back() & kResolveDepthFlag) != 0;
}
bool hasStencilResolveAttachment() const
{
return (mAttachmentFormats.back() & kResolveStencilFlag) != 0;
} }
bool hasDepthStencilUnresolveAttachment() const bool hasDepthStencilUnresolveAttachment() const
{ {
...@@ -223,6 +215,9 @@ class alignas(4) RenderPassDesc final ...@@ -223,6 +215,9 @@ class alignas(4) RenderPassDesc final
void setFramebufferFetchMode(bool hasFramebufferFetch); void setFramebufferFetchMode(bool hasFramebufferFetch);
bool getFramebufferFetchMode() const { return mHasFramebufferFetch; } bool getFramebufferFetchMode() const { return mHasFramebufferFetch; }
void updateRenderToTexture(bool isRenderToTexture);
bool isRenderToTexture() const { return (mAttachmentFormats.back() & kIsRenderToTexture) != 0; }
angle::FormatID operator[](size_t index) const angle::FormatID operator[](size_t index) const
{ {
ASSERT(index < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1); ASSERT(index < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1);
...@@ -244,17 +239,14 @@ class alignas(4) RenderPassDesc final ...@@ -244,17 +239,14 @@ class alignas(4) RenderPassDesc final
// Whether each color attachment has a corresponding resolve attachment. Color resolve // Whether each color attachment has a corresponding resolve attachment. Color resolve
// attachments can be used to optimize resolve through glBlitFramebuffer() as well as support // 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. // 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; gl::DrawBufferMask mColorResolveAttachmentMask;
// Whether each color attachment with a corresponding resolve attachment should be initialized // 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 // 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 // loadOp=LOAD on the implicit multisampled image used with multisampled-render-to-texture
// render targets. This operation is referred to as "unresolve". // render targets. This operation is referred to as "unresolve".
//
// Unused when VK_EXT_multisampled_render_to_single_sampled is available.
gl::DrawBufferMask mColorUnresolveAttachmentMask; gl::DrawBufferMask mColorUnresolveAttachmentMask;
// Color attachment formats are stored with their GL attachment indices. The depth/stencil // Color attachment formats are stored with their GL attachment indices. The depth/stencil
...@@ -289,8 +281,8 @@ class alignas(4) RenderPassDesc final ...@@ -289,8 +281,8 @@ class alignas(4) RenderPassDesc final
static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7; static constexpr uint8_t kDepthStencilFormatStorageMask = 0x7;
// Flags stored in the upper 5 bits of mAttachmentFormats.back(). // Flags stored in the upper 5 bits of mAttachmentFormats.back().
static constexpr uint8_t kResolveDepthFlag = 0x80; static constexpr uint8_t kIsRenderToTexture = 0x80;
static constexpr uint8_t kResolveStencilFlag = 0x40; static constexpr uint8_t kResolveDepthStencilFlag = 0x40;
static constexpr uint8_t kUnresolveDepthFlag = 0x20; static constexpr uint8_t kUnresolveDepthFlag = 0x20;
static constexpr uint8_t kUnresolveStencilFlag = 0x10; static constexpr uint8_t kUnresolveStencilFlag = 0x10;
}; };
...@@ -1181,6 +1173,8 @@ class FramebufferDesc ...@@ -1181,6 +1173,8 @@ class FramebufferDesc
uint32_t getLayerCount() const { return mLayerCount; } uint32_t getLayerCount() const { return mLayerCount; }
void updateFramebufferFetchMode(bool hasFramebufferFetch); void updateFramebufferFetchMode(bool hasFramebufferFetch);
void updateRenderToTexture(bool isRenderToTexture);
private: private:
void reset(); void reset();
void update(uint32_t index, ImageOrBufferViewSubresourceSerial serial); void update(uint32_t index, ImageOrBufferViewSubresourceSerial serial);
...@@ -1195,7 +1189,11 @@ class FramebufferDesc ...@@ -1195,7 +1189,11 @@ class FramebufferDesc
// If the render pass contains an initial subpass to unresolve a number of attachments, the // 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 // subpass description is derived from the following mask, specifying which attachments need
// to be unresolved. Includes both color and depth/stencil attachments. // 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; 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