blob: 55f8f8f4d38f30990d7061de6ebaa0595f0447da [file] [log] [blame]
//
// Copyright 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Blit11.cpp: Texture copy utility class.
#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include <float.h>
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/trace.h"
namespace rx
{
namespace
{
// Include inline shaders in the anonymous namespace to make sure no symbols are exported
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clippedDestArea,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
size_t pixelSize,
const uint8_t *sourceData,
uint8_t *destData)
{
int srcHeightSubOne = (sourceArea.height - 1);
size_t copySize = pixelSize * destArea.width;
size_t srcOffset = sourceArea.x * pixelSize;
size_t destOffset = destArea.x * pixelSize;
for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
{
float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
// Interpolate using the original source rectangle to determine which row to sample from
// while clamping to the edges
unsigned int readRow = static_cast<unsigned int>(
gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
unsigned int writeRow = y;
const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
uint8_t *destRow = destData + writeRow * destRowPitch + destOffset;
memcpy(destRow, sourceRow, copySize);
}
}
void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clippedDestArea,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
ptrdiff_t readOffset,
ptrdiff_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
const uint8_t *sourceData,
uint8_t *destData)
{
auto xMax = clippedDestArea.x + clippedDestArea.width;
auto yMax = clippedDestArea.y + clippedDestArea.height;
for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
{
// Interpolate using the original source rectangle to determine which row to sample from
// while clamping to the edges
float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
unsigned int readRow =
static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
{
// Interpolate the original source rectangle to determine which column to sample
// from while clamping to the edges
float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
unsigned int readColumn = static_cast<unsigned int>(
gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1));
const uint8_t *sourcePixel =
sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
uint8_t *destPixel =
destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
memcpy(destPixel, sourcePixel, copySize);
}
}
}
void StretchedBlitNearest(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clipRect,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
ptrdiff_t readOffset,
ptrdiff_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
const uint8_t *sourceData,
uint8_t *destData)
{
gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
// Determine if entire rows can be copied at once instead of each individual pixel. There
// must be no out of bounds lookups, whole rows copies, and no scale.
if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
copySize == destPixelStride)
{
StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
destData);
}
else
{
StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
sourceRowPitch, destRowPitch, readOffset, writeOffset,
copySize, srcPixelStride, destPixelStride, sourceData,
destData);
}
}
using DepthStencilLoader = void(const float *, uint8_t *);
void LoadDepth16(const float *source, uint8_t *dest)
{
uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
memcpy(dest, &convertedDepth, 2u);
}
void LoadDepth24(const float *source, uint8_t *dest)
{
uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
memcpy(dest, &convertedDepth, 3u);
}
void LoadStencilHelper(const float *source, uint8_t *dest)
{
uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
memcpy(dest, &convertedStencil, 1u);
}
void LoadStencil8(const float *source, uint8_t *dest)
{
// STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
float zero = 0.0f;
LoadDepth24(&zero, &dest[0]);
LoadStencilHelper(source, &dest[3]);
}
void LoadDepth24Stencil8(const float *source, uint8_t *dest)
{
LoadDepth24(source, &dest[0]);
LoadStencilHelper(source, &dest[3]);
}
void LoadDepth32F(const float *source, uint8_t *dest)
{
memcpy(dest, source, sizeof(float));
}
void LoadDepth32FStencil8(const float *source, uint8_t *dest)
{
LoadDepth32F(source, &dest[0]);
LoadStencilHelper(source, &dest[4]);
}
template <DepthStencilLoader loader>
void CopyDepthStencil(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clippedDestArea,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
ptrdiff_t readOffset,
ptrdiff_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
const uint8_t *sourceData,
uint8_t *destData)
{
// No stretching or subregions are supported, only full blits.
ASSERT(sourceArea == destArea);
ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
sourceSize.depth == 1);
ASSERT(clippedDestArea.width == sourceSize.width &&
clippedDestArea.height == sourceSize.height);
ASSERT(readOffset == 0 && writeOffset == 0);
ASSERT(destArea.x == 0 && destArea.y == 0);
for (int row = 0; row < destArea.height; ++row)
{
for (int column = 0; column < destArea.width; ++column)
{
ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
loader(sourcePixel, destPixel);
}
}
}
void Depth32FStencil8ToDepth32F(const float *source, float *dest)
{
*dest = *source;
}
void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
{
uint32_t normDepth = source[0] & 0x00FFFFFF;
float floatDepth = gl::normalizedToFloat<24>(normDepth);
*dest = floatDepth;
}
void BlitD24S8ToD32F(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clippedDestArea,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
ptrdiff_t readOffset,
ptrdiff_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
const uint8_t *sourceData,
uint8_t *destData)
{
// No stretching or subregions are supported, only full blits.
ASSERT(sourceArea == destArea);
ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
sourceSize.depth == 1);
ASSERT(clippedDestArea.width == sourceSize.width &&
clippedDestArea.height == sourceSize.height);
ASSERT(readOffset == 0 && writeOffset == 0);
ASSERT(destArea.x == 0 && destArea.y == 0);
for (int row = 0; row < destArea.height; ++row)
{
for (int column = 0; column < destArea.width; ++column)
{
ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
float *destPixel =
reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
}
}
}
void BlitD32FS8ToD32F(const gl::Box &sourceArea,
const gl::Box &destArea,
const gl::Rectangle &clippedDestArea,
const gl::Extents &sourceSize,
unsigned int sourceRowPitch,
unsigned int destRowPitch,
ptrdiff_t readOffset,
ptrdiff_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
const uint8_t *sourceData,
uint8_t *destData)
{
// No stretching or subregions are supported, only full blits.
ASSERT(sourceArea == destArea);
ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
sourceSize.depth == 1);
ASSERT(clippedDestArea.width == sourceSize.width &&
clippedDestArea.height == sourceSize.height);
ASSERT(readOffset == 0 && writeOffset == 0);
ASSERT(destArea.x == 0 && destArea.y == 0);
for (int row = 0; row < destArea.height; ++row)
{
for (int column = 0; column < destArea.width; ++column)
{
ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
float *destPixel =
reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
}
}
}
Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
{
switch (internalFormat)
{
case GL_DEPTH_COMPONENT16:
return &CopyDepthStencil<LoadDepth16>;
case GL_DEPTH_COMPONENT24:
return &CopyDepthStencil<LoadDepth24>;
case GL_DEPTH_COMPONENT32F:
return &CopyDepthStencil<LoadDepth32F>;
case GL_STENCIL_INDEX8:
return &CopyDepthStencil<LoadStencil8>;
case GL_DEPTH24_STENCIL8:
return &CopyDepthStencil<LoadDepth24Stencil8>;
case GL_DEPTH32F_STENCIL8:
return &CopyDepthStencil<LoadDepth32FStencil8>;
default:
UNREACHABLE();
return nullptr;
}
}
inline void GenerateVertexCoords(const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const gl::Box &destArea,
const gl::Extents &destSize,
float *x1,
float *y1,
float *x2,
float *y2,
float *u1,
float *v1,
float *u2,
float *v2)
{
*x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
*y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
*x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
*y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
*u1 = sourceArea.x / float(sourceSize.width);
*v1 = sourceArea.y / float(sourceSize.height);
*u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
*v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
}
void Write2DVertices(const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const gl::Box &destArea,
const gl::Extents &destSize,
void *outVertices,
unsigned int *outStride,
unsigned int *outVertexCount,
D3D11_PRIMITIVE_TOPOLOGY *outTopology)
{
float x1, y1, x2, y2, u1, v1, u2, v2;
GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
&u2, &v2);
d3d11::PositionTexCoordVertex *vertices =
static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
*outStride = sizeof(d3d11::PositionTexCoordVertex);
*outVertexCount = 4;
*outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
}
void Write3DVertices(const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const gl::Box &destArea,
const gl::Extents &destSize,
void *outVertices,
unsigned int *outStride,
unsigned int *outVertexCount,
D3D11_PRIMITIVE_TOPOLOGY *outTopology)
{
ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
float x1, y1, x2, y2, u1, v1, u2, v2;
GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
&u2, &v2);
d3d11::PositionLayerTexCoord3DVertex *vertices =
static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
for (int i = 0; i < destSize.depth; i++)
{
float readDepth = (float)i / std::max(destSize.depth - 1, 1);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
}
*outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
*outVertexCount = destSize.depth * 6;
*outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
unsigned int GetSwizzleIndex(GLenum swizzle)
{
unsigned int colorIndex = 0;
switch (swizzle)
{
case GL_RED:
colorIndex = 0;
break;
case GL_GREEN:
colorIndex = 1;
break;
case GL_BLUE:
colorIndex = 2;
break;
case GL_ALPHA:
colorIndex = 3;
break;
case GL_ZERO:
colorIndex = 4;
break;
case GL_ONE:
colorIndex = 5;
break;
default:
UNREACHABLE();
break;
}
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},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
{
switch (formatSet.texFormat)
{
case DXGI_FORMAT_R32G8X24_TYPELESS:
return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
case DXGI_FORMAT_R24G8_TYPELESS:
return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
default:
UNREACHABLE();
return DXGI_FORMAT_UNKNOWN;
}
}
} // namespace
#include "libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc"
Blit11::Shader::Shader() = default;
Blit11::Shader::Shader(Shader &&other) = default;
Blit11::Shader::~Shader() = default;
Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default;
Blit11::Blit11(Renderer11 *renderer)
: mRenderer(renderer),
mResourcesInitialized(false),
mVertexBuffer(),
mPointSampler(),
mLinearSampler(),
mScissorEnabledRasterizerState(),
mScissorDisabledRasterizerState(),
mDepthStencilState(),
mQuad2DIL(quad2DLayout,
ArraySize(quad2DLayout),
g_VS_Passthrough2D,
ArraySize(g_VS_Passthrough2D),
"Blit11 2D input layout"),
mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
mDepthPS(g_PS_PassthroughDepth2D,
ArraySize(g_PS_PassthroughDepth2D),
"Blit11 2D depth pixel shader"),
mQuad3DIL(quad3DLayout,
ArraySize(quad3DLayout),
g_VS_Passthrough3D,
ArraySize(g_VS_Passthrough3D),
"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(),
mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
ArraySize(g_VS_ResolveDepthStencil),
"Blit11::mResolveDepthStencilVS"),
mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
ArraySize(g_PS_ResolveDepthStencil),
"Blit11::mResolveDepthStencilPS"),
mResolveStencilPS(g_PS_ResolveStencil,
ArraySize(g_PS_ResolveStencil),
"Blit11::mResolveStencilPS"),
mStencilSRV(),
mResolvedDepthStencilRTView()
{}
Blit11::~Blit11() {}
angle::Result Blit11::initResources(const gl::Context *context)
{
if (mResourcesInitialized)
{
return angle::Result::Continue;
}
ANGLE_TRACE_EVENT0("gpu.angle", "Blit11::initResources");
D3D11_BUFFER_DESC vbDesc;
vbDesc.ByteWidth =
static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
sizeof(d3d11::PositionTexCoordVertex)) *
6 * mRenderer->getNativeCaps().max3DTextureSize);
vbDesc.Usage = D3D11_USAGE_DYNAMIC;
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbDesc.MiscFlags = 0;
vbDesc.StructureByteStride = 0;
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(mRenderer->allocateResource(context11, vbDesc, &mVertexBuffer));
mVertexBuffer.setDebugName("Blit11 vertex buffer");
D3D11_SAMPLER_DESC pointSamplerDesc;
pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
pointSamplerDesc.MipLODBias = 0.0f;
pointSamplerDesc.MaxAnisotropy = 0;
pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
pointSamplerDesc.BorderColor[0] = 0.0f;
pointSamplerDesc.BorderColor[1] = 0.0f;
pointSamplerDesc.BorderColor[2] = 0.0f;
pointSamplerDesc.BorderColor[3] = 0.0f;
pointSamplerDesc.MinLOD = 0.0f;
pointSamplerDesc.MaxLOD = FLT_MAX;
ANGLE_TRY(mRenderer->allocateResource(context11, pointSamplerDesc, &mPointSampler));
mPointSampler.setDebugName("Blit11 point sampler");
D3D11_SAMPLER_DESC linearSamplerDesc;
linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
linearSamplerDesc.MipLODBias = 0.0f;
linearSamplerDesc.MaxAnisotropy = 0;
linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
linearSamplerDesc.BorderColor[0] = 0.0f;
linearSamplerDesc.BorderColor[1] = 0.0f;
linearSamplerDesc.BorderColor[2] = 0.0f;
linearSamplerDesc.BorderColor[3] = 0.0f;
linearSamplerDesc.MinLOD = 0.0f;
linearSamplerDesc.MaxLOD = FLT_MAX;
ANGLE_TRY(mRenderer->allocateResource(context11, linearSamplerDesc, &mLinearSampler));
mLinearSampler.setDebugName("Blit11 linear sampler");
// Use a rasterizer state that will not cull so that inverted quads will not be culled
D3D11_RASTERIZER_DESC rasterDesc;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.CullMode = D3D11_CULL_NONE;
rasterDesc.FrontCounterClockwise = FALSE;
rasterDesc.DepthBias = 0;
rasterDesc.SlopeScaledDepthBias = 0.0f;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
rasterDesc.ScissorEnable = TRUE;
ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorEnabledRasterizerState));
mScissorEnabledRasterizerState.setDebugName("Blit11 scissoring rasterizer state");
rasterDesc.ScissorEnable = FALSE;
ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorDisabledRasterizerState));
mScissorDisabledRasterizerState.setDebugName("Blit11 no scissoring rasterizer state");
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
depthStencilDesc.DepthEnable = TRUE;
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.StencilEnable = FALSE;
depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mDepthStencilState));
mDepthStencilState.setDebugName("Blit11 depth stencil state");
D3D11_BUFFER_DESC swizzleBufferDesc;
swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
swizzleBufferDesc.MiscFlags = 0;
swizzleBufferDesc.StructureByteStride = 0;
ANGLE_TRY(mRenderer->allocateResource(context11, swizzleBufferDesc, &mSwizzleCB));
mSwizzleCB.setDebugName("Blit11 swizzle constant buffer");
mResourcesInitialized = true;
return angle::Result::Continue;
}
// static
Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
D3D11_SRV_DIMENSION dimensionality)
{
switch (dimensionality)
{
case D3D11_SRV_DIMENSION_TEXTURE2D:
switch (type)
{
case GL_FLOAT:
return SWIZZLESHADER_2D_FLOAT;
case GL_UNSIGNED_INT:
return SWIZZLESHADER_2D_UINT;
case GL_INT:
return SWIZZLESHADER_2D_INT;
default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
}
case D3D11_SRV_DIMENSION_TEXTURECUBE:
switch (type)
{
case GL_FLOAT:
return SWIZZLESHADER_CUBE_FLOAT;
case GL_UNSIGNED_INT:
return SWIZZLESHADER_CUBE_UINT;
case GL_INT:
return SWIZZLESHADER_CUBE_INT;
default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
}
case D3D11_SRV_DIMENSION_TEXTURE3D:
switch (type)
{
case GL_FLOAT:
return SWIZZLESHADER_3D_FLOAT;
case GL_UNSIGNED_INT:
return SWIZZLESHADER_3D_UINT;
case GL_INT:
return SWIZZLESHADER_3D_INT;
default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
}
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
switch (type)
{
case GL_FLOAT:
return SWIZZLESHADER_ARRAY_FLOAT;
case GL_UNSIGNED_INT:
return SWIZZLESHADER_ARRAY_UINT;
case GL_INT:
return SWIZZLESHADER_ARRAY_INT;
default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
}
default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
}
}
angle::Result Blit11::getShaderSupport(const gl::Context *context,
const Shader &shader,
Blit11::ShaderSupport *supportOut)
{
Context11 *context11 = GetImplAs<Context11>(context);
switch (shader.dimension)
{
case SHADER_2D:
{
ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
supportOut->inputLayout = &mQuad2DIL.getObj();
supportOut->vertexShader = &mQuad2DVS.getObj();
supportOut->geometryShader = nullptr;
supportOut->vertexWriteFunction = Write2DVertices;
break;
}
case SHADER_3D:
case SHADER_2DARRAY:
{
ANGLE_TRY(mQuad3DIL.resolve(context11, mRenderer));
ANGLE_TRY(mQuad3DVS.resolve(context11, mRenderer));
ANGLE_TRY(mQuad3DGS.resolve(context11, mRenderer));
supportOut->inputLayout = &mQuad3DIL.getObj();
supportOut->vertexShader = &mQuad3DVS.getObj();
supportOut->geometryShader = &mQuad3DGS.getObj();
supportOut->vertexWriteFunction = Write3DVertices;
break;
}
default:
UNREACHABLE();
}
return angle::Result::Continue;
}
angle::Result Blit11::swizzleTexture(const gl::Context *context,
const d3d11::SharedSRV &source,
const d3d11::RenderTargetView &dest,
const gl::Extents &size,
const gl::SwizzleState &swizzleTarget)
{
ANGLE_TRY(initResources(context));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
source.get()->GetDesc(&sourceSRVDesc);
GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
if (componentType == GL_NONE)
{
// We're swizzling the depth component of a depth-stencil texture.
switch (sourceSRVDesc.Format)
{
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
componentType = GL_UNSIGNED_NORMALIZED;
break;
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
componentType = GL_FLOAT;
break;
default:
UNREACHABLE();
break;
}
}
GLenum shaderType = GL_NONE;
switch (componentType)
{
case GL_UNSIGNED_NORMALIZED:
case GL_SIGNED_NORMALIZED:
case GL_FLOAT:
shaderType = GL_FLOAT;
break;
case GL_INT:
shaderType = GL_INT;
break;
case GL_UNSIGNED_INT:
shaderType = GL_UNSIGNED_INT;
break;
default:
UNREACHABLE();
break;
}
const Shader *shader = nullptr;
ANGLE_TRY(getSwizzleShader(context, shaderType, sourceSRVDesc.ViewDimension, &shader));
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
&mappedResource));
ShaderSupport support;
ANGLE_TRY(getShaderSupport(context, *shader, &support));
UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
gl::Box area(0, 0, 0, size.width, size.height, size.depth);
support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
&topology);
deviceContext->Unmap(mVertexBuffer.get(), 0);
// Set constant buffer
ANGLE_TRY(mRenderer->mapResource(context, mSwizzleCB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
&mappedResource));
unsigned int *swizzleIndices = static_cast<unsigned int *>(mappedResource.pData);
swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed);
swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen);
swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue);
swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
deviceContext->Unmap(mSwizzleCB.get(), 0);
StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply constant buffer
stateManager->setPixelConstantBuffer(0, &mSwizzleCB);
// Apply state
stateManager->setSimpleBlendState(nullptr);
stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
// Apply shaders
stateManager->setInputLayout(support.inputLayout);
stateManager->setPrimitiveTopology(topology);
stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
&shader->pixelShader);
// Apply render target
stateManager->setRenderTarget(dest.get(), nullptr);
// Set the viewport
stateManager->setSimpleViewport(size);
// Apply textures and sampler
stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
// Draw the quad
deviceContext->Draw(drawCount, 0);
return angle::Result::Continue;
}
angle::Result Blit11::copyTexture(const gl::Context *context,
const d3d11::SharedSRV &source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
GLenum sourceFormat,
const d3d11::RenderTargetView &dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
GLenum destFormat,
GLenum destTypeForDownsampling,
GLenum filter,
bool maskOffAlpha,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha)
{
ANGLE_TRY(initResources(context));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// Determine if the source format is a signed integer format, the destFormat will already
// be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
source.get()->GetDesc(&sourceSRVDesc);
GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
ASSERT(componentType != GL_NONE);
ASSERT(componentType != GL_SIGNED_NORMALIZED);
bool isSrcSigned = (componentType == GL_INT);
D3D11_RENDER_TARGET_VIEW_DESC destRTVDesc;
dest.get()->GetDesc(&destRTVDesc);
GLenum destComponentType = d3d11::GetComponentType(destRTVDesc.Format);
ASSERT(componentType != GL_NONE);
bool isDestSigned = (destComponentType == GL_INT);
ShaderDimension dimension = SHADER_INVALID;
switch (sourceSRVDesc.ViewDimension)
{
case D3D11_SRV_DIMENSION_TEXTURE2D:
dimension = SHADER_2D;
break;
case D3D11_SRV_DIMENSION_TEXTURE3D:
dimension = SHADER_3D;
break;
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
dimension = SHADER_2DARRAY;
break;
default:
UNREACHABLE();
}
const Shader *shader = nullptr;
ANGLE_TRY(getBlitShader(context, destFormat, sourceFormat, isSrcSigned, isDestSigned,
unpackPremultiplyAlpha, unpackUnmultiplyAlpha, destTypeForDownsampling,
dimension, &shader));
ShaderSupport support;
ANGLE_TRY(getShaderSupport(context, *shader, &support));
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
&mappedResource));
UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
&stride, &drawCount, &topology);
deviceContext->Unmap(mVertexBuffer.get(), 0);
StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
if (maskOffAlpha)
{
ANGLE_TRY(mAlphaMaskBlendState.resolve(GetImplAs<Context11>(context), mRenderer));
stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj());
}
else
{
stateManager->setSimpleBlendState(nullptr);
}
stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
if (scissor)
{
stateManager->setSimpleScissorRect(*scissor);
stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
}
else
{
stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
}
// Apply shaders
stateManager->setInputLayout(support.inputLayout);
stateManager->setPrimitiveTopology(topology);
stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
&shader->pixelShader);
// Apply render target
stateManager->setRenderTarget(dest.get(), nullptr);
// Set the viewport
stateManager->setSimpleViewport(destSize);
// Apply texture and sampler
switch (filter)
{
case GL_NEAREST:
stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
break;
case GL_LINEAR:
stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler);
break;
default:
UNREACHABLE();
ANGLE_TRY_HR(GetImplAs<Context11>(context), E_FAIL,
"Internal error, unknown blit filter mode.");
}
// Draw the quad
deviceContext->Draw(drawCount, 0);
return angle::Result::Continue;
}
angle::Result Blit11::copyStencil(const gl::Context *context,
const TextureHelper11 &source,
unsigned int sourceSubresource,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const TextureHelper11 &dest,
unsigned int destSubresource,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, true);
}
angle::Result Blit11::copyDepth(const gl::Context *context,
const d3d11::SharedSRV &source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const d3d11::DepthStencilView &dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
ANGLE_TRY(initResources(context));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
&mappedResource));
UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
&drawCount, &topology);
deviceContext->Unmap(mVertexBuffer.get(), 0);
StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
stateManager->setSimpleBlendState(nullptr);
stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
if (scissor)
{
stateManager->setSimpleScissorRect(*scissor);
stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
}
else
{
stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
}
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
ANGLE_TRY(mDepthPS.resolve(context11, mRenderer));
// Apply shaders
stateManager->setInputLayout(&mQuad2DIL.getObj());
stateManager->setPrimitiveTopology(topology);
stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj());
// Apply render target
stateManager->setRenderTarget(nullptr, dest.get());
// Set the viewport
stateManager->setSimpleViewport(destSize);
// Apply texture and sampler
stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
// Draw the quad
deviceContext->Draw(drawCount, 0);
return angle::Result::Continue;
}
angle::Result Blit11::copyDepthStencil(const gl::Context *context,
const TextureHelper11 &source,
unsigned int sourceSubresource,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const TextureHelper11 &dest,
unsigned int destSubresource,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, false);
}
angle::Result Blit11::copyDepthStencilImpl(const gl::Context *context,
const TextureHelper11 &source,
unsigned int sourceSubresource,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const TextureHelper11 &dest,
unsigned int destSubresource,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
bool stencilOnly)
{
auto srcDXGIFormat = source.getFormat();
const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
unsigned int copyOffset = 0;
unsigned int copySize = srcPixelSize;
auto destDXGIFormat = dest.getFormat();
const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
unsigned int destPixelSize = destSizeInfo.pixelBytes;
ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
if (stencilOnly)
{
const auto &srcFormat = source.getFormatSet().format();
// Stencil channel should be right after the depth channel. Some views to depth/stencil
// resources have red channel for depth, in which case the depth channel bit width is in
// redBits.
ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
// Known formats have either 24 or 32 bits of depth.
ASSERT(depthBits == 24 || depthBits == 32);
copyOffset = depthBits / 8;
// Stencil is assumed to be 8-bit - currently this is true for all possible formats.
copySize = 1;
}
if (srcDXGIFormat != destDXGIFormat)
{
if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
{
ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, copyOffset,
copyOffset, copySize, srcPixelSize, destPixelSize,
BlitD24S8ToD32F);
}
ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
}
return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
copySize, srcPixelSize, destPixelSize, StretchedBlitNearest);
}
angle::Result Blit11::copyAndConvertImpl(const gl::Context *context,
const TextureHelper11 &source,
unsigned int sourceSubresource,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const TextureHelper11 &destStaging,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
size_t readOffset,
size_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
BlitConvertFunction *convertFunction)
{
ANGLE_TRY(initResources(context));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
TextureHelper11 sourceStaging;
ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
source.getFormatSet(), sourceSize,
StagingAccess::READ, &sourceStaging));
deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(),
sourceSubresource, nullptr);
D3D11_MAPPED_SUBRESOURCE sourceMapping;
ANGLE_TRY(
mRenderer->mapResource(context, sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping));
D3D11_MAPPED_SUBRESOURCE destMapping;
angle::Result error =
mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping);
if (error == angle::Result::Stop)
{
deviceContext->Unmap(sourceStaging.get(), 0);
return error;
}
// Clip dest area to the destination size
gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
// Clip dest area to the scissor
if (scissor)
{
if (!gl::ClipRectangle(clipRect, *scissor, &clipRect))
{
return angle::Result::Continue;
}
}
convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
static_cast<uint8_t *>(destMapping.pData));
deviceContext->Unmap(sourceStaging.get(), 0);
deviceContext->Unmap(destStaging.get(), 0);
return angle::Result::Continue;
}
angle::Result Blit11::copyAndConvert(const gl::Context *context,
const TextureHelper11 &source,
unsigned int sourceSubresource,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
const TextureHelper11 &dest,
unsigned int destSubresource,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
size_t readOffset,
size_t writeOffset,
size_t copySize,
size_t srcPixelStride,
size_t destPixelStride,
BlitConvertFunction *convertFunction)
{
ANGLE_TRY(initResources(context));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// HACK: Create the destination staging buffer as a read/write texture so
// ID3D11DevicContext::UpdateSubresource can be called
// using it's mapped data as a source
TextureHelper11 destStaging;
ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D, dest.getFormatSet(),
destSize, StagingAccess::READ_WRITE, &destStaging));
deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource,
nullptr);
ANGLE_TRY(copyAndConvertImpl(context, source, sourceSubresource, sourceArea, sourceSize,
destStaging, destArea, destSize, scissor, readOffset, writeOffset,
copySize, srcPixelStride, destPixelStride, convertFunction));
// Work around timeouts/TDRs in older NVIDIA drivers.
if (mRenderer->getFeatures().depthStencilBlitExtraCopy.enabled)
{
D3D11_MAPPED_SUBRESOURCE mapped;
ANGLE_TRY(
mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped));
deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData,
mapped.RowPitch, mapped.DepthPitch);
deviceContext->Unmap(destStaging.get(), 0);
}
else
{
deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0,
destStaging.get(), 0, nullptr);
}
return angle::Result::Continue;
}
angle::Result Blit11::addBlitShaderToMap(const gl::Context *context,
BlitShaderType blitShaderType,
ShaderDimension dimension,
const ShaderData &shaderData,
const char *name)
{
ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
d3d11::PixelShader ps;
ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
ps.setDebugName(name);
Shader shader;
shader.dimension = dimension;
shader.pixelShader = std::move(ps);
mBlitShaderMap[blitShaderType] = std::move(shader);
return angle::Result::Continue;
}
angle::Result Blit11::addSwizzleShaderToMap(const gl::Context *context,
SwizzleShaderType swizzleShaderType,
ShaderDimension dimension,
const ShaderData &shaderData,
const char *name)
{
ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
d3d11::PixelShader ps;
ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
ps.setDebugName(name);
Shader shader;
shader.dimension = dimension;
shader.pixelShader = std::move(ps);
mSwizzleShaderMap[swizzleShaderType] = std::move(shader);
return angle::Result::Continue;
}
void Blit11::clearShaderMap()
{
mBlitShaderMap.clear();
mSwizzleShaderMap.clear();
}
Blit11::BlitShaderOperation Blit11::getBlitShaderOperation(GLenum destinationFormat,
GLenum sourceFormat,
bool isSrcSigned,
bool isDestSigned,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha,
GLenum destTypeForDownsampling)
{
bool floatToIntBlit =
!gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat);
if (isSrcSigned)
{
ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
switch (destinationFormat)
{
case GL_RGBA_INTEGER:
return RGBAI;
case GL_RGB_INTEGER:
return RGBI;
case GL_RG_INTEGER:
return RGI;
case GL_RED_INTEGER:
return RI;
default:
UNREACHABLE();
return OPERATION_INVALID;
}
}
else if (isDestSigned)
{
ASSERT(floatToIntBlit);
switch (destinationFormat)
{
case GL_RGBA_INTEGER:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBAF_TOI;
}
else
{
return unpackPremultiplyAlpha ? RGBAF_TOI_PREMULTIPLY : RGBAF_TOI_UNMULTIPLY;
}
break;
case GL_RGB_INTEGER:
case GL_RG_INTEGER:
case GL_RED_INTEGER:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBF_TOI;
}
else
{
return unpackPremultiplyAlpha ? RGBF_TOI_PREMULTIPLY : RGBF_TOI_UNMULTIPLY;
}
break;
default:
UNREACHABLE();
return OPERATION_INVALID;
}
}
else
{
// Check for the downsample formats first
switch (destTypeForDownsampling)
{
case GL_UNSIGNED_SHORT_4_4_4_4:
ASSERT(destinationFormat == GL_RGBA && !floatToIntBlit);
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBAF_4444;
}
else if (unpackPremultiplyAlpha)
{
return RGBAF_4444_PREMULTIPLY;
}
else
{
return RGBAF_4444_UNMULTIPLY;
}
case GL_UNSIGNED_SHORT_5_6_5:
ASSERT(destinationFormat == GL_RGB && !floatToIntBlit);
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBF_565;
}
else
{
return unpackPremultiplyAlpha ? RGBF_565_PREMULTIPLY : RGBF_565_UNMULTIPLY;
}
case GL_UNSIGNED_SHORT_5_5_5_1:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBAF_5551;
}
else
{
return unpackPremultiplyAlpha ? RGBAF_5551_PREMULTIPLY : RGBAF_5551_UNMULTIPLY;
}
default:
// By default, use the regular passthrough/multiply/unmultiply shaders. The above
// shaders are only needed for some emulated texture formats.
break;
}
if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit)
{
switch (destinationFormat)
{
case GL_RGBA:
case GL_BGRA_EXT:
ASSERT(!floatToIntBlit);
return unpackPremultiplyAlpha ? RGBAF_PREMULTIPLY : RGBAF_UNMULTIPLY;
case GL_RGB:
case GL_RG:
case GL_RED:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBF_TOUI;
}
else
{
return unpackPremultiplyAlpha ? RGBF_PREMULTIPLY : RGBF_UNMULTIPLY;
}
case GL_RGBA_INTEGER:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBAF_TOUI;
}
else
{
return unpackPremultiplyAlpha ? RGBAF_TOUI_PREMULTIPLY
: RGBAF_TOUI_UNMULTIPLY;
}
case GL_RGB_INTEGER:
case GL_RG_INTEGER:
case GL_RED_INTEGER:
if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
{
return RGBF_TOUI;
}
else
{
return unpackPremultiplyAlpha ? RGBF_TOUI_PREMULTIPLY
: RGBF_TOUI_UNMULTIPLY;
}
case GL_LUMINANCE:
ASSERT(!floatToIntBlit);
return unpackPremultiplyAlpha ? LUMAF_PREMULTIPLY : LUMAF_UNMULTIPLY;
case GL_LUMINANCE_ALPHA:
ASSERT(!floatToIntBlit);
return unpackPremultiplyAlpha ? LUMAALPHAF_PREMULTIPLY : LUMAALPHAF_UNMULTIPLY;
case GL_ALPHA:
return ALPHA;
default:
UNREACHABLE();
return OPERATION_INVALID;
}
}
else
{
switch (destinationFormat)
{
case GL_RGBA:
return RGBAF;
case GL_RGBA_INTEGER:
return RGBAUI;
case GL_BGRA_EXT:
return BGRAF;
case GL_RGB:
return RGBF;
case GL_RGB_INTEGER:
return RGBUI;
case GL_RG:
return RGF;
case GL_RG_INTEGER:
return RGUI;
case GL_RED:
return RF;
case GL_RED_INTEGER:
return RUI;
case GL_ALPHA:
return ALPHA;
case GL_LUMINANCE:
return LUMA;
case GL_LUMINANCE_ALPHA:
return LUMAALPHA;
default:
UNREACHABLE();
return OPERATION_INVALID;
}
}
}
}
angle::Result Blit11::getBlitShader(const gl::Context *context,
GLenum destFormat,
GLenum sourceFormat,
bool isSrcSigned,
bool isDestSigned,
bool unpackPremultiplyAlpha,
bool unpackUnmultiplyAlpha,
GLenum destTypeForDownsampling,
ShaderDimension dimension,
const Shader **shader)
{
BlitShaderOperation blitShaderOperation = OPERATION_INVALID;
blitShaderOperation = getBlitShaderOperation(destFormat, sourceFormat, isSrcSigned,
isDestSigned, unpackPremultiplyAlpha,
unpackUnmultiplyAlpha, destTypeForDownsampling);
BlitShaderType blitShaderType = BLITSHADER_INVALID;
blitShaderType = getBlitShaderType(blitShaderOperation, dimension);
ANGLE_CHECK_HR(GetImplAs<Context11>(context), blitShaderType != BLITSHADER_INVALID,
"Internal blit shader type mismatch", E_FAIL);
auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
if (blitShaderIt != mBlitShaderMap.end())
{
*shader = &blitShaderIt->second;
return angle::Result::Continue;
}
ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
ANGLE_TRY(mapBlitShader(context, blitShaderType));
blitShaderIt = mBlitShaderMap.find(blitShaderType);
ASSERT(blitShaderIt != mBlitShaderMap.end());
*shader = &blitShaderIt->second;
return angle::Result::Continue;
}
angle::Result Blit11::getSwizzleShader(const gl::Context *context,
GLenum type,
D3D11_SRV_DIMENSION viewDimension,
const Shader **shader)
{
SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
ANGLE_CHECK_HR(GetImplAs<Context11>(context), swizzleShaderType != SWIZZLESHADER_INVALID,
"Swizzle shader type not found", E_FAIL);
auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
if (swizzleShaderIt != mSwizzleShaderMap.end())
{
*shader = &swizzleShaderIt->second;
return angle::Result::Continue;
}
// Swizzling shaders (OpenGL ES 3+)
ASSERT(mRenderer->isES3Capable());
switch (swizzleShaderType)
{
case SWIZZLESHADER_2D_FLOAT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
ShaderData(g_PS_SwizzleF2D),
"Blit11 2D F swizzle pixel shader"));
break;
case SWIZZLESHADER_2D_UINT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
ShaderData(g_PS_SwizzleUI2D),
"Blit11 2D UI swizzle pixel shader"));
break;
case SWIZZLESHADER_2D_INT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
ShaderData(g_PS_SwizzleI2D),
"Blit11 2D I swizzle pixel shader"));
break;
case SWIZZLESHADER_CUBE_FLOAT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleF2DArray),
"Blit11 2D Cube F swizzle pixel shader"));
break;
case SWIZZLESHADER_CUBE_UINT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleUI2DArray),
"Blit11 2D Cube UI swizzle pixel shader"));
break;
case SWIZZLESHADER_CUBE_INT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleI2DArray),
"Blit11 2D Cube I swizzle pixel shader"));
break;
case SWIZZLESHADER_3D_FLOAT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleF3D),
"Blit11 3D F swizzle pixel shader"));
break;
case SWIZZLESHADER_3D_UINT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleUI3D),
"Blit11 3D UI swizzle pixel shader"));
break;
case SWIZZLESHADER_3D_INT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleI3D),
"Blit11 3D I swizzle pixel shader"));
break;
case SWIZZLESHADER_ARRAY_FLOAT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleF2DArray),
"Blit11 2D Array F swizzle pixel shader"));
break;
case SWIZZLESHADER_ARRAY_UINT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleUI2DArray),
"Blit11 2D Array UI swizzle pixel shader"));
break;
case SWIZZLESHADER_ARRAY_INT:
ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
ShaderData(g_PS_SwizzleI2DArray),
"Blit11 2D Array I swizzle pixel shader"));
break;
default:
ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
}
swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
*shader = &swizzleShaderIt->second;
return angle::Result::Continue;
}
angle::Result Blit11::resolveDepth(const gl::Context *context,
RenderTarget11 *depth,
TextureHelper11 *textureOut)
{
ANGLE_TRY(initResources(context));
// Multisampled depth stencil SRVs are not available in feature level 10.0
ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
const auto &extents = depth->getExtents();
auto *deviceContext = mRenderer->getDeviceContext();
auto *stateManager = mRenderer->getStateManager();
ANGLE_TRY(initResolveDepthOnly(context, depth->getFormatSet(), extents));
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
ANGLE_TRY(mResolveDepthPS.resolve(context11, mRenderer));
// Apply the necessary state changes to the D3D11 immediate device context.
stateManager->setInputLayout(nullptr);
stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr,
&mResolveDepthPS.getObj());
stateManager->setRasterizerState(nullptr);
stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get());
stateManager->setSimpleBlendState(nullptr);
stateManager->setSimpleViewport(extents);
// Set the viewport
stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0,
&depth->getShaderResourceView(context));
// Trigger the blit on the GPU.
deviceContext->Draw(6, 0);
*textureOut = mResolvedDepth;
return angle::Result::Continue;
}
angle::Result Blit11::initResolveDepthOnly(const gl::Context *context,
const d3d11::Format &format,
const gl::Extents &extents)
{
if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
format.texFormat == mResolvedDepth.getFormat())
{
return angle::Result::Continue;
}
D3D11_TEXTURE2D_DESC textureDesc;
textureDesc.Width = extents.width;
textureDesc.Height = extents.height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = format.texFormat;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(mRenderer->allocateTexture(context11, textureDesc, format, &mResolvedDepth));
mResolvedDepth.setDebugName("Blit11::mResolvedDepth");
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Flags = 0;
dsvDesc.Format = format.dsvFormat;
dsvDesc.Texture2D.MipSlice = 0;
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, mResolvedDepth.get(),
&mResolvedDepthDSView));
mResolvedDepthDSView.setDebugName("Blit11::mResolvedDepthDSView");
// Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
// works as expected. Otherwise the results of the first use seem to be incorrect.
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
deviceContext->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
return angle::Result::Continue;
}
angle::Result Blit11::initResolveDepthStencil(const gl::Context *context,
const gl::Extents &extents)
{
// Check if we need to recreate depth stencil view
if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
{
ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
return angle::Result::Continue;
}
if (mResolvedDepthStencil.valid())
{
releaseResolveDepthStencilResources();
}
const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC textureDesc;
textureDesc.Width = extents.width;
textureDesc.Height = extents.height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = formatSet.texFormat;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
Context11 *context11 = GetImplAs<Context11>(context);
ANGLE_TRY(
mRenderer->allocateTexture(context11, textureDesc, formatSet, &mResolvedDepthStencil));
mResolvedDepthStencil.setDebugName("Blit11::mResolvedDepthStencil");
ANGLE_TRY(mRenderer->allocateResourceNoDesc(context11, mResolvedDepthStencil.get(),
&mResolvedDepthStencilRTView));
mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView");
return angle::Result::Continue;
}
angle::Result Blit11::resolveStencil(const gl::Context *context,
RenderTarget11 *depthStencil,
bool alsoDepth,
TextureHelper11 *textureOut)
{
ANGLE_TRY(initResources(context));
// Multisampled depth stencil SRVs are not available in feature level 10.0
ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
const auto &extents = depthStencil->getExtents();
ANGLE_TRY(initResolveDepthStencil(context, extents));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
auto *stateManager = mRenderer->getStateManager();
ID3D11Resource *stencilResource = depthStencil->getTexture().get();
// Check if we need to re-create the stencil SRV.
if (mStencilSRV.valid())
{
ID3D11Resource *priorResource = nullptr;
mStencilSRV.get()->GetResource(&priorResource);
if (stencilResource != priorResource)
{
mStencilSRV.reset();
}
SafeRelease(priorResource);
}
Context11 *context11 = GetImplAs<Context11>(context);
if (!mStencilSRV.valid())
{
D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
ANGLE_TRY(
mRenderer->allocateResource(context11, srViewDesc, stencilResource, &mStencilSRV));
mStencilSRV.setDebugName("Blit11::mStencilSRV");
}
// Notify the Renderer that all state should be invalidated.
ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
// Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
// writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
// because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
const d3d11::PixelShader *pixelShader = nullptr;
if (alsoDepth)
{
ANGLE_TRY(mResolveDepthStencilPS.resolve(context11, mRenderer));
pixelShader = &mResolveDepthStencilPS.getObj();
}
else
{
ANGLE_TRY(mResolveStencilPS.resolve(context11, mRenderer));
pixelShader = &mResolveStencilPS.getObj();
}
// Apply the necessary state changes to the D3D11 immediate device context.
stateManager->setInputLayout(nullptr);
stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader);
stateManager->setRasterizerState(nullptr);
stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr);
stateManager->setSimpleBlendState(nullptr);
// Set the viewport
stateManager->setSimpleViewport(extents);
stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0,
&depthStencil->getShaderResourceView(context));
stateManager->setShaderResource(gl::ShaderType::Fragment, 1, &mStencilSRV);
// Trigger the blit on the GPU.
deviceContext->Draw(6, 0);
gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
depthStencil->getFormatSet(), extents,
StagingAccess::READ_WRITE, textureOut));
const auto &copyFunction = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
const auto &dsFormatSet = depthStencil->getFormatSet();
const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
ANGLE_TRY(copyAndConvertImpl(context, mResolvedDepthStencil, 0, copyBox, extents, *textureOut,
copyBox, extents, nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes,
copyFunction));
return angle::Result::Continue;
}
void Blit11::releaseResolveDepthStencilResources()
{
mStencilSRV.reset();
mResolvedDepthStencilRTView.reset();
}
} // namespace rx