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/Caps.cpp b/src/libANGLE/Caps.cpp
index e7b0b96..7379705 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -175,6 +175,7 @@
compressedTextureETC(false),
sRGB(false),
depthTextureANGLE(false),
+ depthTextureOES(false),
depth32(false),
textureStorage(false),
textureNPOT(false),
@@ -665,6 +666,17 @@
return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
}
+// Check for GL_OES_depth_texture
+static bool DetermineDepthTextureOESSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT16,
+ GL_DEPTH_COMPONENT32_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true);
+}
+
// Check for GL_OES_depth32
static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
{
@@ -785,6 +797,7 @@
compressedEACRG11SignedTexture = DetermineEACRG11SignedTextureSupport(textureCaps);
sRGB = DetermineSRGBTextureSupport(textureCaps);
depthTextureANGLE = DetermineDepthTextureANGLESupport(textureCaps);
+ depthTextureOES = DetermineDepthTextureOESSupport(textureCaps);
depth32 = DetermineDepth32Support(textureCaps);
colorBufferFloatRGB = DetermineColorBufferFloatRGBSupport(textureCaps);
colorBufferFloatRGBA = DetermineColorBufferFloatRGBASupport(textureCaps);
@@ -847,6 +860,7 @@
map["GL_CHROMIUM_compressed_texture_etc"] = enableableExtension(&Extensions::compressedTextureETC);
map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGB);
map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextureANGLE);
+ map["GL_OES_depth_texture"] = esOnlyExtension(&Extensions::depthTextureOES);
map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
map["GL_EXT_texture_storage"] = enableableExtension(&Extensions::textureStorage);
map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNPOT);
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 08311de..db45c40 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -117,6 +117,9 @@
// GL_EXT_texture_compression_bptc
void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
+ // indicate if any depth texture extension is available
+ bool depthTextureAny() const { return (depthTextureANGLE || depthTextureOES); }
+
// ES2 Extension support
// GL_OES_element_index_uint
@@ -240,6 +243,9 @@
// GL_ANGLE_depth_texture
bool depthTextureANGLE;
+ // OES_depth_texture
+ bool depthTextureOES;
+
// GL_OES_depth32
// Allows DEPTH_COMPONENT32_OES as a valid Renderbuffer format.
bool depth32;
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index 1401322..9ab99d9 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -136,6 +136,13 @@
return extensions.*bool1 || extensions.*bool2;
}
+// Check support for any of three extensions
+template <ExtensionBool bool1, ExtensionBool bool2, ExtensionBool bool3>
+static bool RequireExtOrExtOrExt(const Version &, const Extensions &extensions)
+{
+ return extensions.*bool1 || extensions.*bool2 || extensions.*bool3;
+}
+
// R8, RG8
static bool SizedRGSupport(const Version &clientVersion, const Extensions &extensions)
{
@@ -785,12 +792,12 @@
AddRGBAFormat(&map, GL_RGB32F, true, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, SizedFloatRGBSupport, RequireExt<&Extensions::textureFloatLinear>, RequireExt<&Extensions::colorBufferFloatRGB>, NeverSupported );
AddRGBAFormat(&map, GL_RGBA32F, true, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, SizedFloatRGBASupport, RequireExt<&Extensions::textureFloatLinear>, SizedFloatRGBARenderableSupport, SizedFloatRGBARenderableSupport );
- // Depth stencil formats
+ // ANGLE Depth stencil formats
// | Internal format |sized| D |S | X | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer |
- AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16, true, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<1, 0>, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, RequireES<1, 0>, RequireES<1, 0> );
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16, true, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<1, 0>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireES<1, 0>, RequireES<1, 0> );
AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT24, true, 24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, RequireES<3, 0>, RequireES<3, 0> );
AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, RequireES<3, 0>, RequireES<3, 0> );
- AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depth32>, AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depth32> );
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32>, AlwaysSupported, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32>, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32>);
AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8, true, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, AlwaysSupported, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencil>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencil>);
AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8, true, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3, 0>, AlwaysSupported, RequireES<3, 0>, RequireES<3, 0> );
// STENCIL_INDEX8 is special-cased, see around the bottom of the list.
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
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 248a511..a6caffc 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -730,9 +730,7 @@
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH_STENCIL_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (context->getExtensions().depthTextureANGLE)
+ if (context->getExtensions().depthTextureAny())
{
context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
return false;
@@ -742,6 +740,21 @@
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
}
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (context->getExtensions().depthTextureAny() ||
+ context->getExtensions().packedDepthStencil)
+ {
+ context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ else
+ {
+ context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+ return false;
+ }
+ break;
default:
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
@@ -1497,7 +1510,9 @@
break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL_OES:
- if (!context->getExtensions().depthTextureANGLE)
+ if (!context->getExtensions().depthTextureANGLE &&
+ !(context->getExtensions().packedDepthStencil &&
+ context->getExtensions().depthTextureOES))
{
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
@@ -1509,15 +1524,18 @@
}
// OES_depth_texture supports loading depth data and multiple levels,
// but ANGLE_depth_texture does not
- if (pixels != nullptr)
+ if (!context->getExtensions().depthTextureOES)
{
- context->validationError(GL_INVALID_OPERATION, kPixelDataNotNull);
- return false;
- }
- if (level != 0)
- {
- context->validationError(GL_INVALID_OPERATION, kLevelNotZero);
- return false;
+ if (pixels != nullptr)
+ {
+ context->validationError(GL_INVALID_OPERATION, kPixelDataNotNull);
+ return false;
+ }
+ if (level != 0)
+ {
+ context->validationError(GL_INVALID_OPERATION, kLevelNotZero);
+ return false;
+ }
}
break;
default:
@@ -1587,8 +1605,16 @@
break;
case GL_DEPTH_COMPONENT:
+ if (!(context->getExtensions().depthTextureAny()))
+ {
+ context->validationError(GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
case GL_DEPTH_STENCIL:
- if (!context->getExtensions().depthTextureANGLE)
+ if (!(context->getExtensions().depthTextureANGLE ||
+ context->getExtensions().packedDepthStencil))
{
context->validationError(GL_INVALID_ENUM, kInvalidFormat);
return false;
@@ -1883,8 +1909,7 @@
break;
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (!context->getExtensions().depthTextureANGLE)
+ if (!(context->getExtensions().depthTextureAny()))
{
context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
return false;
@@ -1895,12 +1920,39 @@
return false;
}
// ANGLE_depth_texture only supports 1-level textures
- if (levels != 1)
+ if (!context->getExtensions().depthTextureOES)
{
- context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
- return false;
+ if (levels != 1)
+ {
+ context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
}
break;
+ case GL_DEPTH24_STENCIL8_OES:
+ if (!(context->getExtensions().depthTextureANGLE ||
+ (context->getExtensions().packedDepthStencil &&
+ context->getExtensions().textureStorage)))
+ {
+ context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+ return false;
+ }
+ if (target != TextureType::_2D)
+ {
+ context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
+ return false;
+ }
+ if (!context->getExtensions().packedDepthStencil)
+ {
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/src/tests/gl_tests/DepthStencilFormatsTest.cpp b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
index 67fdac9..eb3df59 100644
--- a/src/tests/gl_tests/DepthStencilFormatsTest.cpp
+++ b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
@@ -117,7 +117,9 @@
TEST_P(DepthStencilFormatsTest, DepthTexture)
{
- bool shouldHaveTextureSupport = IsGLExtensionEnabled("GL_ANGLE_depth_texture");
+ bool shouldHaveTextureSupport = (IsGLExtensionEnabled("GL_ANGLE_depth_texture") ||
+ IsGLExtensionEnabled("GL_OES_depth_texture"));
+
EXPECT_EQ(shouldHaveTextureSupport,
checkTexImageFormatSupport(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT));
EXPECT_EQ(shouldHaveTextureSupport,
@@ -140,14 +142,331 @@
EXPECT_EQ(shouldHaveRenderbufferSupport,
checkRenderbufferFormatSupport(GL_DEPTH24_STENCIL8_OES));
- bool shouldHaveTextureSupport = IsGLExtensionEnabled("GL_OES_packed_depth_stencil") &&
+ bool shouldHaveTextureSupport = (IsGLExtensionEnabled("GL_OES_packed_depth_stencil") &&
+ IsGLExtensionEnabled("GL_OES_depth_texture")) ||
IsGLExtensionEnabled("GL_ANGLE_depth_texture");
EXPECT_EQ(shouldHaveTextureSupport,
checkTexImageFormatSupport(GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES));
if (IsGLExtensionEnabled("GL_EXT_texture_storage"))
{
- EXPECT_EQ(shouldHaveTextureSupport, checkTexStorageFormatSupport(GL_DEPTH24_STENCIL8_OES));
+ bool shouldHaveTexStorageSupport = IsGLExtensionEnabled("GL_OES_packed_depth_stencil") ||
+ IsGLExtensionEnabled("GL_ANGLE_depth_texture");
+ EXPECT_EQ(shouldHaveTexStorageSupport,
+ checkTexStorageFormatSupport(GL_DEPTH24_STENCIL8_OES));
+ }
+}
+
+// This test will initialize a depth texture and then render with it and verify
+// pixel correctness.
+// This is modeled after webgl-depth-texture.html
+TEST_P(DepthStencilFormatsTest, DepthTextureRender)
+{
+ constexpr char kVS[] = R"(attribute vec4 a_position;
+void main()
+{
+ gl_Position = a_position;
+})";
+
+ constexpr char kFS[] = R"(precision mediump float;
+uniform sampler2D u_texture;
+uniform vec2 u_resolution;
+void main()
+{
+ vec2 texcoord = (gl_FragCoord.xy - vec2(0.5)) / (u_resolution - vec2(1.0));
+ gl_FragColor = texture2D(u_texture, texcoord);
+})";
+
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth_texture") &&
+ !IsGLExtensionEnabled("GL_ANGLE_depth_texture"));
+
+ // http://anglebug.com/3454
+ ANGLE_SKIP_TEST_IF(IsIntel() && IsWindows() && IsD3D9());
+
+ const int res = 2;
+ const int destRes = 4;
+ GLint resolution;
+
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
+
+ glUseProgram(program);
+ resolution = glGetUniformLocation(program, "u_resolution");
+ ASSERT_NE(-1, resolution);
+ glUniform2f(resolution, static_cast<float>(destRes), static_cast<float>(destRes));
+
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ float verts[] = {
+ 1, 1, 1, -1, 1, 0, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 0,
+ };
+ glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
+
+ // OpenGL ES does not have a FLIPY PixelStore attribute
+ // glPixelStorei(GL_UNPACK_FLIP)
+
+ enum ObjType
+ {
+ GL,
+ EXT
+ };
+ struct TypeInfo
+ {
+ ObjType obj;
+ GLuint attachment;
+ GLuint format;
+ GLuint type;
+ void *data;
+ int depthBits;
+ int stencilBits;
+ };
+
+ GLuint fakeData[10] = {0};
+
+ std::vector<TypeInfo> types = {
+ {ObjType::GL, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, fakeData, 16, 0},
+ {ObjType::GL, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, fakeData, 16, 0},
+ {ObjType::EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES,
+ fakeData, 24, 8},
+ };
+
+ for (const TypeInfo &type : types)
+ {
+ GLTexture cubeTex;
+ glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
+ ASSERT_GL_NO_ERROR();
+
+ std::vector<GLuint> targets{GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
+
+ for (const GLuint target : targets)
+ {
+ glTexImage2D(target, 0, type.format, 1, 1, 0, type.format, type.type, nullptr);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+
+ std::vector<GLuint> filterModes = {GL_LINEAR, GL_NEAREST};
+
+ const bool supportPackedDepthStencilFramebuffer = getClientMajorVersion() >= 3;
+
+ for (const GLuint filterMode : filterModes)
+ {
+ GLTexture tex;
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterMode);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterMode);
+
+ // test level > 0
+ glTexImage2D(GL_TEXTURE_2D, 1, type.format, 1, 1, 0, type.format, type.type, nullptr);
+ if (IsGLExtensionEnabled("GL_OES_depth_texture"))
+ {
+ EXPECT_GL_NO_ERROR();
+ }
+ else
+ {
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+
+ // test with data
+ glTexImage2D(GL_TEXTURE_2D, 0, type.format, 1, 1, 0, type.format, type.type, type.data);
+ if (IsGLExtensionEnabled("GL_OES_depth_texture"))
+ {
+ EXPECT_GL_NO_ERROR();
+ }
+ else
+ {
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+
+ // test copyTexImage2D
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, type.format, 0, 0, 1, 1, 0);
+ GLuint error = glGetError();
+ ASSERT_TRUE(error == GL_INVALID_ENUM || error == GL_INVALID_OPERATION);
+
+ // test real thing
+ glTexImage2D(GL_TEXTURE_2D, 0, type.format, res, res, 0, type.format, type.type,
+ nullptr);
+ EXPECT_GL_NO_ERROR();
+
+ // test texSubImage2D
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, type.format, type.type, type.data);
+ if (IsGLExtensionEnabled("GL_OES_depth_texture"))
+ {
+ EXPECT_GL_NO_ERROR();
+ }
+ else
+ {
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+ }
+
+ // test copyTexSubImage2D
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+ // test generateMipmap
+ glGenerateMipmap(GL_TEXTURE_2D);
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+
+ GLuint fbo = 0;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ if (type.depthBits > 0 && type.stencilBits > 0 && !supportPackedDepthStencilFramebuffer)
+ {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
+ EXPECT_GL_NO_ERROR();
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex,
+ 0);
+ EXPECT_GL_NO_ERROR();
+ }
+ else
+ {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, type.attachment, GL_TEXTURE_2D, tex, 0);
+ EXPECT_GL_NO_ERROR();
+ }
+
+ // Ensure DEPTH_BITS returns >= 16 bits for UNSIGNED_SHORT and UNSIGNED_INT, >= 24
+ // UNSIGNED_INT_24_8_WEBGL. If there is stencil, ensure STENCIL_BITS reports >= 8 for
+ // UNSIGNED_INT_24_8_WEBGL.
+
+ GLint depthBits = 0;
+ glGetIntegerv(GL_DEPTH_BITS, &depthBits);
+ EXPECT_GE(depthBits, type.depthBits);
+
+ GLint stencilBits = 0;
+ glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
+ EXPECT_GE(stencilBits, type.stencilBits);
+
+ // TODO: remove this check if the spec is updated to require these combinations to work.
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ // try adding a color buffer.
+ GLuint colorTex = 0;
+ glGenTextures(1, &colorTex);
+ glBindTexture(GL_TEXTURE_2D, colorTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res, res, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ nullptr);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ colorTex, 0);
+ EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ }
+
+ EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ // use the default texture to render with while we return to the depth texture.
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ /* Setup 2x2 depth texture:
+ * 1 0.6 0.8
+ * |
+ * 0 0.2 0.4
+ * 0---1
+ */
+ const GLfloat d00 = 0.2;
+ const GLfloat d01 = 0.4;
+ const GLfloat d10 = 0.6;
+ const GLfloat d11 = 0.8;
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0, 0, 1, 1);
+ glClearDepthf(d00);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glScissor(1, 0, 1, 1);
+ glClearDepthf(d10);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glScissor(0, 1, 1, 1);
+ glClearDepthf(d01);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glScissor(1, 1, 1, 1);
+ glClearDepthf(d11);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ // render the depth texture.
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glViewport(0, 0, destRes, destRes);
+ glBindTexture(GL_TEXTURE_2D, tex);
+ glDisable(GL_DITHER);
+ glEnable(GL_DEPTH_TEST);
+ glClearColor(1, 0, 0, 1);
+ glClearDepthf(1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ GLubyte actualPixels[destRes * destRes * 4];
+ glReadPixels(0, 0, destRes, destRes, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels);
+ const GLfloat eps = 0.002;
+ std::vector<GLfloat> expectedMin;
+ std::vector<GLfloat> expectedMax;
+ if (filterMode == GL_NEAREST)
+ {
+ GLfloat init[] = {d00, d00, d10, d10, d00, d00, d10, d10,
+ d01, d01, d11, d11, d01, d01, d11, d11};
+ expectedMin.insert(expectedMin.begin(), init, init + 16);
+ expectedMax.insert(expectedMax.begin(), init, init + 16);
+
+ for (int i = 0; i < 16; i++)
+ {
+ expectedMin[i] = expectedMin[i] - eps;
+ expectedMax[i] = expectedMax[i] + eps;
+ }
+ }
+ else
+ {
+ GLfloat initMin[] = {
+ d00 - eps, d00, d00, d10 - eps, d00, d00, d00, d10,
+ d00, d00, d00, d10, d01 - eps, d01, d01, d11 - eps,
+ };
+ GLfloat initMax[] = {
+ d00 + eps, d10, d10, d10 + eps, d01, d11, d11, d11,
+ d01, d11, d11, d11, d01 + eps, d11, d11, d11 + eps,
+ };
+ expectedMin.insert(expectedMin.begin(), initMin, initMin + 16);
+ expectedMax.insert(expectedMax.begin(), initMax, initMax + 16);
+ }
+ for (int yy = 0; yy < destRes; ++yy)
+ {
+ for (int xx = 0; xx < destRes; ++xx)
+ {
+ const int t = xx + destRes * yy;
+ const GLfloat was = (GLfloat)(actualPixels[4 * t] / 255.0); // 4bpp
+ const GLfloat eMin = expectedMin[t];
+ const GLfloat eMax = expectedMax[t];
+ EXPECT_TRUE(was >= eMin && was <= eMax)
+ << "At " << xx << ", " << yy << ", expected within [" << eMin << ", "
+ << eMax << "] was " << was;
+ }
+ }
+
+ // check limitations
+ // Note: What happens if current attachment type is GL_DEPTH_STENCIL_ATTACHMENT
+ // and you try to call glFramebufferTexture2D with GL_DEPTH_ATTACHMENT?
+ // The webGL test this code came from expected that to fail.
+ // I think due to this line in ES3 spec:
+ // GL_INVALID_OPERATION is generated if textarget and texture are not compatible
+ // However, that's not the behavior I'm seeing, nor does it seem that a depth_stencil
+ // buffer isn't compatible with a depth attachment (e.g. stencil is unused).
+ if (type.attachment == GL_DEPTH_ATTACHMENT)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, type.attachment, GL_TEXTURE_2D, 0, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
+ tex, 0);
+ EXPECT_GLENUM_NE(GL_NO_ERROR, glGetError());
+ EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ glClear(GL_DEPTH_BUFFER_BIT);
+ EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ EXPECT_GL_NO_ERROR();
+ }
+ }
}
}