mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Metal: support OES_depth_texture
Also added Depth32 & Depth16 texture data upload tests. Bug: angleproject:2634 Change-Id: I103f1cda1dc915f0dc8b04f7aaa2d8c0f9220cda Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1919281 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
committed by
Commit Bot
parent
7587588595
commit
d1860ea17e
@@ -20,6 +20,12 @@ struct FeaturesMtl : FeatureSetBase
|
||||
Feature hasBaseVertexInstancedDraw = {
|
||||
"has_base_vertex_instanced_draw", FeatureCategory::MetalFeatures,
|
||||
"The renderer supports base vertex instanced draw", &members};
|
||||
|
||||
// Support depth texture filtering
|
||||
Feature hasDepthTextureFiltering = {
|
||||
"has_depth_texture_filtering", FeatureCategory::MetalFeatures,
|
||||
"The renderer supports depth texture's filtering other than nearest", &members};
|
||||
|
||||
// Non-uniform compute shader dispatch support, i.e. Group size is not necessarily to be fixed:
|
||||
Feature hasNonUniformDispatch = {
|
||||
"has_non_uniform_dispatch", FeatureCategory::MetalFeatures,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"src/libANGLE/renderer/metal/gen_mtl_format_table.py":
|
||||
"b6468446dd1da3e44ac9dd11690b5bf1",
|
||||
"src/libANGLE/renderer/metal/mtl_format_map.json":
|
||||
"c6f5b6dda11e456cfbcaeec53eb46fa0",
|
||||
"0166b70697732612bd46942e7ccf8e6e",
|
||||
"src/libANGLE/renderer/metal/mtl_format_table_autogen.mm":
|
||||
"706e07c2bf5b50fa031678a5c2372465"
|
||||
"8796be69461e2bb07db3b81b6ef24432"
|
||||
}
|
||||
@@ -1799,7 +1799,7 @@ void R11G11B10F::average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B1
|
||||
void D24S8::ReadDepthStencil(DepthStencil *dst, const D24S8 *src)
|
||||
{
|
||||
dst->depth = gl::normalizedToFloat<24>(src->D);
|
||||
dst->stencil = gl::getShiftedData<8, 24>(src->S);
|
||||
dst->stencil = src->S;
|
||||
}
|
||||
|
||||
void D24S8::WriteDepthStencil(D24S8 *dst, const DepthStencil *src)
|
||||
@@ -1810,22 +1810,24 @@ void D24S8::WriteDepthStencil(D24S8 *dst, const DepthStencil *src)
|
||||
|
||||
void S8::ReadDepthStencil(DepthStencil *dst, const S8 *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->depth = 0;
|
||||
dst->stencil = src->S;
|
||||
}
|
||||
|
||||
void S8::WriteDepthStencil(S8 *dst, const DepthStencil *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->S = src->stencil & 0xFF;
|
||||
}
|
||||
|
||||
void D16::ReadDepthStencil(DepthStencil *dst, const D16 *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->depth = gl::normalizedToFloat(src->D);
|
||||
dst->stencil = 0;
|
||||
}
|
||||
|
||||
void D16::WriteDepthStencil(D16 *dst, const DepthStencil *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->D = gl::floatToNormalized<uint16_t>(static_cast<float>(src->depth));
|
||||
}
|
||||
|
||||
void D24X8::ReadDepthStencil(DepthStencil *dst, const D24X8 *src)
|
||||
@@ -1835,7 +1837,7 @@ void D24X8::ReadDepthStencil(DepthStencil *dst, const D24X8 *src)
|
||||
|
||||
void D24X8::WriteDepthStencil(D24X8 *dst, const DepthStencil *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->D = gl::floatToNormalized<24, uint32_t>(static_cast<float>(src->depth));
|
||||
}
|
||||
|
||||
void D32F::ReadDepthStencil(DepthStencil *dst, const D32F *src)
|
||||
@@ -1845,23 +1847,24 @@ void D32F::ReadDepthStencil(DepthStencil *dst, const D32F *src)
|
||||
|
||||
void D32F::WriteDepthStencil(D32F *dst, const DepthStencil *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->D = static_cast<float>(src->depth);
|
||||
}
|
||||
|
||||
void D32::ReadDepthStencil(DepthStencil *dst, const D32 *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->depth = gl::normalizedToFloat(src->D);
|
||||
dst->stencil = 0;
|
||||
}
|
||||
|
||||
void D32::WriteDepthStencil(D32 *dst, const DepthStencil *src)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
dst->D = gl::floatToNormalized<uint32_t>(static_cast<float>(src->depth));
|
||||
}
|
||||
|
||||
void D32FS8X24::ReadDepthStencil(DepthStencil *dst, const D32FS8X24 *src)
|
||||
{
|
||||
dst->depth = src->D;
|
||||
dst->stencil = gl::getShiftedData<8, 24>(static_cast<uint32_t>(src->S));
|
||||
dst->stencil = src->S;
|
||||
}
|
||||
|
||||
void D32FS8X24::WriteDepthStencil(D32FS8X24 *dst, const DepthStencil *src)
|
||||
|
||||
@@ -726,8 +726,8 @@ static_assert(sizeof(R11G11B10F) == 4, "R11G11B10F struct not 32-bits.");
|
||||
|
||||
struct D24S8
|
||||
{
|
||||
uint32_t D : 24;
|
||||
uint32_t S : 8;
|
||||
uint32_t D : 24;
|
||||
|
||||
static void ReadDepthStencil(DepthStencil *dst, const D24S8 *src);
|
||||
static void WriteDepthStencil(D24S8 *dst, const DepthStencil *src);
|
||||
|
||||
@@ -347,7 +347,7 @@ class Framebuffer final : public angle::ObserverInterface,
|
||||
DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
|
||||
DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
|
||||
DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS,
|
||||
DIRTY_BIT_DEPTH_BUFFER_CONTENTS,
|
||||
DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
|
||||
DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
|
||||
DIRTY_BIT_DRAW_BUFFERS,
|
||||
DIRTY_BIT_READ_BUFFER,
|
||||
|
||||
@@ -614,11 +614,15 @@ void DisplayMtl::initializeFeatures()
|
||||
{
|
||||
// default values:
|
||||
mFeatures.hasBaseVertexInstancedDraw.enabled = true;
|
||||
mFeatures.hasDepthTextureFiltering.enabled = false;
|
||||
mFeatures.hasNonUniformDispatch.enabled = true;
|
||||
mFeatures.hasTextureSwizzle.enabled = false;
|
||||
mFeatures.allowSeparatedDepthStencilBuffers.enabled = false;
|
||||
|
||||
|
||||
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
mFeatures.hasDepthTextureFiltering.enabled = true;
|
||||
|
||||
// Texture swizzle is only supported if macos sdk 10.15 is present
|
||||
# if defined(__MAC_10_15)
|
||||
if (ANGLE_APPLE_AVAILABLE_XC(10.15, 13.0))
|
||||
|
||||
@@ -161,6 +161,7 @@ class TextureMtl : public TextureImpl
|
||||
|
||||
private:
|
||||
void releaseTexture(bool releaseImages);
|
||||
angle::Result ensureSamplerStateCreated(const gl::Context *context);
|
||||
// Ensure image at given index is created:
|
||||
angle::Result ensureImageCreated(const gl::Context *context, const gl::ImageIndex &index);
|
||||
angle::Result checkForEmulatedChannels(const gl::Context *context,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "libANGLE/renderer/metal/TextureMtl.h"
|
||||
|
||||
#include "common/Color.h"
|
||||
#include "common/MemoryBuffer.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/mathutil.h"
|
||||
@@ -114,6 +115,207 @@ gl::TextureType GetTextureImageType(gl::TextureType texType)
|
||||
}
|
||||
}
|
||||
|
||||
angle::Result CopyTextureContentsToStagingBuffer(ContextMtl *contextMtl,
|
||||
const angle::Format &textureAngleFormat,
|
||||
const angle::Format &stagingAngleFormat,
|
||||
const MTLSize ®ionSize,
|
||||
const uint8_t *data,
|
||||
size_t bytesPerRow,
|
||||
size_t *bufferRowPitchOut,
|
||||
size_t *buffer2DImageSizeOut,
|
||||
mtl::BufferRef *bufferOut)
|
||||
{
|
||||
// NOTE(hqle): 3D textures not supported yet.
|
||||
ASSERT(regionSize.depth == 1);
|
||||
|
||||
size_t stagingBufferRowPitch = regionSize.width * stagingAngleFormat.pixelBytes;
|
||||
size_t stagingBuffer2DImageSize = stagingBufferRowPitch * regionSize.height;
|
||||
size_t stagingBufferSize = stagingBuffer2DImageSize * regionSize.depth;
|
||||
mtl::BufferRef stagingBuffer;
|
||||
ANGLE_TRY(mtl::Buffer::MakeBuffer(contextMtl, stagingBufferSize, nullptr, &stagingBuffer));
|
||||
|
||||
uint8_t *pdst = stagingBuffer->map(contextMtl);
|
||||
|
||||
if (textureAngleFormat.id == stagingAngleFormat.id)
|
||||
{
|
||||
for (NSUInteger r = 0; r < regionSize.height; ++r)
|
||||
{
|
||||
const uint8_t *pCopySrc = data + r * bytesPerRow;
|
||||
uint8_t *pCopyDst = pdst + r * stagingBufferRowPitch;
|
||||
memcpy(pCopyDst, pCopySrc, stagingBufferRowPitch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is only for depth & stencil case.
|
||||
ASSERT(textureAngleFormat.depthBits || textureAngleFormat.stencilBits);
|
||||
ASSERT(textureAngleFormat.pixelReadFunction && stagingAngleFormat.pixelWriteFunction);
|
||||
|
||||
// cache to store read result of source pixel
|
||||
angle::DepthStencil depthStencilData;
|
||||
auto sourcePixelReadData = reinterpret_cast<uint8_t *>(&depthStencilData);
|
||||
ASSERT(textureAngleFormat.pixelBytes <= sizeof(depthStencilData));
|
||||
|
||||
for (NSUInteger r = 0; r < regionSize.height; ++r)
|
||||
{
|
||||
for (NSUInteger c = 0; c < regionSize.width; ++c)
|
||||
{
|
||||
const uint8_t *sourcePixelData =
|
||||
data + r * bytesPerRow + c * textureAngleFormat.pixelBytes;
|
||||
|
||||
uint8_t *destPixelData =
|
||||
pdst + r * stagingBufferRowPitch + c * stagingAngleFormat.pixelBytes;
|
||||
|
||||
textureAngleFormat.pixelReadFunction(sourcePixelData, sourcePixelReadData);
|
||||
stagingAngleFormat.pixelWriteFunction(sourcePixelReadData, destPixelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stagingBuffer->unmap(contextMtl);
|
||||
|
||||
*bufferOut = stagingBuffer;
|
||||
*bufferRowPitchOut = stagingBufferRowPitch;
|
||||
*buffer2DImageSizeOut = stagingBuffer2DImageSize;
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result UploadTextureContentsWithStagingBuffer(ContextMtl *contextMtl,
|
||||
const mtl::TextureRef &texture,
|
||||
const angle::Format &textureAngleFormat,
|
||||
MTLRegion region,
|
||||
uint32_t mipmapLevel,
|
||||
uint32_t slice,
|
||||
const uint8_t *data,
|
||||
size_t bytesPerRow)
|
||||
{
|
||||
ASSERT(texture && texture->valid());
|
||||
|
||||
ASSERT(!texture->isCPUAccessible());
|
||||
|
||||
ASSERT(!textureAngleFormat.depthBits || !textureAngleFormat.stencilBits);
|
||||
|
||||
// Compressed texture is not supporte atm
|
||||
ASSERT(!textureAngleFormat.isBlock);
|
||||
|
||||
// Copy data to staging buffer
|
||||
size_t stagingBufferRowPitch;
|
||||
size_t stagingBuffer2DImageSize;
|
||||
mtl::BufferRef stagingBuffer;
|
||||
ANGLE_TRY(CopyTextureContentsToStagingBuffer(
|
||||
contextMtl, textureAngleFormat, textureAngleFormat, region.size, data, bytesPerRow,
|
||||
&stagingBufferRowPitch, &stagingBuffer2DImageSize, &stagingBuffer));
|
||||
|
||||
// Copy staging buffer to texture.
|
||||
mtl::BlitCommandEncoder *encoder = contextMtl->getBlitCommandEncoder();
|
||||
encoder->copyBufferToTexture(stagingBuffer, 0, stagingBufferRowPitch, stagingBuffer2DImageSize,
|
||||
region.size, texture, slice, mipmapLevel, region.origin,
|
||||
MTLBlitOptionNone);
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
// Packed depth stencil upload using staging buffer
|
||||
angle::Result UploadPackedDepthStencilTextureContentsWithStagingBuffer(
|
||||
ContextMtl *contextMtl,
|
||||
const mtl::TextureRef &texture,
|
||||
const angle::Format &textureAngleFormat,
|
||||
MTLRegion region,
|
||||
uint32_t mipmapLevel,
|
||||
uint32_t slice,
|
||||
const uint8_t *data,
|
||||
size_t bytesPerRow)
|
||||
{
|
||||
ASSERT(texture && texture->valid());
|
||||
|
||||
ASSERT(!texture->isCPUAccessible());
|
||||
|
||||
ASSERT(textureAngleFormat.depthBits && textureAngleFormat.stencilBits);
|
||||
|
||||
// We have to split the depth & stencil data into 2 buffers.
|
||||
angle::FormatID stagingDepthBufferFormatId;
|
||||
angle::FormatID stagingStencilBufferFormatId;
|
||||
|
||||
switch (textureAngleFormat.id)
|
||||
{
|
||||
case angle::FormatID::D24_UNORM_S8_UINT:
|
||||
stagingDepthBufferFormatId = angle::FormatID::D24_UNORM_X8_UINT;
|
||||
stagingStencilBufferFormatId = angle::FormatID::S8_UINT;
|
||||
break;
|
||||
case angle::FormatID::D32_FLOAT_S8X24_UINT:
|
||||
stagingDepthBufferFormatId = angle::FormatID::D32_FLOAT;
|
||||
stagingStencilBufferFormatId = angle::FormatID::S8_UINT;
|
||||
break;
|
||||
default:
|
||||
ANGLE_MTL_UNREACHABLE(contextMtl);
|
||||
}
|
||||
|
||||
const angle::Format &angleStagingDepthFormat = angle::Format::Get(stagingDepthBufferFormatId);
|
||||
const angle::Format &angleStagingStencilFormat =
|
||||
angle::Format::Get(stagingStencilBufferFormatId);
|
||||
|
||||
size_t stagingDepthBufferRowPitch, stagingStencilBufferRowPitch;
|
||||
size_t stagingDepthBuffer2DImageSize, stagingStencilBuffer2DImageSize;
|
||||
mtl::BufferRef stagingDepthbuffer, stagingStencilBuffer;
|
||||
|
||||
ANGLE_TRY(CopyTextureContentsToStagingBuffer(
|
||||
contextMtl, textureAngleFormat, angleStagingDepthFormat, region.size, data, bytesPerRow,
|
||||
&stagingDepthBufferRowPitch, &stagingDepthBuffer2DImageSize, &stagingDepthbuffer));
|
||||
|
||||
ANGLE_TRY(CopyTextureContentsToStagingBuffer(
|
||||
contextMtl, textureAngleFormat, angleStagingStencilFormat, region.size, data, bytesPerRow,
|
||||
&stagingStencilBufferRowPitch, &stagingStencilBuffer2DImageSize, &stagingStencilBuffer));
|
||||
|
||||
mtl::BlitCommandEncoder *encoder = contextMtl->getBlitCommandEncoder();
|
||||
|
||||
encoder->copyBufferToTexture(stagingDepthbuffer, 0, stagingDepthBufferRowPitch,
|
||||
stagingDepthBuffer2DImageSize, region.size, texture, slice,
|
||||
mipmapLevel, region.origin, MTLBlitOptionDepthFromDepthStencil);
|
||||
encoder->copyBufferToTexture(stagingStencilBuffer, 0, stagingStencilBufferRowPitch,
|
||||
stagingStencilBuffer2DImageSize, region.size, texture, slice,
|
||||
mipmapLevel, region.origin, MTLBlitOptionStencilFromDepthStencil);
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result UploadTextureContents(const gl::Context *context,
|
||||
const mtl::TextureRef &texture,
|
||||
const angle::Format &textureAngleFormat,
|
||||
const MTLRegion ®ion,
|
||||
uint32_t mipmapLevel,
|
||||
uint32_t slice,
|
||||
const uint8_t *data,
|
||||
size_t bytesPerRow)
|
||||
{
|
||||
ASSERT(texture && texture->valid());
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
|
||||
if (texture->isCPUAccessible())
|
||||
{
|
||||
// If texture is CPU accessible, just call replaceRegion() directly.
|
||||
texture->replaceRegion(contextMtl, region, mipmapLevel, slice, data, bytesPerRow);
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
// Texture is not CPU accessible, we need to use staging buffer
|
||||
if (textureAngleFormat.depthBits && textureAngleFormat.stencilBits)
|
||||
{
|
||||
ANGLE_TRY(UploadPackedDepthStencilTextureContentsWithStagingBuffer(
|
||||
contextMtl, texture, textureAngleFormat, region, mipmapLevel, slice, data,
|
||||
bytesPerRow));
|
||||
}
|
||||
else
|
||||
{
|
||||
ANGLE_TRY(UploadTextureContentsWithStagingBuffer(contextMtl, texture, textureAngleFormat,
|
||||
region, mipmapLevel, slice, data,
|
||||
bytesPerRow));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// TextureMtl implementation
|
||||
@@ -123,8 +325,6 @@ TextureMtl::~TextureMtl() = default;
|
||||
|
||||
void TextureMtl::onDestroy(const gl::Context *context)
|
||||
{
|
||||
mMetalSamplerState = nil;
|
||||
|
||||
releaseTexture(true);
|
||||
}
|
||||
|
||||
@@ -132,7 +332,8 @@ void TextureMtl::releaseTexture(bool releaseImages)
|
||||
{
|
||||
mFormat = mtl::Format();
|
||||
|
||||
mNativeTexture = nullptr;
|
||||
mNativeTexture = nullptr;
|
||||
mMetalSamplerState = nil;
|
||||
|
||||
for (RenderTargetMtl &rt : mLayeredRenderTargets)
|
||||
{
|
||||
@@ -229,6 +430,42 @@ angle::Result TextureMtl::ensureTextureCreated(const gl::Context *context)
|
||||
}
|
||||
}
|
||||
|
||||
// Create sampler state
|
||||
ANGLE_TRY(ensureSamplerStateCreated(context));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
angle::Result TextureMtl::ensureSamplerStateCreated(const gl::Context *context)
|
||||
{
|
||||
if (mMetalSamplerState)
|
||||
{
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
DisplayMtl *displayMtl = contextMtl->getDisplay();
|
||||
|
||||
mtl::SamplerDesc samplerDesc(mState.getSamplerState());
|
||||
|
||||
if (mFormat.actualAngleFormat().depthBits &&
|
||||
!displayMtl->getFeatures().hasDepthTextureFiltering.enabled)
|
||||
{
|
||||
// On devices not supporting filtering for depth textures, we need to convert to nearest
|
||||
// here.
|
||||
samplerDesc.minFilter = MTLSamplerMinMagFilterNearest;
|
||||
samplerDesc.magFilter = MTLSamplerMinMagFilterNearest;
|
||||
if (samplerDesc.mipFilter != MTLSamplerMipFilterNotMipmapped)
|
||||
{
|
||||
samplerDesc.mipFilter = MTLSamplerMipFilterNearest;
|
||||
}
|
||||
|
||||
samplerDesc.maxAnisotropy = 1;
|
||||
}
|
||||
|
||||
mMetalSamplerState =
|
||||
displayMtl->getStateCache().getSamplerState(displayMtl->getMetalDevice(), samplerDesc);
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
@@ -508,8 +745,9 @@ angle::Result TextureMtl::generateMipmapCPU(const gl::Context *context)
|
||||
dstLevelData.get(), dstRowPitch, 0);
|
||||
|
||||
// Upload to texture
|
||||
mNativeTexture->replaceRegion(contextMtl, MTLRegionMake2D(0, 0, dstWidth, dstHeight),
|
||||
mip, layer, dstLevelData.get(), dstRowPitch);
|
||||
ANGLE_TRY(UploadTextureContents(context, mNativeTexture, angleFormat,
|
||||
MTLRegionMake2D(0, 0, dstWidth, dstHeight), mip, layer,
|
||||
dstLevelData.get(), dstRowPitch));
|
||||
|
||||
prevLevelWidth = dstWidth;
|
||||
prevLevelHeight = dstHeight;
|
||||
@@ -576,27 +814,14 @@ angle::Result TextureMtl::getAttachmentRenderTarget(const gl::Context *context,
|
||||
angle::Result TextureMtl::syncState(const gl::Context *context,
|
||||
const gl::Texture::DirtyBits &dirtyBits)
|
||||
{
|
||||
ContextMtl *contextMtl = mtl::GetImpl(context);
|
||||
|
||||
if (dirtyBits.none() && mMetalSamplerState)
|
||||
if (dirtyBits.any())
|
||||
{
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
DisplayMtl *display = contextMtl->getDisplay();
|
||||
|
||||
if (dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_RED) ||
|
||||
dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_GREEN) ||
|
||||
dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_BLUE) ||
|
||||
dirtyBits.test(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA))
|
||||
{
|
||||
// NOTE(hqle): Metal doesn't support swizzle on many devices. Skip for now.
|
||||
// Invalidate sampler state
|
||||
mMetalSamplerState = nil;
|
||||
}
|
||||
|
||||
ANGLE_TRY(ensureTextureCreated(context));
|
||||
|
||||
mMetalSamplerState = display->getStateCache().getSamplerState(
|
||||
display->getMetalDevice(), mtl::SamplerDesc(mState.getSamplerState()));
|
||||
ANGLE_TRY(ensureSamplerStateCreated(context));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
@@ -812,7 +1037,8 @@ angle::Result TextureMtl::setSubImageImpl(const gl::Context *context,
|
||||
}
|
||||
|
||||
// Upload to texture
|
||||
image->replaceRegion(contextMtl, mtlRegion, 0, 0, pixels, sourceRowPitch);
|
||||
ANGLE_TRY(UploadTextureContents(context, image, mFormat.actualAngleFormat(), mtlRegion, 0, 0,
|
||||
pixels, sourceRowPitch));
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
@@ -852,7 +1078,8 @@ angle::Result TextureMtl::convertAndSetSubImage(const gl::Context *context,
|
||||
false, false, false);
|
||||
|
||||
// Upload to texture
|
||||
image->replaceRegion(contextMtl, mtlRow, 0, 0, conversionRow.data(), dstRowPitch);
|
||||
ANGLE_TRY(UploadTextureContents(context, image, dstFormat, mtlRow, 0, 0,
|
||||
conversionRow.data(), dstRowPitch));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
@@ -1019,7 +1246,8 @@ angle::Result TextureMtl::copySubImageCPU(const gl::Context *context,
|
||||
conversionRow.data()));
|
||||
|
||||
// Upload to texture
|
||||
image->replaceRegion(contextMtl, mtlDstRowArea, 0, 0, conversionRow.data(), dstRowPitch);
|
||||
ANGLE_TRY(UploadTextureContents(context, image, dstFormat, mtlDstRowArea, 0, 0,
|
||||
conversionRow.data(), dstRowPitch));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
|
||||
@@ -274,6 +274,17 @@ class BlitCommandEncoder final : public CommandEncoder
|
||||
|
||||
BlitCommandEncoder &restart();
|
||||
|
||||
BlitCommandEncoder ©BufferToTexture(const BufferRef &src,
|
||||
size_t srcOffset,
|
||||
size_t srcBytesPerRow,
|
||||
size_t srcBytesPerImage,
|
||||
MTLSize srcSize,
|
||||
const TextureRef &dst,
|
||||
uint32_t dstSlice,
|
||||
uint32_t dstLevel,
|
||||
MTLOrigin dstOrigin,
|
||||
MTLBlitOption blitOption);
|
||||
|
||||
BlitCommandEncoder ©Texture(const TextureRef &dst,
|
||||
uint32_t dstSlice,
|
||||
uint32_t dstLevel,
|
||||
|
||||
@@ -840,6 +840,39 @@ BlitCommandEncoder &BlitCommandEncoder::restart()
|
||||
}
|
||||
}
|
||||
|
||||
BlitCommandEncoder &BlitCommandEncoder::copyBufferToTexture(const BufferRef &src,
|
||||
size_t srcOffset,
|
||||
size_t srcBytesPerRow,
|
||||
size_t srcBytesPerImage,
|
||||
MTLSize srcSize,
|
||||
const TextureRef &dst,
|
||||
uint32_t dstSlice,
|
||||
uint32_t dstLevel,
|
||||
MTLOrigin dstOrigin,
|
||||
MTLBlitOption blitOption)
|
||||
{
|
||||
if (!src || !dst)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
cmdBuffer().setReadDependency(src);
|
||||
cmdBuffer().setWriteDependency(dst);
|
||||
|
||||
[get() copyFromBuffer:src->get()
|
||||
sourceOffset:srcOffset
|
||||
sourceBytesPerRow:srcBytesPerRow
|
||||
sourceBytesPerImage:srcBytesPerImage
|
||||
sourceSize:srcSize
|
||||
toTexture:dst->get()
|
||||
destinationSlice:dstSlice
|
||||
destinationLevel:dstLevel
|
||||
destinationOrigin:dstOrigin
|
||||
options:blitOption];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BlitCommandEncoder &BlitCommandEncoder::copyTexture(const TextureRef &dst,
|
||||
uint32_t dstSlice,
|
||||
uint32_t dstLevel,
|
||||
|
||||
@@ -323,6 +323,10 @@ class Context : public ErrorHandler
|
||||
|
||||
#define ANGLE_MTL_TRY(context, test) ANGLE_MTL_CHECK(context, test, GL_INVALID_OPERATION)
|
||||
|
||||
#define ANGLE_MTL_UNREACHABLE(context) \
|
||||
UNREACHABLE(); \
|
||||
ANGLE_MTL_TRY(context, false)
|
||||
|
||||
} // namespace mtl
|
||||
} // namespace rx
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@
|
||||
"A32_FLOAT": "R32G32B32A32_FLOAT",
|
||||
"L32_FLOAT": "R32G32B32A32_FLOAT",
|
||||
"L32A32_FLOAT": "R32G32B32A32_FLOAT",
|
||||
"D24_UNORM_X8_UINT": "D32_FLOAT"
|
||||
"D24_UNORM_X8_UINT": "D32_FLOAT",
|
||||
"D32_UNORM": "D32_FLOAT"
|
||||
},
|
||||
"override_ios": {
|
||||
"D24_UNORM_S8_UINT": "D32_FLOAT_S8X24_UINT",
|
||||
|
||||
@@ -262,6 +262,11 @@ void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_)
|
||||
this->actualFormatId = angle::FormatID::D32_FLOAT;
|
||||
break;
|
||||
|
||||
case angle::FormatID::D32_UNORM:
|
||||
this->metalFormat = MTLPixelFormatDepth32Float;
|
||||
this->actualFormatId = angle::FormatID::D32_FLOAT;
|
||||
break;
|
||||
|
||||
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
case angle::FormatID::L16A16_FLOAT:
|
||||
if (metalDevice.depth24Stencil8PixelFormatSupported)
|
||||
|
||||
@@ -34,6 +34,14 @@ bool OverrideTextureCaps(const DisplayMtl *display, angle::FormatID formatId, gl
|
||||
case angle::FormatID::R8G8B8A8_UNORM_SRGB:
|
||||
case angle::FormatID::B8G8R8A8_UNORM:
|
||||
case angle::FormatID::B8G8R8A8_UNORM_SRGB:
|
||||
// NOTE: even though iOS devices don't support filtering depth textures, we still report as
|
||||
// supported here in order for the OES_depth_texture extension to be enabled.
|
||||
// During draw call, the filter modes will be converted to nearest.
|
||||
case angle::FormatID::D16_UNORM:
|
||||
case angle::FormatID::D24_UNORM_S8_UINT:
|
||||
case angle::FormatID::D32_FLOAT_S8X24_UINT:
|
||||
case angle::FormatID::D32_FLOAT:
|
||||
case angle::FormatID::D32_UNORM:
|
||||
caps->texturable = caps->filterable = caps->textureAttachment = caps->renderbuffer =
|
||||
true;
|
||||
return true;
|
||||
@@ -112,11 +120,13 @@ void GenerateTextureCapsMap(const FormatTable &formatTable,
|
||||
tmpTextureExtensions.compressedTexturePVRTCsRGB = true;
|
||||
}
|
||||
#endif
|
||||
tmpTextureExtensions.sRGB = true;
|
||||
tmpTextureExtensions.depth32 = true;
|
||||
tmpTextureExtensions.depth24OES = true;
|
||||
tmpTextureExtensions.rgb8rgba8 = true;
|
||||
tmpTextureExtensions.textureStorage = true;
|
||||
tmpTextureExtensions.sRGB = true;
|
||||
tmpTextureExtensions.depth32 = true;
|
||||
tmpTextureExtensions.depth24OES = true;
|
||||
tmpTextureExtensions.rgb8rgba8 = true;
|
||||
tmpTextureExtensions.textureStorage = true;
|
||||
tmpTextureExtensions.depthTextureOES = true;
|
||||
tmpTextureExtensions.depthTextureANGLE = true;
|
||||
|
||||
auto formatVerifier = [&](const gl::InternalFormat &internalFormatInfo) {
|
||||
angle::FormatID angleFormatId =
|
||||
@@ -146,14 +156,6 @@ void GenerateTextureCapsMap(const FormatTable &formatTable,
|
||||
textureCaps.sampleCounts.insert(0);
|
||||
textureCaps.sampleCounts.insert(1);
|
||||
|
||||
if (textureCaps.filterable && mtlFormat.actualFormatId == angle::FormatID::D32_FLOAT)
|
||||
{
|
||||
// Only MacOS support filterable for D32_FLOAT texture
|
||||
#if !TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
textureCaps.filterable = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
textureCapsMap.set(mtlFormat.intendedFormatId, textureCaps);
|
||||
|
||||
if (intendedAngleFormat.isBlock)
|
||||
|
||||
@@ -112,6 +112,9 @@ class Texture final : public Resource,
|
||||
|
||||
static TextureRef MakeFromMetal(id<MTLTexture> metalTexture);
|
||||
|
||||
// Allow CPU to read & write data directly to this texture?
|
||||
bool isCPUAccessible() const;
|
||||
|
||||
void replaceRegion(ContextMtl *context,
|
||||
MTLRegion region,
|
||||
uint32_t mipmapLevel,
|
||||
@@ -130,6 +133,8 @@ class Texture final : public Resource,
|
||||
TextureRef createCubeFaceView(uint32_t face);
|
||||
// Create a view of one slice at a level.
|
||||
TextureRef createSliceMipView(uint32_t slice, uint32_t level);
|
||||
// Create a view with different format
|
||||
TextureRef createViewWithDifferentFormat(MTLPixelFormat format);
|
||||
|
||||
MTLTextureType textureType() const;
|
||||
MTLPixelFormat pixelFormat() const;
|
||||
@@ -163,6 +168,7 @@ class Texture final : public Resource,
|
||||
bool supportTextureView);
|
||||
|
||||
// Create a texture view
|
||||
Texture(Texture *original, MTLPixelFormat format);
|
||||
Texture(Texture *original, MTLTextureType type, NSRange mipmapLevelRange, uint32_t slice);
|
||||
|
||||
void syncContent(ContextMtl *context);
|
||||
|
||||
@@ -201,6 +201,18 @@ Texture::Texture(ContextMtl *context,
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Texture(Texture *original, MTLPixelFormat format)
|
||||
: Resource(original),
|
||||
mColorWritableMask(original->mColorWritableMask) // Share color write mask property
|
||||
{
|
||||
ANGLE_MTL_OBJC_SCOPE
|
||||
{
|
||||
auto view = [original->get() newTextureViewWithPixelFormat:format];
|
||||
|
||||
set([view ANGLE_MTL_AUTORELEASE]);
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Texture(Texture *original, MTLTextureType type, NSRange mipmapLevelRange, uint32_t slice)
|
||||
: Resource(original),
|
||||
mColorWritableMask(original->mColorWritableMask) // Share color write mask property
|
||||
@@ -242,6 +254,17 @@ void Texture::syncContent(ContextMtl *context)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Texture::isCPUAccessible() const
|
||||
{
|
||||
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
||||
if (get().storageMode == MTLStorageModeManaged)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return get().storageMode == MTLStorageModeShared;
|
||||
}
|
||||
|
||||
void Texture::replaceRegion(ContextMtl *context,
|
||||
MTLRegion region,
|
||||
uint32_t mipmapLevel,
|
||||
@@ -253,6 +276,9 @@ void Texture::replaceRegion(ContextMtl *context,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(isCPUAccessible());
|
||||
|
||||
CommandQueue &cmdQueue = context->cmdQueue();
|
||||
|
||||
syncContent(context);
|
||||
@@ -279,6 +305,8 @@ void Texture::getBytes(ContextMtl *context,
|
||||
uint32_t mipmapLevel,
|
||||
uint8_t *dataOut)
|
||||
{
|
||||
ASSERT(isCPUAccessible());
|
||||
|
||||
CommandQueue &cmdQueue = context->cmdQueue();
|
||||
|
||||
syncContent(context);
|
||||
@@ -327,6 +355,11 @@ TextureRef Texture::createSliceMipView(uint32_t slice, uint32_t level)
|
||||
}
|
||||
}
|
||||
|
||||
TextureRef Texture::createViewWithDifferentFormat(MTLPixelFormat format)
|
||||
{
|
||||
return TextureRef(new Texture(this, format));
|
||||
}
|
||||
|
||||
MTLPixelFormat Texture::pixelFormat() const
|
||||
{
|
||||
return get().pixelFormat;
|
||||
|
||||
@@ -48,6 +48,10 @@ struct StencilDesc
|
||||
struct DepthStencilDesc
|
||||
{
|
||||
DepthStencilDesc();
|
||||
DepthStencilDesc(const DepthStencilDesc &src);
|
||||
DepthStencilDesc(DepthStencilDesc &&src);
|
||||
|
||||
DepthStencilDesc &operator=(const DepthStencilDesc &src);
|
||||
|
||||
bool operator==(const DepthStencilDesc &rhs) const;
|
||||
|
||||
@@ -78,9 +82,13 @@ struct DepthStencilDesc
|
||||
struct SamplerDesc
|
||||
{
|
||||
SamplerDesc();
|
||||
SamplerDesc(const SamplerDesc &src);
|
||||
SamplerDesc(SamplerDesc &&src);
|
||||
|
||||
explicit SamplerDesc(const gl::SamplerState &glState);
|
||||
|
||||
SamplerDesc &operator=(const SamplerDesc &src);
|
||||
|
||||
// Set default values. All filters are nearest, and addresModes are clamp to edge.
|
||||
void reset();
|
||||
|
||||
@@ -207,6 +215,10 @@ constexpr PrimitiveTopologyClass kPrimitiveTopologyClassPoint = MTLPrimitiveTopo
|
||||
struct RenderPipelineDesc
|
||||
{
|
||||
RenderPipelineDesc();
|
||||
RenderPipelineDesc(const RenderPipelineDesc &src);
|
||||
RenderPipelineDesc(RenderPipelineDesc &&src);
|
||||
|
||||
RenderPipelineDesc &operator=(const RenderPipelineDesc &src);
|
||||
|
||||
bool operator==(const RenderPipelineDesc &rhs) const;
|
||||
|
||||
|
||||
@@ -245,6 +245,20 @@ DepthStencilDesc::DepthStencilDesc()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
DepthStencilDesc::DepthStencilDesc(const DepthStencilDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
DepthStencilDesc::DepthStencilDesc(DepthStencilDesc &&src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
|
||||
DepthStencilDesc &DepthStencilDesc::operator=(const DepthStencilDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool DepthStencilDesc::operator==(const DepthStencilDesc &rhs) const
|
||||
{
|
||||
@@ -388,6 +402,14 @@ SamplerDesc::SamplerDesc()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
SamplerDesc::SamplerDesc(const SamplerDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
SamplerDesc::SamplerDesc(SamplerDesc &&src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
|
||||
SamplerDesc::SamplerDesc(const gl::SamplerState &glState) : SamplerDesc()
|
||||
{
|
||||
@@ -402,6 +424,12 @@ SamplerDesc::SamplerDesc(const gl::SamplerState &glState) : SamplerDesc()
|
||||
maxAnisotropy = static_cast<uint32_t>(glState.getMaxAnisotropy());
|
||||
}
|
||||
|
||||
SamplerDesc &SamplerDesc::operator=(const SamplerDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SamplerDesc::reset()
|
||||
{
|
||||
rAddressMode = MTLSamplerAddressModeClampToEdge;
|
||||
@@ -570,12 +598,28 @@ RenderPipelineDesc::RenderPipelineDesc()
|
||||
rasterizationEnabled = true;
|
||||
}
|
||||
|
||||
RenderPipelineDesc::RenderPipelineDesc(const RenderPipelineDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
|
||||
RenderPipelineDesc::RenderPipelineDesc(RenderPipelineDesc &&src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
}
|
||||
|
||||
RenderPipelineDesc &RenderPipelineDesc::operator=(const RenderPipelineDesc &src)
|
||||
{
|
||||
memcpy(this, &src, sizeof(*this));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool RenderPipelineDesc::operator==(const RenderPipelineDesc &rhs) const
|
||||
{
|
||||
return ANGLE_PROP_EQ(*this, rhs, vertexDescriptor) &&
|
||||
ANGLE_PROP_EQ(*this, rhs, outputDescriptor) &&
|
||||
|
||||
ANGLE_PROP_EQ(*this, rhs, inputPrimitiveTopology);
|
||||
// NOTE(hqle): Use a faster way to compare, i.e take into account
|
||||
// the number of active vertex attributes & render targets.
|
||||
// If that way is used, hash() method must be changed also.
|
||||
return memcmp(this, &rhs, sizeof(*this)) == 0;
|
||||
}
|
||||
|
||||
size_t RenderPipelineDesc::hash() const
|
||||
|
||||
@@ -704,14 +704,14 @@ TEST_P(DepthStencilFormatsTest, VerifyDepthStencilUploadData)
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glStencilFunc(GL_EQUAL, kStencilRef, 0xFF);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
drawQuad(program.get(), essl1_shaders::PositionAttrib(), 1.0f);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
@@ -735,6 +735,152 @@ TEST_P(DepthStencilFormatsTest, VerifyDepthStencilUploadData)
|
||||
EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::black);
|
||||
}
|
||||
|
||||
// Verify that depth texture's data can be uploaded correctly
|
||||
TEST_P(DepthStencilFormatsTest, VerifyDepth32UploadData)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth_texture"));
|
||||
|
||||
GLTexture tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// normalized 0.99 = 0xfd70a3d6
|
||||
std::vector<GLuint> depthData(1, 0xfd70a3d6);
|
||||
GLTexture rbDepth;
|
||||
glBindTexture(GL_TEXTURE_2D, rbDepth);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
|
||||
depthData.data());
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
GLFramebuffer fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rbDepth, 0);
|
||||
|
||||
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glClearColor(0, 1, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Fail Depth Test and color buffer is unchanged
|
||||
float depthValue = 0.98f;
|
||||
drawQuad(programRed.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
|
||||
// Pass Depth Test and draw red
|
||||
depthValue = 1.0f;
|
||||
drawQuad(programRed.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Change depth texture data
|
||||
glBindTexture(GL_TEXTURE_2D, rbDepth);
|
||||
depthData[0] = 0x7fffffff; // 0.5
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
|
||||
depthData.data());
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
|
||||
|
||||
// Fail Depth Test and color buffer is unchanged
|
||||
depthValue = 0.48f;
|
||||
drawQuad(programGreen.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
|
||||
glClearDepthf(0.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Pass Depth Test and draw blue
|
||||
depthValue = 0.01f;
|
||||
drawQuad(programBlue.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
// Verify that 16 bits depth texture's data can be uploaded correctly
|
||||
TEST_P(DepthStencilFormatsTest, VerifyDepth16UploadData)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth_texture"));
|
||||
|
||||
GLTexture tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// normalized 0.99 = 0xfd6f
|
||||
std::vector<GLushort> depthData(1, 0xfd6f);
|
||||
GLTexture rbDepth;
|
||||
glBindTexture(GL_TEXTURE_2D, rbDepth);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT,
|
||||
GL_UNSIGNED_SHORT, depthData.data());
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
GLFramebuffer fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rbDepth, 0);
|
||||
|
||||
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glClearColor(0, 1, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Fail Depth Test and color buffer is unchanged
|
||||
float depthValue = 0.98f;
|
||||
drawQuad(programRed.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
|
||||
// Pass Depth Test and draw red
|
||||
depthValue = 1.0f;
|
||||
drawQuad(programRed.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Change depth texture data
|
||||
glBindTexture(GL_TEXTURE_2D, rbDepth);
|
||||
depthData[0] = 0x7fff; // 0.5
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
|
||||
depthData.data());
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
|
||||
|
||||
// Fail Depth Test and color buffer is unchanged
|
||||
depthValue = 0.48f;
|
||||
drawQuad(programGreen.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
ANGLE_GL_PROGRAM(programBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
|
||||
glClearDepthf(0.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Pass Depth Test and draw blue
|
||||
depthValue = 0.01f;
|
||||
drawQuad(programBlue.get(), essl1_shaders::PositionAttrib(), depthValue * 2 - 1);
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST_ES2(DepthStencilFormatsTest);
|
||||
|
||||
Reference in New Issue
Block a user