Add support for OES_depth_texture
Note: Includes workaround for http://anglebug.com/3452 - some Android
devices do not indicate filtering support on VK_FORMAT_D16_UNORM.
Bug: angleproject:3103
Test: angle_end2end_tests --gtest_filter=DepthStencilFormatsTest.DepthTexture/*
angle_end2end_tests --gtest_filter=DepthStencilFormatsTest.PackedDepthStencil/*
angle_end2end_tests --gtest_filter=DepthStencilFormatsTest.DepthTextureRender/ES2_VULKAN
Change-Id: Ic325fb94ab0e619a17c2e149e0e0865fa4142f3a
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1575426
Commit-Queue: Courtney Goeltzenleuchter <courtneygo@google.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index f973864..01a74e5 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1653,6 +1653,10 @@
extensions->blendFuncExtended = true;
extensions->maxDualSourceDrawBuffers = 1;
+ // D3D11 cannot support reading depth texture as a luminance texture.
+ // It treats it as a red-channel-only texture.
+ extensions->depthTextureOES = false;
+
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
// support gl_FrontFacing.
diff --git a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index e039289..622ee42 100644
--- a/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -658,6 +658,10 @@
extensions->mapBuffer = false;
extensions->mapBufferRange = false;
+ // D3D does not allow depth textures to have more than one mipmap level OES_depth_texture
+ // allows for that so we can't implement full support with the D3D9 back end.
+ extensions->depthTextureOES = false;
+
// textureRG is emulated and not performant.
extensions->textureRG = false;
@@ -674,6 +678,7 @@
if (IsAMD(adapterId.VendorId))
{
extensions->depthTextureANGLE = false;
+ extensions->depthTextureOES = false;
}
}
else
@@ -710,14 +715,14 @@
extensions->robustBufferAccessBehavior = false;
extensions->blendMinMax = true;
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-feature-level-9-1-hardware
- extensions->floatBlend = false;
- extensions->framebufferBlit = true;
- extensions->framebufferMultisample = true;
- extensions->instancedArraysANGLE = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ extensions->floatBlend = false;
+ extensions->framebufferBlit = true;
+ extensions->framebufferMultisample = true;
+ extensions->instancedArraysANGLE = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
// D3D9 requires at least one attribute that has a divisor of 0, which isn't required by the EXT
// extension
- extensions->instancedArraysEXT = false;
- extensions->packReverseRowOrder = true;
+ extensions->instancedArraysEXT = false;
+ extensions->packReverseRowOrder = true;
extensions->standardDerivatives =
(deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
extensions->shaderTextureLOD = true;
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index 0cdb05f..feb6d15 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -221,9 +221,7 @@
ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() = default;
-ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state), mUniformBlocksOffsets{}
-{
-}
+ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state), mUniformBlocksOffsets{} {}
ProgramVk::~ProgramVk() = default;
@@ -998,8 +996,10 @@
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(image.recordCommands(contextVk, &srcLayoutChange));
- image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT,
- vk::ImageLayout::FragmentShaderReadOnly, srcLayoutChange);
+ VkImageAspectFlags aspectFlags = image.getAspectFlags();
+ ASSERT(aspectFlags != 0);
+ image.changeLayout(aspectFlags, vk::ImageLayout::FragmentShaderReadOnly,
+ srcLayoutChange);
}
image.addReadDependency(framebuffer);
@@ -1092,8 +1092,8 @@
descSet = mEmptyDescriptorSets[descriptorSetIndex];
}
- constexpr uint32_t kShaderTypeMin = static_cast<uint32_t>(gl::kGLES2ShaderTypeMin);
- constexpr uint32_t kShaderTypeMax = static_cast<uint32_t>(gl::kGLES2ShaderTypeMax);
+ constexpr uint32_t kShaderTypeMin = static_cast<uint32_t>(gl::kGLES2ShaderTypeMin);
+ constexpr uint32_t kShaderTypeMax = static_cast<uint32_t>(gl::kGLES2ShaderTypeMax);
constexpr uint32_t kShaderTypeCount = kShaderTypeMax - kShaderTypeMin + 1;
// Default uniforms are encompassed in a block per shader stage, and they are assigned
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index f46ff95..d8388a3 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -1320,6 +1320,11 @@
{
mFeatures.forceNonZeroScissor.enabled = true;
}
+
+ if (IsAndroid() && IsQualcomm(mPhysicalDeviceProperties.vendorID))
+ {
+ mFeatures.forceD16TexFilter.enabled = true;
+ }
}
void RendererVk::initPipelineCacheVkKey()
@@ -2284,6 +2289,12 @@
// Otherwise query the format features and cache it.
vkGetPhysicalDeviceFormatProperties(mPhysicalDevice, format, &deviceProperties);
+ // Workaround for some Android devices that don't indicate filtering
+ // support on D16_UNORM and they should.
+ if (mFeatures.forceD16TexFilter.enabled && format == VK_FORMAT_D16_UNORM)
+ {
+ deviceProperties.*features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+ }
}
return deviceProperties.*features & featureBits;
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index d329907..27b4598 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -1340,7 +1340,7 @@
// Lazily allocate the image view itself.
// Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle.
- return mImage->initLayerImageView(context, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ return mImage->initLayerImageView(context, mState.getType(), mImage->getAspectFlags(),
gl::SwizzleState(), *imageViewOut, getNativeImageLevel(level),
1, getNativeImageLayer(layer), 1);
}
@@ -1357,14 +1357,18 @@
const uint32_t levelCount,
vk::CommandBuffer *commandBuffer)
{
- const RendererVk *renderer = contextVk->getRenderer();
- const angle::Format &textureFormat = format.imageFormat();
+ RendererVk *renderer = contextVk->getRenderer();
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT;
-
- if (!textureFormat.isBlock)
+ if (renderer->hasImageFormatFeatureBits(format.vkImageFormat,
+ VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
+ {
+ imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ }
+ else if (renderer->hasImageFormatFeatureBits(format.vkImageFormat,
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
{
imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
@@ -1410,16 +1414,22 @@
uint32_t baseLevel = getNativeImageLevel(0);
uint32_t baseLayer = getNativeImageLayer(0);
uint32_t layerCount = mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1;
+ VkImageAspectFlags aspectFlags = vk::GetFormatAspectFlags(format.angleFormat());
+ // If we are reading a depth buffer, select only the depth component/aspect
+ if (aspectFlags & VK_IMAGE_ASPECT_DEPTH_BIT)
+ {
+ aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
+ }
- ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- mappedSwizzle, &mReadMipmapImageView, baseLevel,
- levelCount, baseLayer, layerCount));
- ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- mappedSwizzle, &mReadBaseLevelImageView, baseLevel, 1,
- baseLayer, layerCount));
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), aspectFlags, mappedSwizzle,
+ &mReadMipmapImageView, baseLevel, levelCount, baseLayer,
+ layerCount));
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), aspectFlags, mappedSwizzle,
+ &mReadBaseLevelImageView, baseLevel, 1, baseLayer,
+ layerCount));
if (!format.imageFormat().isBlock)
{
- ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), aspectFlags,
gl::SwizzleState(), &mDrawBaseLevelImageView,
baseLevel, 1, baseLayer, layerCount));
}
diff --git a/src/libANGLE/renderer/vulkan/vk_format_map.json b/src/libANGLE/renderer/vulkan/vk_format_map.json
index f6d0b26..f643025 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_map.json
+++ b/src/libANGLE/renderer/vulkan/vk_format_map.json
@@ -224,6 +224,10 @@
"buffer": "NONE",
"image": "D24_UNORM_S8_UINT"
},
+ "D32_UNORM": {
+ "buffer": "NONE",
+ "image": "D24_UNORM_S8_UINT"
+ },
"ETC1_R8G8B8_UNORM_BLOCK": {
"buffer": "NONE",
"image": "ETC2_R8G8B8_UNORM_BLOCK"
diff --git a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
index a49c852..4924520 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
@@ -695,7 +695,19 @@
break;
case angle::FormatID::D32_UNORM:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_DEPTH_COMPONENT32_OES;
+ {
+ static constexpr ImageFormatInitInfo kInfo[] = {
+ {angle::FormatID::D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, nullptr},
+ {angle::FormatID::D32_FLOAT_S8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, nullptr},
+ {angle::FormatID::D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, nullptr}};
+ initImageFallback(renderer, kInfo, ArraySize(kInfo));
+ }
+ bufferFormatID = angle::FormatID::NONE;
+ vkBufferFormat = VK_FORMAT_UNDEFINED;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = true;
break;
case angle::FormatID::EAC_R11G11_SNORM_BLOCK:
diff --git a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
index 378f1db..b2bb0bf 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
@@ -321,15 +321,28 @@
swizzleStateOut->swizzleAlpha = swizzleState.swizzleRed;
break;
default:
- // Set any missing channel to default in case the emulated format has that channel.
- swizzleStateOut->swizzleRed =
- angleFormat.redBits > 0 ? swizzleState.swizzleRed : GL_ZERO;
- swizzleStateOut->swizzleGreen =
- angleFormat.greenBits > 0 ? swizzleState.swizzleGreen : GL_ZERO;
- swizzleStateOut->swizzleBlue =
- angleFormat.blueBits > 0 ? swizzleState.swizzleBlue : GL_ZERO;
- swizzleStateOut->swizzleAlpha =
- angleFormat.alphaBits > 0 ? swizzleState.swizzleAlpha : GL_ONE;
+ if (angleFormat.hasDepthOrStencilBits())
+ {
+ swizzleStateOut->swizzleRed =
+ angleFormat.depthBits > 0 ? swizzleState.swizzleRed : GL_ZERO;
+ swizzleStateOut->swizzleGreen =
+ angleFormat.depthBits > 0 ? swizzleState.swizzleRed : GL_ZERO;
+ swizzleStateOut->swizzleBlue =
+ angleFormat.depthBits > 0 ? swizzleState.swizzleRed : GL_ZERO;
+ swizzleStateOut->swizzleAlpha = GL_ONE;
+ }
+ else
+ {
+ // Set any missing channel to default in case the emulated format has that channel.
+ swizzleStateOut->swizzleRed =
+ angleFormat.redBits > 0 ? swizzleState.swizzleRed : GL_ZERO;
+ swizzleStateOut->swizzleGreen =
+ angleFormat.greenBits > 0 ? swizzleState.swizzleGreen : GL_ZERO;
+ swizzleStateOut->swizzleBlue =
+ angleFormat.blueBits > 0 ? swizzleState.swizzleBlue : GL_ZERO;
+ swizzleStateOut->swizzleAlpha =
+ angleFormat.alphaBits > 0 ? swizzleState.swizzleAlpha : GL_ONE;
+ }
break;
}
}
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index bc6ad8a..7e094a9 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -1683,6 +1683,10 @@
void ImageHelper::clearDepthStencil(VkImageAspectFlags imageAspectFlags,
VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
vk::CommandBuffer *commandBuffer)
{
ASSERT(valid());
@@ -1691,10 +1695,10 @@
VkImageSubresourceRange clearRange = {
/*aspectMask*/ clearAspectFlags,
- /*baseMipLevel*/ 0,
- /*levelCount*/ 1,
- /*baseArrayLayer*/ 0,
- /*layerCount*/ 1,
+ /*baseMipLevel*/ baseMipLevel,
+ /*levelCount*/ levelCount,
+ /*baseArrayLayer*/ baseArrayLayer,
+ /*layerCount*/ layerCount,
};
commandBuffer->clearDepthStencilImage(mImage, getCurrentLayout(), depthStencil, 1, &clearRange);
@@ -1711,9 +1715,9 @@
if (isDepthStencil)
{
- ASSERT(mipLevel == 0 && baseArrayLayer == 0 && layerCount == 1);
const VkImageAspectFlags aspect = vk::GetDepthStencilAspectFlags(mFormat->imageFormat());
- clearDepthStencil(aspect, aspect, value.depthStencil, commandBuffer);
+ clearDepthStencil(aspect, aspect, value.depthStencil, mipLevel, 1, baseArrayLayer,
+ layerCount, commandBuffer);
}
else
{
@@ -1945,12 +1949,12 @@
loadFunction.loadFunction(extents.width, extents.height, extents.depth, source, inputRowPitch,
inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
- VkBufferImageCopy copy = {};
+ VkBufferImageCopy copy = {};
+ VkImageAspectFlags aspectFlags = GetFormatAspectFlags(vkFormat.imageFormat());
copy.bufferOffset = stagingOffset;
copy.bufferRowLength = bufferRowLength;
copy.bufferImageHeight = bufferImageHeight;
- copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy.imageSubresource.mipLevel = index.getLevelIndex();
copy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
copy.imageSubresource.layerCount = index.getLayerCount();
@@ -1958,7 +1962,19 @@
gl_vk::GetOffset(offset, ©.imageOffset);
gl_vk::GetExtent(extents, ©.imageExtent);
- mSubresourceUpdates.emplace_back(bufferHandle, copy);
+ // TODO: http://anglebug.com/3437 - need to split packed depth_stencil into
+ // staging buffers for upload.
+ // Ignore stencil for now.
+ if (aspectFlags & VK_IMAGE_ASPECT_STENCIL_BIT)
+ {
+ aspectFlags &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+
+ if (aspectFlags)
+ {
+ copy.imageSubresource.aspectMask = aspectFlags;
+ mSubresourceUpdates.emplace_back(bufferHandle, copy);
+ }
return angle::Result::Continue;
}
@@ -1984,6 +2000,9 @@
copy.imageSubresource.baseArrayLayer = imageIndex.hasLayer() ? imageIndex.getLayerIndex() : 0;
copy.imageSubresource.layerCount = imageIndex.getLayerCount();
+ // Note: Only support color now
+ ASSERT(getAspectFlags() == VK_IMAGE_ASPECT_COLOR_BIT);
+
gl_vk::GetOffset(offset, ©.imageOffset);
gl_vk::GetExtent(extents, ©.imageExtent);
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index 9672faa..754bb98 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -754,6 +754,10 @@
void clearDepthStencil(VkImageAspectFlags imageAspectFlags,
VkImageAspectFlags clearAspectFlags,
const VkClearDepthStencilValue &depthStencil,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
vk::CommandBuffer *commandBuffer);
struct SubresourceUpdate