Commit 9e3d7aa0 by Jamie Madill

D3D11: Work around small mipped stencil textures.

AMD has a bug with 2x2 and 1x1 mips of depth/stencil textures. Formats D24S8 and D32FS8 both seem to render black for the very small mips. We can work around this by selectively caching a copy of the texture data that only has depth information, since stencil isn't filterable in OpenGL ES. BUG=angleproject:1493 BUG=chromium:638323 Change-Id: Iebef42c4680018d9854dbe789d677823167213dd Reviewed-on: https://chromium-review.googlesource.com/380037Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 6a25746c
......@@ -75,6 +75,11 @@ struct WorkaroundsD3D
// and Offset is in range. To work around this, we translatie texelFetchOffset into texelFetch
// by adding Offset directly to Location before reading the texture.
bool preAddTexelFetchOffsets = false;
// On some AMD drivers, 1x1 and 2x2 mips of depth/stencil textures aren't sampled correctly.
// We can work around this bug by doing an internal blit to a temporary single-channel texture
// before we sample.
bool emulateTinyStencilTextures = false;
};
} // namespace rx
......
......@@ -274,6 +274,93 @@ void CopyDepthStencil(const gl::Box &sourceArea,
}
}
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)
......@@ -1381,7 +1468,7 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destFormat);
unsigned int destPixelSize = destSizeInfo.pixelBytes;
ASSERT(srcFormat == destFormat);
ASSERT(srcFormat == destFormat || destFormat == DXGI_FORMAT_R32_TYPELESS);
if (stencilOnly)
{
......@@ -1400,6 +1487,22 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
copySize = 1;
}
if (srcFormat != destFormat)
{
if (srcFormat == DXGI_FORMAT_R24G8_TYPELESS)
{
ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, copyOffset,
copyOffset, copySize, srcPixelSize, destPixelSize,
BlitD24S8ToD32F);
}
ASSERT(srcFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
}
return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
destArea, destSize, scissor, copyOffset, copyOffset, copySize,
srcPixelSize, destPixelSize, StretchedBlitNearest);
......
......@@ -419,129 +419,139 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
}
}
if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil)
if (maskedClearRenderTargets.empty() && !maskedClearDepthStencil)
{
// To clear the render targets and depth stencil in one pass:
//
// Render a quad clipped to the scissor rectangle which draws the clear color and a blend
// state that will perform the required color masking.
//
// The quad's depth is equal to the depth clear value with a depth stencil state that
// will enable or disable depth test/writes if the depth buffer should be cleared or not.
//
// The rasterizer state's stencil is set to always pass or fail based on if the stencil
// should be cleared or not with a stencil write mask of the stencil clear value.
//
// ======================================================================================
//
// Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
// buffer that is not normalized fixed point or floating point with floating point values
// are undefined so we can just write floats to them and D3D11 will bit cast them to
// integers.
//
// Also, we don't have to worry about attempting to clear a normalized fixed/floating point
// buffer with integer values because there is no gl API call which would allow it,
// glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
// be a compatible clear type.
// Bind all the render targets which need clearing
ASSERT(maskedClearRenderTargets.size() <= mRenderer->getNativeCaps().maxDrawBuffers);
std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
{
RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
if (!rtv)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
}
return gl::NoError();
}
rtvs[i] = rtv;
}
ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const UINT sampleMask = 0xFFFFFFFF;
ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
// Set the vertices
UINT vertexStride = 0;
const UINT startIdx = 0;
ClearShader *shader = nullptr;
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
// To clear the render targets and depth stencil in one pass:
//
// Render a quad clipped to the scissor rectangle which draws the clear color and a blend
// state that will perform the required color masking.
//
// The quad's depth is equal to the depth clear value with a depth stencil state that
// will enable or disable depth test/writes if the depth buffer should be cleared or not.
//
// The rasterizer state's stencil is set to always pass or fail based on if the stencil
// should be cleared or not with a stencil write mask of the stencil clear value.
//
// ======================================================================================
//
// Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
// buffer that is not normalized fixed point or floating point with floating point values
// are undefined so we can just write floats to them and D3D11 will bit cast them to
// integers.
//
// Also, we don't have to worry about attempting to clear a normalized fixed/floating point
// buffer with integer values because there is no gl API call which would allow it,
// glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
// be a compatible clear type.
// Bind all the render targets which need clearing
ASSERT(maskedClearRenderTargets.size() <= mRenderer->getNativeCaps().maxDrawBuffers);
std::vector<ID3D11RenderTargetView *> rtvs(maskedClearRenderTargets.size());
for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
{
RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
if (!rtv)
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result);
return gl::Error(GL_OUT_OF_MEMORY,
"Internal render target view pointer unexpectedly null.");
}
const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
switch (clearParams.colorClearType)
{
case GL_FLOAT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData);
rtvs[i] = rtv;
}
ID3D11DepthStencilView *dsv =
maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
const FLOAT blendFactors[4] = {1.0f, 1.0f, 1.0f, 1.0f};
const UINT sampleMask = 0xFFFFFFFF;
ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
// Set the vertices
UINT vertexStride = 0;
const UINT startIdx = 0;
ClearShader *shader = nullptr;
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result =
deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.",
result);
}
const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
switch (clearParams.colorClearType)
{
case GL_FLOAT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue,
clearParams.depthClearValue, mappedResource.pData);
vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>);
shader = mFloatClearShader;
shader = mFloatClearShader;
break;
case GL_UNSIGNED_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData);
case GL_UNSIGNED_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue,
clearParams.depthClearValue, mappedResource.pData);
vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>);
shader = mUintClearShader;
shader = mUintClearShader;
break;
case GL_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData);
case GL_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue,
clearParams.depthClearValue, mappedResource.pData);
vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>);
shader = mIntClearShader;
shader = mIntClearShader;
break;
default:
default:
UNREACHABLE();
break;
}
deviceContext->Unmap(mVertexBuffer, 0);
// Set the viewport to be the same size as the framebuffer
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = static_cast<FLOAT>(framebufferSize.width);
viewport.Height = static_cast<FLOAT>(framebufferSize.height);
viewport.MinDepth = 0;
viewport.MaxDepth = 1;
deviceContext->RSSetViewports(1, &viewport);
// Apply state
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilClear);
deviceContext->RSSetState(mRasterizerState);
// Apply shaders
deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0);
deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0);
deviceContext->GSSetShader(nullptr, nullptr, 0);
// Apply vertex buffer
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// Apply render targets
mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv);
// Draw the clear quad
deviceContext->Draw(4, 0);
// Clean up
mRenderer->markAllStateDirty();
}
return gl::Error(GL_NO_ERROR);
deviceContext->Unmap(mVertexBuffer, 0);
// Set the viewport to be the same size as the framebuffer
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = static_cast<FLOAT>(framebufferSize.width);
viewport.Height = static_cast<FLOAT>(framebufferSize.height);
viewport.MinDepth = 0;
viewport.MaxDepth = 1;
deviceContext->RSSetViewports(1, &viewport);
// Apply state
deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
deviceContext->OMSetDepthStencilState(dsState, stencilClear);
deviceContext->RSSetState(mRasterizerState);
// Apply shaders
deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0);
deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0);
deviceContext->GSSetShader(nullptr, nullptr, 0);
// Apply vertex buffer
deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// Apply render targets
mRenderer->getStateManager()->setOneTimeRenderTargets(rtvs, dsv);
// Draw the clear quad
deviceContext->Draw(4, 0);
// Clean up
mRenderer->markAllStateDirty();
return gl::NoError();
}
ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
......
......@@ -3079,7 +3079,7 @@ gl::Error Renderer11::copyTexture(const gl::Texture *source,
destStorage11->markLevelDirty(destLevel);
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
......@@ -3541,16 +3541,12 @@ gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
ASSERT(storage11->supportsNativeMipmapFunction());
ID3D11ShaderResourceView *srv;
gl::Error error = storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
textureState.getEffectiveMaxLevel(), &srv);
if (error.isError())
{
return error;
}
ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
textureState.getEffectiveMaxLevel(), &srv));
mDeviceContext->GenerateMips(srv);
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
......
......@@ -31,15 +31,15 @@
namespace rx
{
TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
: baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle)
TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
: baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
{
}
bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
{
return std::tie(baseLevel, mipLevels, swizzle) <
std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle);
return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
}
TextureStorage11::TextureStorage11(Renderer11 *renderer,
......@@ -53,6 +53,7 @@ TextureStorage11::TextureStorage11(Renderer11 *renderer,
mTextureWidth(0),
mTextureHeight(0),
mTextureDepth(0),
mDropStencilTexture(nullptr),
mBindFlags(bindFlags),
mMiscFlags(miscFlags)
{
......@@ -73,6 +74,7 @@ TextureStorage11::~TextureStorage11()
SafeRelease(i->second);
}
mSrvCache.clear();
SafeRelease(mDropStencilTexture);
}
DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
......@@ -203,11 +205,7 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// We must ensure that the level zero texture is in sync with mipped texture.
gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
if (error.isError())
{
return error;
}
ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
}
if (swizzleRequired)
......@@ -215,7 +213,22 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
verifySwizzleExists(textureState.getSwizzleState());
}
SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired);
// We drop the stencil when sampling from the SRV if three conditions hold:
// 1. the drop stencil workaround is enabled.
bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
// 2. this is a stencil texture.
bool hasStencil = (d3d11::GetDXGIFormatInfo(mFormatInfo.dsvFormat).stencilBits > 0);
// 3. the texture has a 1x1 or 2x2 mip.
bool hasSmallMips = (getLevelWidth(mMipLevels - 1) <= 2 || getLevelHeight(mMipLevels - 1) <= 2);
bool useDropStencil = (workaround && hasStencil && hasSmallMips);
if (useDropStencil)
{
// Ensure drop texture gets re-created, if SRV is cached.
ANGLE_TRY(createDropStencilTexture());
}
SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
return gl::NoError();
......@@ -232,17 +245,29 @@ gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key,
}
ID3D11Resource *texture = nullptr;
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
if (key.swizzle)
{
ASSERT(!key.dropStencil ||
d3d11::GetDXGIFormatInfo(mFormatInfo.swizzle.dsvFormat).stencilBits == 0);
ANGLE_TRY(getSwizzleTexture(&texture));
format = mFormatInfo.swizzle.srvFormat;
}
else if (key.dropStencil)
{
ASSERT(mDropStencilTexture);
texture = mDropStencilTexture;
format = DXGI_FORMAT_R32_FLOAT;
}
else
{
ANGLE_TRY(getResource(&texture));
format = mFormatInfo.srvFormat;
}
ID3D11ShaderResourceView *srv = nullptr;
DXGI_FORMAT format = (key.swizzle ? mFormatInfo.swizzle.srvFormat : mFormatInfo.srvFormat);
ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv));
mSrvCache.insert(std::make_pair(key, srv));
......@@ -271,25 +296,17 @@ gl::Error TextureStorage11::getSRVLevel(int mipLevel,
else
{
ID3D11Resource *resource = nullptr;
gl::Error error = getResource(&resource);
if (error.isError())
{
return error;
}
ANGLE_TRY(getResource(&resource));
DXGI_FORMAT resourceFormat =
blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
error = createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]);
if (error.isError())
{
return error;
}
ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]));
}
}
*outSRV = levelSRVs[mipLevel];
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
......@@ -310,14 +327,12 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// We must ensure that the level zero texture is in sync with mipped texture.
gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
if (error.isError())
{
return error;
}
ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
}
SRVKey key(baseLevel, mipLevels, false);
// TODO(jmadill): Assert we don't need to drop stencil.
SRVKey key(baseLevel, mipLevels, false, false);
ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
return gl::NoError();
......@@ -337,35 +352,22 @@ gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarg
{
// Need to re-render the swizzle for this level
ID3D11ShaderResourceView *sourceSRV = nullptr;
gl::Error error = getSRVLevel(level, true, &sourceSRV);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSRVLevel(level, true, &sourceSRV));
ID3D11RenderTargetView *destRTV = nullptr;
error = getSwizzleRenderTarget(level, &destRTV);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
Blit11 *blitter = mRenderer->getBlitter();
error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget);
if (error.isError())
{
return error;
}
ANGLE_TRY(blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget));
mSwizzleCache[level] = swizzleTarget;
}
}
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
void TextureStorage11::markLevelDirty(int mipLevel)
......@@ -376,6 +378,8 @@ void TextureStorage11::markLevelDirty(int mipLevel)
// not a valid swizzle combination
mSwizzleCache[mipLevel] = gl::SwizzleState();
}
SafeRelease(mDropStencilTexture);
}
void TextureStorage11::markDirty()
......@@ -457,22 +461,16 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture,
ASSERT(dstTexture);
ID3D11Resource *srcTexture = nullptr;
gl::Error error(GL_NO_ERROR);
// If the zero-LOD workaround is active and we want to update a level greater than zero, then we
// should update the mipmapped texture, even if mapmaps are currently disabled.
if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
error = getMippedResource(&srcTexture);
ANGLE_TRY(getMippedResource(&srcTexture));
}
else
{
error = getResource(&srcTexture);
}
if (error.isError())
{
return error;
ANGLE_TRY(getResource(&srcTexture));
}
ASSERT(srcTexture);
......@@ -514,18 +512,10 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex,
markLevelDirty(destIndex.mipIndex);
RenderTargetD3D *source = nullptr;
gl::Error error = getRenderTarget(sourceIndex, &source);
if (error.isError())
{
return error;
}
ANGLE_TRY(getRenderTarget(sourceIndex, &source));
RenderTargetD3D *dest = nullptr;
error = getRenderTarget(destIndex, &dest);
if (error.isError())
{
return error;
}
ANGLE_TRY(getRenderTarget(destIndex, &dest));
ID3D11ShaderResourceView *sourceSRV =
GetAs<RenderTarget11>(source)->getBlitShaderResourceView();
......@@ -582,26 +572,18 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
ASSERT(destStorage);
ID3D11Resource *sourceResouce = nullptr;
gl::Error error = getResource(&sourceResouce);
if (error.isError())
{
return error;
}
ANGLE_TRY(getResource(&sourceResouce));
TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource);
if (error.isError())
{
return error;
}
ANGLE_TRY(dest11->getResource(&destResource));
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
immediateContext->CopyResource(destResource, sourceResouce);
dest11->markDirty();
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
......@@ -708,6 +690,12 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
return gl::NoError();
}
gl::Error TextureStorage11::createDropStencilTexture()
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION, "Drop stencil texture not implemented.");
}
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
: TextureStorage11(renderer,
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
......@@ -831,63 +819,37 @@ gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
// corresponding textures in destStorage.
if (mTexture)
{
gl::Error error = dest11->useLevelZeroWorkaroundTexture(false);
if (error.isError())
{
return error;
}
ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource);
if (error.isError())
{
return error;
}
ANGLE_TRY(dest11->getResource(&destResource));
immediateContext->CopyResource(destResource, mTexture);
}
if (mLevelZeroTexture)
{
gl::Error error = dest11->useLevelZeroWorkaroundTexture(true);
if (error.isError())
{
return error;
}
ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource);
if (error.isError())
{
return error;
}
ANGLE_TRY(dest11->getResource(&destResource));
immediateContext->CopyResource(destResource, mLevelZeroTexture);
}
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
else
{
ID3D11Resource *sourceResouce = nullptr;
gl::Error error = getResource(&sourceResouce);
if (error.isError())
{
return error;
}
ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource);
if (error.isError())
{
return error;
}
ID3D11Resource *sourceResouce = nullptr;
ANGLE_TRY(getResource(&sourceResouce));
immediateContext->CopyResource(destResource, sourceResouce);
dest11->markDirty();
}
ID3D11Resource *destResource = nullptr;
ANGLE_TRY(dest11->getResource(&destResource));
return gl::Error(GL_NO_ERROR);
immediateContext->CopyResource(destResource, sourceResouce);
dest11->markDirty();
return gl::NoError();
}
gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
......@@ -898,11 +860,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe
{
if (!mUseLevelZeroTexture && mTexture)
{
gl::Error error = ensureTextureExists(1);
if (error.isError())
{
return error;
}
ANGLE_TRY(ensureTextureExists(1));
// Pull data back from the mipped texture if necessary.
ASSERT(mLevelZeroTexture);
......@@ -916,11 +874,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe
{
if (mUseLevelZeroTexture && mLevelZeroTexture)
{
gl::Error error = ensureTextureExists(mMipLevels);
if (error.isError())
{
return error;
}
ANGLE_TRY(ensureTextureExists(mMipLevels));
// Pull data back from the level zero texture if necessary.
ASSERT(mTexture);
......@@ -947,7 +901,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe
}
}
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
......@@ -1029,33 +983,23 @@ gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &inde
}
}
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
{
if (mUseLevelZeroTexture && mMipLevels > 1)
{
gl::Error error = ensureTextureExists(1);
if (error.isError())
{
return error;
}
ANGLE_TRY(ensureTextureExists(1));
*outResource = mLevelZeroTexture;
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
else
{
gl::Error error = ensureTextureExists(mMipLevels);
if (error.isError())
{
return error;
}
*outResource = mTexture;
return gl::Error(GL_NO_ERROR);
}
ANGLE_TRY(ensureTextureExists(mMipLevels));
*outResource = mTexture;
return gl::NoError();
}
gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
......@@ -1063,14 +1007,10 @@ gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
// This shouldn't be called unless the zero max LOD workaround is active.
ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
gl::Error error = ensureTextureExists(mMipLevels);
if (error.isError())
{
return error;
}
ANGLE_TRY(ensureTextureExists(mMipLevels));
*outResource = mTexture;
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
......@@ -1144,29 +1084,17 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
if (mRenderTarget[level])
{
*outRT = mRenderTarget[level];
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture);
if (error.isError())
{
return error;
}
ANGLE_TRY(getResource(&texture));
ID3D11ShaderResourceView *srv = nullptr;
error = getSRVLevel(level, false, &srv);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSRVLevel(level, false, &srv));
ID3D11ShaderResourceView *blitSRV = nullptr;
error = getSRVLevel(level, true, &blitSRV);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSRVLevel(level, true, &blitSRV));
ID3D11Device *device = mRenderer->getDevice();
......@@ -1200,7 +1128,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
}
*outRT = mLevelZeroRenderTarget;
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
......@@ -1261,7 +1189,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
SafeRelease(dsv);
*outRT = mRenderTarget[level];
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11_2D::createSRV(int baseLevel,
......@@ -1387,7 +1315,41 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
}
*outRTV = mSwizzleRenderTargets[mipLevel];
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11_2D::createDropStencilTexture()
{
if (mDropStencilTexture)
{
return gl::NoError();
}
D3D11_TEXTURE2D_DESC dropDesc = {};
dropDesc.ArraySize = 1;
dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
dropDesc.CPUAccessFlags = 0;
dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
dropDesc.Height = mTextureHeight;
dropDesc.MipLevels = mMipLevels;
dropDesc.MiscFlags = 0;
dropDesc.SampleDesc.Count = 1;
dropDesc.SampleDesc.Quality = 0;
dropDesc.Usage = D3D11_USAGE_DEFAULT;
dropDesc.Width = mTextureWidth;
ID3D11Device *device = mRenderer->getDevice();
HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
if (FAILED(hr))
{
return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
}
d3d11::SetDebugName(mDropStencilTexture, "TexStorage2D.DropStencil");
ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::Make2D(0, mMipLevels)));
return gl::NoError();
}
TextureStorage11_External::TextureStorage11_External(
......@@ -2575,6 +2537,66 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureStorage11::initDropStencilTexture(const gl::ImageIndexIterator &it)
{
ID3D11Resource *resource = nullptr;
ANGLE_TRY(getResource(&resource));
TextureHelper11 sourceTexture = TextureHelper11::MakeAndReference(resource, mFormatInfo);
TextureHelper11 destTexture = TextureHelper11::MakeAndReference(
mDropStencilTexture,
d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()));
gl::ImageIndexIterator itCopy = it;
while (itCopy.hasNext())
{
gl::ImageIndex index = itCopy.next();
gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
1);
gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
UINT subresource = getSubresourceIndex(index);
ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(sourceTexture, subresource, wholeArea,
wholeSize, destTexture, subresource,
wholeArea, wholeSize, nullptr));
}
return gl::NoError();
}
gl::Error TextureStorage11_Cube::createDropStencilTexture()
{
if (mDropStencilTexture)
{
return gl::NoError();
}
D3D11_TEXTURE2D_DESC dropDesc = {};
dropDesc.ArraySize = 6;
dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
dropDesc.CPUAccessFlags = 0;
dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
dropDesc.Height = mTextureHeight;
dropDesc.MipLevels = mMipLevels;
dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
dropDesc.SampleDesc.Count = 1;
dropDesc.SampleDesc.Quality = 0;
dropDesc.Usage = D3D11_USAGE_DEFAULT;
dropDesc.Width = mTextureWidth;
ID3D11Device *device = mRenderer->getDevice();
HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
if (FAILED(hr))
{
return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
}
d3d11::SetDebugName(mDropStencilTexture, "TexStorageCube.DropStencil");
ANGLE_TRY(initDropStencilTexture(gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
return gl::NoError();
}
TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
GLenum internalformat,
bool renderTarget,
......@@ -2812,25 +2834,13 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
if (!mLevelRenderTargets[mipLevel])
{
ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture);
if (error.isError())
{
return error;
}
ANGLE_TRY(getResource(&texture));
ID3D11ShaderResourceView *srv = nullptr;
error = getSRVLevel(mipLevel, false, &srv);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSRVLevel(mipLevel, false, &srv));
ID3D11ShaderResourceView *blitSRV = nullptr;
error = getSRVLevel(mipLevel, true, &blitSRV);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV));
ID3D11Device *device = mRenderer->getDevice();
......@@ -2971,11 +2981,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
if (!mSwizzleRenderTargets[mipLevel])
{
ID3D11Resource *swizzleTexture = nullptr;
gl::Error error = getSwizzleTexture(&swizzleTexture);
if (error.isError())
{
return error;
}
ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
ID3D11Device *device = mRenderer->getDevice();
......@@ -3275,21 +3281,14 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
HRESULT result;
ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture);
if (error.isError())
{
return error;
}
ANGLE_TRY(getResource(&texture));
ID3D11ShaderResourceView *srv;
error = createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv);
if (error.isError())
{
return error;
}
ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
ID3D11ShaderResourceView *blitSRV;
if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
{
error = createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
gl::Error error =
createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
if (error.isError())
{
SafeRelease(srv);
......@@ -3377,7 +3376,7 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
ASSERT(outRT);
*outRT = mRenderTargets[key];
return gl::Error(GL_NO_ERROR);
return gl::NoError();
}
gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
......@@ -3454,4 +3453,42 @@ gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
*outRTV = mSwizzleRenderTargets[mipLevel];
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureStorage11_2DArray::createDropStencilTexture()
{
if (mDropStencilTexture)
{
return gl::NoError();
}
D3D11_TEXTURE2D_DESC dropDesc = {};
dropDesc.ArraySize = mTextureDepth;
dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
dropDesc.CPUAccessFlags = 0;
dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
dropDesc.Height = mTextureHeight;
dropDesc.MipLevels = mMipLevels;
dropDesc.MiscFlags = 0;
dropDesc.SampleDesc.Count = 1;
dropDesc.SampleDesc.Quality = 0;
dropDesc.Usage = D3D11_USAGE_DEFAULT;
dropDesc.Width = mTextureWidth;
ID3D11Device *device = mRenderer->getDevice();
HRESULT hr = device->CreateTexture2D(&dropDesc, nullptr, &mDropStencilTexture);
if (FAILED(hr))
{
return gl::Error(GL_INVALID_OPERATION, "Error creating drop stencil texture.");
}
d3d11::SetDebugName(mDropStencilTexture, "TexStorage2DArray.DropStencil");
std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
ANGLE_TRY(initDropStencilTexture(
gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
return gl::NoError();
}
} // namespace rx
......@@ -94,6 +94,10 @@ class TextureStorage11 : public TextureStorage
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV);
// Get a version of a depth texture with only depth information, not stencil.
virtual gl::Error createDropStencilTexture();
gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it);
// The baseLevel parameter should *not* have mTopLevel applied.
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const = 0;
......@@ -113,6 +117,7 @@ class TextureStorage11 : public TextureStorage
unsigned int mTextureDepth;
gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
ID3D11Texture2D *mDropStencilTexture;
private:
const UINT mBindFlags;
......@@ -120,13 +125,14 @@ class TextureStorage11 : public TextureStorage
struct SRVKey
{
SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false);
SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
bool operator<(const SRVKey &rhs) const;
int baseLevel; // Without mTopLevel applied.
int mipLevels;
bool swizzle;
int baseLevel = 0; // Without mTopLevel applied.
int mipLevels = 0;
bool swizzle = false;
bool dropStencil = false;
};
typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
......@@ -142,30 +148,35 @@ class TextureStorage11_2D : public TextureStorage11
public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
virtual ~TextureStorage11_2D();
~TextureStorage11_2D() override;
virtual gl::Error getResource(ID3D11Resource **outResource);
virtual gl::Error getMippedResource(ID3D11Resource **outResource);
virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getMippedResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
virtual gl::Error copyToStorage(TextureStorage *destStorage);
gl::Error copyToStorage(TextureStorage *destStorage) override;
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override;
gl::Error createDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels);
private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
......@@ -301,6 +312,8 @@ class TextureStorage11_Cube : public TextureStorage11
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error createDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels);
private:
......@@ -384,6 +397,8 @@ class TextureStorage11_2DArray : public TextureStorage11
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error createDropStencilTexture() override;
private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
......
......@@ -1542,6 +1542,9 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
workarounds.preAddTexelFetchOffsets = (adapterDesc.VendorId == VENDOR_ID_INTEL);
// TODO(jmadill): Disable when we have a fixed driver version.
workarounds.emulateTinyStencilTextures = (adapterDesc.VendorId == VENDOR_ID_AMD);
return workarounds;
}
......
......@@ -4,6 +4,8 @@
// found in the LICENSE file.
//
#include <cmath>
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
......@@ -3480,6 +3482,61 @@ TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
EXPECT_EQ(expected, actual);
}
template <typename T>
T UNorm(double value)
{
return static_cast<T>(value * static_cast<double>(std::numeric_limits<T>::max()));
}
// Test rendering a depth texture with mipmaps.
TEST_P(Texture2DTestES3, DepthTexturesWithMipmaps)
{
const int size = getWindowWidth();
auto dim = [size](int level) { return size >> level; };
int levels = static_cast<int>(std::log2(size));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glTexStorage2D(GL_TEXTURE_2D, levels, GL_DEPTH_COMPONENT24, size, size);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
ASSERT_GL_NO_ERROR();
glUseProgram(mProgram);
glUniform1i(mTexture2DUniformLocation, 0);
std::vector<unsigned char> expected;
for (int level = 0; level < levels; ++level)
{
double value = (static_cast<double>(level) / static_cast<double>(levels - 1));
expected.push_back(UNorm<unsigned char>(value));
int levelDim = dim(level);
ASSERT_GT(levelDim, 0);
std::vector<unsigned int> initData(levelDim * levelDim, UNorm<unsigned int>(value));
glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, levelDim, levelDim, GL_DEPTH_COMPONENT,
GL_UNSIGNED_INT, initData.data());
}
ASSERT_GL_NO_ERROR();
for (int level = 0; level < levels; ++level)
{
glViewport(0, 0, dim(level), dim(level));
drawQuad(mProgram, "position", 0.5f);
GLColor actual = ReadColor(0, 0);
EXPECT_NEAR(expected[level], actual.R, 10u);
}
ASSERT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
// TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
ANGLE_INSTANTIATE_TEST(Texture2DTest,
......
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