Commit 137271ff by Sunny Sachanandani Committed by Commit Bot

Support specifying array slice for D3D11 texture EGLImage

Client can specify array slice for creating the SRV/RTV with EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE. Test: D3DTextureTest.TextureArrayImage* Bug: angleproject:5538, chromium:1116101 Change-Id: I81cb2823df2145f1d05ad1526b0e36d6a0724d5e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2628609Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
parent bb3adfa4
......@@ -87,6 +87,9 @@ Additions to Chapter 2 of the EGL 1.2 Specification (EGL Operation)
specified plane of <buffer>. See table egl.restrictions for acceptable
values.
If EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE is specified, it is used to access
the specified array slice of the texture array <buffer>.
If EGL_TEXTURE_OFFSET_X_ANGLE or EGL_TEXTURE_OFFSET_Y_ANGLE are specified,
they must be non-negative and are used to offset all rendering into the
surface including blits, clears and draws.
......@@ -199,7 +202,7 @@ Issues
1. What renderers allow the use of a multi-sampled texture?
PROPOSED: Mutli-sampled texture support is currently limited to D3D11.
PROPOSED: Multi-sampled texture support is currently limited to D3D11.
Additionally, the client is responsible for resolving the texture.
2. How does this extension interact with EXT_sRGB_write_control?
......@@ -230,6 +233,8 @@ Issues
Revision History
Version 8, 2021/01/13 - added support for texture array.
Version 7, 2021/01/12 - added support for NV12/P010/P016 planar formats.
Version 6, 2020/05/12 - added support for specifying texture offsets.
......
......@@ -24,10 +24,11 @@
#ifndef EGL_ANGLE_d3d_texture_client_buffer
#define EGL_ANGLE_d3d_texture_client_buffer 1
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
#define EGL_TEXTURE_OFFSET_X_ANGLE 0x3490
#define EGL_TEXTURE_OFFSET_Y_ANGLE 0x3491
#define EGL_D3D11_TEXTURE_PLANE_ANGLE 0x3492
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
#define EGL_TEXTURE_OFFSET_X_ANGLE 0x3490
#define EGL_TEXTURE_OFFSET_Y_ANGLE 0x3491
#define EGL_D3D11_TEXTURE_PLANE_ANGLE 0x3492
#define EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE 0x3493
#endif /* EGL_ANGLE_d3d_texture_client_buffer */
#ifndef EGL_ANGLE_software_display
......
......@@ -322,7 +322,7 @@ egl::Error DisplayD3D::validateClientBuffer(const egl::Config *config,
case EGL_D3D_TEXTURE_ANGLE:
return mRenderer->getD3DTextureInfo(config, static_cast<IUnknown *>(clientBuffer),
attribs, nullptr, nullptr, nullptr, nullptr,
nullptr);
nullptr, nullptr);
default:
return DisplayImpl::validateClientBuffer(config, buftype, clientBuffer, attribs);
......@@ -340,7 +340,7 @@ egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
{
return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
attribs, nullptr, nullptr, nullptr, nullptr,
nullptr);
nullptr, nullptr);
}
default:
......
......@@ -187,7 +187,8 @@ class RendererD3D : public BufferFactoryD3D
EGLint *height,
GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const = 0;
const angle::Format **angleFormat,
UINT *arraySlice) const = 0;
virtual egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const = 0;
......
......@@ -106,7 +106,7 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
{
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, mState.attributes,
&mFixedWidth, &mFixedHeight, nullptr, nullptr,
&mColorFormat));
&mColorFormat, nullptr));
if (mState.attributes.contains(EGL_GL_COLORSPACE))
{
if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
......
......@@ -29,7 +29,8 @@ egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
{
const angle::Format *angleFormat = nullptr;
ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), mAttribs,
&mWidth, &mHeight, &mSamples, &mFormat, &angleFormat));
&mWidth, &mHeight, &mSamples, &mFormat, &angleFormat,
&mArraySlice));
ID3D11Texture2D *texture =
d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer));
ASSERT(texture != nullptr);
......@@ -52,6 +53,8 @@ egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
mIsTexturable = (textureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) &&
(resourceUsage & DXGI_USAGE_SHADER_INPUT);
mIsTextureArray = (textureDesc.ArraySize > 1);
mYUV = (textureDesc.Format == DXGI_FORMAT_NV12 || textureDesc.Format == DXGI_FORMAT_P010 ||
textureDesc.Format == DXGI_FORMAT_P016);
......@@ -120,9 +123,34 @@ angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = formatInfo.rtvFormat;
rtvDesc.ViewDimension =
mSamples == 0 ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
if (mIsTextureArray)
{
if (mSamples == 0)
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = 0;
rtvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
rtvDesc.Texture2DArray.ArraySize = 1;
}
else
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
rtvDesc.Texture2DMSArray.FirstArraySlice = mArraySlice;
rtvDesc.Texture2DMSArray.ArraySize = 1;
}
}
else
{
if (mSamples == 0)
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0;
}
else
{
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
}
}
ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, mTexture.get(), &rtv));
rtv.setDebugName("getAttachmentRenderTarget.RTV");
......@@ -133,10 +161,36 @@ angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = formatInfo.srvFormat;
srvDesc.ViewDimension =
mSamples == 0 ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
if (mIsTextureArray)
{
if (mSamples == 0)
{
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MostDetailedMip = 0;
srvDesc.Texture2DArray.MipLevels = 1;
srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
srvDesc.Texture2DArray.ArraySize = 1;
}
else
{
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
srvDesc.Texture2DArray.ArraySize = 1;
}
}
else
{
if (mSamples == 0)
{
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
}
else
{
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
}
}
ANGLE_TRY(mRenderer->allocateResource(context11, srvDesc, mTexture.get(), &srv));
srv.setDebugName("getAttachmentRenderTarget.SRV");
......
......@@ -51,13 +51,15 @@ class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
TextureHelper11 mTexture;
gl::Format mFormat = gl::Format::Invalid();
bool mIsRenderable = false;
bool mIsTexturable = false;
bool mYUV = false;
EGLint mWidth = 0;
EGLint mHeight = 0;
GLsizei mSamples = 0;
gl::Format mFormat = gl::Format::Invalid();
bool mIsRenderable = false;
bool mIsTexturable = false;
bool mIsTextureArray = false;
bool mYUV = false;
EGLint mWidth = 0;
EGLint mHeight = 0;
GLsizei mSamples = 0;
UINT mArraySlice = 0;
std::unique_ptr<RenderTargetD3D> mRenderTarget;
};
......
......@@ -1419,7 +1419,8 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
EGLint *height,
GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const
const angle::Format **angleFormat,
UINT *arraySlice) const
{
angle::ComPtr<ID3D11Texture2D> d3dTexture =
d3d11::DynamicCastComObjectToComPtr<ID3D11Texture2D>(texture);
......@@ -1557,6 +1558,14 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
}
}
UINT textureArraySlice =
static_cast<UINT>(attribs.getAsInt(EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, 0));
if (textureArraySlice >= desc.ArraySize)
{
return egl::EglBadParameter()
<< "Invalid client buffer texture array slice: " << textureArraySlice;
}
if (width)
{
*width = imageWidth;
......@@ -1582,6 +1591,11 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
*angleFormat = textureAngleFormat;
}
if (arraySlice)
{
*arraySlice = textureArraySlice;
}
return egl::NoError();
}
......
......@@ -108,7 +108,8 @@ class Renderer11 : public RendererD3D
EGLint *height,
GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const override;
const angle::Format **angleFormat,
UINT *arraySlice) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
......
......@@ -732,7 +732,8 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
EGLint *height,
GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const
const angle::Format **angleFormat,
UINT *arraySlice) const
{
IDirect3DTexture9 *texture = nullptr;
if (FAILED(d3dTexture->QueryInterface(&texture)))
......@@ -801,6 +802,11 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
*angleFormat = &d3dFormatInfo.info();
}
if (arraySlice)
{
*arraySlice = 0;
}
return egl::NoError();
}
......
......@@ -81,7 +81,8 @@ class Renderer9 : public RendererD3D
EGLint *height,
GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const override;
const angle::Format **angleFormat,
UINT *arraySlice) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
......
......@@ -2955,6 +2955,16 @@ bool ValidateCreateImage(const ValidationContext *val,
}
break;
case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
if (!displayExtensions.imageD3D11Texture)
{
val->setError(EGL_BAD_ATTRIBUTE,
"EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
"EGL_ANGLE_image_d3d11_texture support.");
return false;
}
break;
case EGL_WIDTH:
case EGL_HEIGHT:
if (target != EGL_LINUX_DMA_BUF_EXT)
......
......@@ -1243,6 +1243,7 @@ TEST_P(D3DTextureTest, ClearTextureImage)
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
eglDestroyImageKHR(display, image);
d3d11_texture->Release();
}
......@@ -1292,6 +1293,7 @@ TEST_P(D3DTextureTest, NonRenderableTextureImage)
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
eglDestroyImageKHR(display, image);
d3d11_texture->Release();
}
......@@ -1426,6 +1428,82 @@ TEST_P(D3DTextureTest, RGBEmulationTextureImage)
glDeleteRenderbuffers(1, &rgbaRbo);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
eglDestroyImageKHR(display, image);
d3d11_texture->Release();
}
TEST_P(D3DTextureTest, TextureArrayImage)
{
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
window->makeCurrent();
const UINT bufferSize = 32;
const UINT arraySize = 4;
ID3D11Texture2D *d3d11_texture = nullptr;
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, arraySize, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
const unsigned char kRFill = 0x12;
const unsigned char kGFill = 0x23;
const unsigned char kBFill = 0x34;
const unsigned char kAFill = 0x45;
std::vector<unsigned char> imageData(bufferSize * bufferSize * 4, 0);
for (size_t i = 0; i < imageData.size(); i += 4)
{
imageData[i] = kRFill;
imageData[i + 1] = kGFill;
imageData[i + 2] = kBFill;
imageData[i + 3] = kAFill;
}
ID3D11DeviceContext *context = nullptr;
mD3D11Device->GetImmediateContext(&context);
ASSERT_NE(context, nullptr);
D3D11_BOX dstBox = {0, 0, 0, bufferSize, bufferSize, 1};
context->UpdateSubresource(d3d11_texture, arraySize - 1, &dstBox, imageData.data(),
bufferSize * 4, imageData.size());
const EGLint attribs[] = {EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, arraySize - 1, EGL_NONE};
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
ASSERT_EGL_SUCCESS();
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
ASSERT_GL_NO_ERROR();
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
ASSERT_GL_NO_ERROR();
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, kRFill,
kGFill, kBFill, kAFill);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
eglDestroyImageKHR(display, image);
d3d11_texture->Release();
}
......@@ -1634,10 +1712,13 @@ class D3DTextureYUVTest : public D3DTextureTest
}
ASSERT_GL_NO_ERROR();
glDeleteTextures(1, &uvTexture);
glDeleteProgram(textureExternalOESProgram);
glDeleteTextures(1, &yTexture);
glDeleteTextures(1, &uvTexture);
glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rbo);
eglDestroyImageKHR(display, yImage);
eglDestroyImageKHR(display, uvImage);
d3d11_texture->Release();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment