Commit a5ed56ee by Jamie Madill

D3D11: Mask off alpha channel for RGBA->RGB blits.

We emulate RGB8 in D3D11 with RGBA8 textures. Make sure when we blit that we don't copy the unused texture channel. BUG=angleproject:1245 TEST=dEQP-GLES3.functional.fbo.blit.* Change-Id: I805132fda984860a6d84ad4c1fc7169973938df9 Reviewed-on: https://chromium-review.googlesource.com/316010Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7a6a1ffe
......@@ -196,6 +196,23 @@ inline unsigned int GetSwizzleIndex(GLenum swizzle)
return colorIndex;
}
D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
{
D3D11_BLEND_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
D3D11_COLOR_WRITE_ENABLE_GREEN |
D3D11_COLOR_WRITE_ENABLE_BLUE;
return desc;
}
D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
......@@ -236,6 +253,7 @@ Blit11::Blit11(Renderer11 *renderer)
"Blit11 3D input layout"),
mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
mSwizzleCB(nullptr)
{
}
......@@ -729,9 +747,16 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
return gl::Error(GL_NO_ERROR);
}
gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
GLenum destFormat,
GLenum filter,
bool maskOffAlpha)
{
gl::Error error = initResources();
if (error.isError())
......@@ -784,7 +809,16 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
// Apply state
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
if (maskOffAlpha)
{
ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
ASSERT(blendState);
deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
}
else
{
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
}
deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
if (scissor)
......
......@@ -29,9 +29,16 @@ class Blit11 : angle::NonCopyable
gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
const gl::Rectangle *scissor, GLenum destFormat, GLenum filter);
gl::Error copyTexture(ID3D11ShaderResourceView *source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
ID3D11RenderTargetView *dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
GLenum destFormat,
GLenum filter,
bool maskOffAlpha);
gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
......@@ -167,6 +174,8 @@ class Blit11 : angle::NonCopyable
d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS;
d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS;
d3d11::LazyBlendState mAlphaMaskBlendState;
ID3D11Buffer *mSwizzleCB;
};
......
......@@ -2771,7 +2771,8 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::
// Use nearest filtering because source and destination are the same size for the direct
// copy
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
......@@ -2822,7 +2823,8 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl
// Use nearest filtering because source and destination are the same size for the direct
// copy
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
......@@ -2873,7 +2875,8 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::
// Use nearest filtering because source and destination are the same size for the direct
// copy
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
......@@ -2924,7 +2927,8 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const
// Use nearest filtering because source and destination are the same size for the direct
// copy
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
destFormat, GL_NEAREST, false);
if (error.isError())
{
return error;
......@@ -3809,11 +3813,32 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL);
bool wholeBufferCopy = !scissorNeeded &&
readRect.x == 0 && readRect.width == readSize.width &&
readRect.y == 0 && readRect.height == readSize.height &&
drawRect.x == 0 && drawRect.width == drawSize.width &&
drawRect.y == 0 && drawRect.height == drawSize.height;
const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat());
const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat());
const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
// Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
// emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
gl::Color<bool> colorMask;
colorMask.red = (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) &&
(dxgiFormatInfo.redBits > 0);
colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
(dxgiFormatInfo.greenBits > 0);
colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
(dxgiFormatInfo.blueBits > 0);
colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
(dxgiFormatInfo.alphaBits > 0);
// We only currently support masking off the alpha channel.
bool colorMaskingNeeded = colorMask.alpha;
ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
readRect.width == readSize.width && readRect.y == 0 &&
readRect.height == readSize.height && drawRect.x == 0 &&
drawRect.width == drawSize.width && drawRect.y == 0 &&
drawRect.height == drawSize.height;
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
......@@ -3824,14 +3849,13 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit);
gl::Error result(GL_NO_ERROR);
if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
(!(depthBlit || stencilBlit) || wholeBufferCopy))
!colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
{
UINT dstX = drawRect.x;
UINT dstY = drawRect.y;
......@@ -3901,9 +3925,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
}
else
{
GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format;
// We don't currently support masking off any other channel than alpha
bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
scissor, format, filter);
scissor, destFormatInfo.format, filter, maskOffAlpha);
}
}
......
......@@ -554,8 +554,9 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co
gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
Blit11 *blitter = mRenderer->getBlitter();
return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format,
GL_LINEAR, false);
}
void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
......
......@@ -1334,6 +1334,56 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
#endif
}
LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
size_t inputDescLen,
const BYTE *byteCode,
size_t byteCodeLen,
const char *debugName)
: mInputDesc(inputDescLen),
mByteCodeLen(byteCodeLen),
mByteCode(byteCode),
mDebugName(debugName)
{
memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
}
ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
{
checkAssociatedDevice(device);
if (mResource == nullptr)
{
HRESULT result =
device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
mByteCode, mByteCodeLen, &mResource);
ASSERT(SUCCEEDED(result));
UNUSED_ASSERTION_VARIABLE(result);
d3d11::SetDebugName(mResource, mDebugName);
}
return mResource;
}
LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
: mDesc(desc), mDebugName(debugName)
{
}
ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
{
checkAssociatedDevice(device);
if (mResource == nullptr)
{
HRESULT result = device->CreateBlendState(&mDesc, &mResource);
ASSERT(SUCCEEDED(result));
UNUSED_ASSERTION_VARIABLE(result);
d3d11::SetDebugName(mResource, mDebugName);
}
return mResource;
}
WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
{
WorkaroundsD3D workarounds;
......
......@@ -296,35 +296,17 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
const char *mDebugName;
};
inline LazyInputLayout::LazyInputLayout(
const D3D11_INPUT_ELEMENT_DESC *inputDesc,
size_t inputDescLen,
const BYTE *byteCode,
size_t byteCodeLen,
const char *debugName)
: mInputDesc(inputDescLen),
mByteCodeLen(byteCodeLen),
mByteCode(byteCode),
mDebugName(debugName)
class LazyBlendState final : public LazyResource<ID3D11BlendState>
{
memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
}
public:
LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
inline ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
{
checkAssociatedDevice(device);
ID3D11BlendState *resolve(ID3D11Device *device) override;
if (mResource == nullptr)
{
HRESULT result = device->CreateInputLayout(
&mInputDesc[0], static_cast<UINT>(mInputDesc.size()), mByteCode, mByteCodeLen, &mResource);
ASSERT(SUCCEEDED(result));
UNUSED_ASSERTION_VARIABLE(result);
d3d11::SetDebugName(mResource, mDebugName);
}
return mResource;
}
private:
D3D11_BLEND_DESC mDesc;
const char *mDebugName;
};
// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
// represent an entire buffer.
......
......@@ -45,10 +45,6 @@
// TODO(jmadill): Find why this fails when run in a certain sequence, but not singly.
1098 WIN : dEQP-GLES3.functional.uniform_api.random.50 = FAIL
// TODO(jmadill): This seems to fail only on certain NVidia configurations.
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba8_to_rgb565 = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgb565 = FAIL
// TODO(jmadill): triage these into permanent and temporary failures
1089 WIN : dEQP-GLES3.functional.shaders.functions.invalid.local_function_prototype_vertex = FAIL
......@@ -394,7 +390,6 @@
1097 WIN : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.rg16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.color.repeated_clear.sample.tex2d.r16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba8_to_rgb8 = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba8_to_rgba32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba8_to_rgba16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba8_to_r11f_g11f_b10f = FAIL
......@@ -416,7 +411,6 @@
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgb10_a2_to_rg16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgb10_a2_to_r32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgb10_a2_to_r16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba4_to_rgb8 = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba4_to_rgba32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba4_to_rgba16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.rgba4_to_r11f_g11f_b10f = FAIL
......@@ -459,7 +453,6 @@
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.r8_to_rg16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.r8_to_r32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.conversion.r8_to_r16f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgb8 = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgba32f = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgba32f_nearest_scale_blit_from_default = FAIL
1097 WIN : dEQP-GLES3.functional.fbo.blit.default_framebuffer.rgba32f_nearest_out_of_bounds_blit_from_default = FAIL
......
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