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 ...@@ -75,6 +75,11 @@ struct WorkaroundsD3D
// and Offset is in range. To work around this, we translatie texelFetchOffset into texelFetch // and Offset is in range. To work around this, we translatie texelFetchOffset into texelFetch
// by adding Offset directly to Location before reading the texture. // by adding Offset directly to Location before reading the texture.
bool preAddTexelFetchOffsets = false; 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 } // namespace rx
......
...@@ -274,6 +274,93 @@ void CopyDepthStencil(const gl::Box &sourceArea, ...@@ -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) Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
{ {
switch (internalFormat) switch (internalFormat)
...@@ -1381,7 +1468,7 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source, ...@@ -1381,7 +1468,7 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destFormat); const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destFormat);
unsigned int destPixelSize = destSizeInfo.pixelBytes; unsigned int destPixelSize = destSizeInfo.pixelBytes;
ASSERT(srcFormat == destFormat); ASSERT(srcFormat == destFormat || destFormat == DXGI_FORMAT_R32_TYPELESS);
if (stencilOnly) if (stencilOnly)
{ {
...@@ -1400,6 +1487,22 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source, ...@@ -1400,6 +1487,22 @@ gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
copySize = 1; 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, return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
destArea, destSize, scissor, copyOffset, copyOffset, copySize, destArea, destSize, scissor, copyOffset, copyOffset, copySize,
srcPixelSize, destPixelSize, StretchedBlitNearest); srcPixelSize, destPixelSize, StretchedBlitNearest);
......
...@@ -419,129 +419,139 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, ...@@ -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: return gl::NoError();
// }
// 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.");
}
rtvs[i] = rtv; // To clear the render targets and depth stencil in one pass:
} //
ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr; // Render a quad clipped to the scissor rectangle which draws the clear color and a blend
// state that will perform the required color masking.
ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); //
const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // The quad's depth is equal to the depth clear value with a depth stencil state that
const UINT sampleMask = 0xFFFFFFFF; // will enable or disable depth test/writes if the depth buffer should be cleared or not.
//
ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); // The rasterizer state's stencil is set to always pass or fail based on if the stencil
const UINT stencilClear = clearParams.stencilClearValue & 0xFF; // should be cleared or not with a stencil write mask of the stencil clear value.
//
// Set the vertices // ======================================================================================
UINT vertexStride = 0; //
const UINT startIdx = 0; // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
ClearShader *shader = nullptr; // buffer that is not normalized fixed point or floating point with floating point values
D3D11_MAPPED_SUBRESOURCE mappedResource; // are undefined so we can just write floats to them and D3D11 will bit cast them to
HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); // integers.
if (FAILED(result)) //
// 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; rtvs[i] = rtv;
switch (clearParams.colorClearType) }
{ ID3D11DepthStencilView *dsv =
case GL_FLOAT: maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData);
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>); vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>);
shader = mFloatClearShader; shader = mFloatClearShader;
break; break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue,
clearParams.depthClearValue, mappedResource.pData);
vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>); vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>);
shader = mUintClearShader; shader = mUintClearShader;
break; break;
case GL_INT: case GL_INT:
ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue,
clearParams.depthClearValue, mappedResource.pData);
vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>); vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>);
shader = mIntClearShader; shader = mIntClearShader;
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; 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) ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
......
...@@ -3079,7 +3079,7 @@ gl::Error Renderer11::copyTexture(const gl::Texture *source, ...@@ -3079,7 +3079,7 @@ gl::Error Renderer11::copyTexture(const gl::Texture *source,
destStorage11->markLevelDirty(destLevel); 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) gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
...@@ -3541,16 +3541,12 @@ gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage, ...@@ -3541,16 +3541,12 @@ gl::Error Renderer11::generateMipmapUsingD3D(TextureStorage *storage,
ASSERT(storage11->supportsNativeMipmapFunction()); ASSERT(storage11->supportsNativeMipmapFunction());
ID3D11ShaderResourceView *srv; ID3D11ShaderResourceView *srv;
gl::Error error = storage11->getSRVLevels(textureState.getEffectiveBaseLevel(), ANGLE_TRY(storage11->getSRVLevels(textureState.getEffectiveBaseLevel(),
textureState.getEffectiveMaxLevel(), &srv); textureState.getEffectiveMaxLevel(), &srv));
if (error.isError())
{
return error;
}
mDeviceContext->GenerateMips(srv); mDeviceContext->GenerateMips(srv);
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
......
...@@ -31,15 +31,15 @@ ...@@ -31,15 +31,15 @@
namespace rx namespace rx
{ {
TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
: baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
{ {
} }
bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
{ {
return std::tie(baseLevel, mipLevels, swizzle) < return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
} }
TextureStorage11::TextureStorage11(Renderer11 *renderer, TextureStorage11::TextureStorage11(Renderer11 *renderer,
...@@ -53,6 +53,7 @@ TextureStorage11::TextureStorage11(Renderer11 *renderer, ...@@ -53,6 +53,7 @@ TextureStorage11::TextureStorage11(Renderer11 *renderer,
mTextureWidth(0), mTextureWidth(0),
mTextureHeight(0), mTextureHeight(0),
mTextureDepth(0), mTextureDepth(0),
mDropStencilTexture(nullptr),
mBindFlags(bindFlags), mBindFlags(bindFlags),
mMiscFlags(miscFlags) mMiscFlags(miscFlags)
{ {
...@@ -73,6 +74,7 @@ TextureStorage11::~TextureStorage11() ...@@ -73,6 +74,7 @@ TextureStorage11::~TextureStorage11()
SafeRelease(i->second); SafeRelease(i->second);
} }
mSrvCache.clear(); mSrvCache.clear();
SafeRelease(mDropStencilTexture);
} }
DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
...@@ -203,11 +205,7 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, ...@@ -203,11 +205,7 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{ {
// We must ensure that the level zero texture is in sync with mipped texture. // We must ensure that the level zero texture is in sync with mipped texture.
gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
if (error.isError())
{
return error;
}
} }
if (swizzleRequired) if (swizzleRequired)
...@@ -215,7 +213,22 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, ...@@ -215,7 +213,22 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
verifySwizzleExists(textureState.getSwizzleState()); 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)); ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
return gl::NoError(); return gl::NoError();
...@@ -232,17 +245,29 @@ gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key, ...@@ -232,17 +245,29 @@ gl::Error TextureStorage11::getCachedOrCreateSRV(const SRVKey &key,
} }
ID3D11Resource *texture = nullptr; ID3D11Resource *texture = nullptr;
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
if (key.swizzle) if (key.swizzle)
{ {
ASSERT(!key.dropStencil ||
d3d11::GetDXGIFormatInfo(mFormatInfo.swizzle.dsvFormat).stencilBits == 0);
ANGLE_TRY(getSwizzleTexture(&texture)); ANGLE_TRY(getSwizzleTexture(&texture));
format = mFormatInfo.swizzle.srvFormat;
}
else if (key.dropStencil)
{
ASSERT(mDropStencilTexture);
texture = mDropStencilTexture;
format = DXGI_FORMAT_R32_FLOAT;
} }
else else
{ {
ANGLE_TRY(getResource(&texture)); ANGLE_TRY(getResource(&texture));
format = mFormatInfo.srvFormat;
} }
ID3D11ShaderResourceView *srv = nullptr; ID3D11ShaderResourceView *srv = nullptr;
DXGI_FORMAT format = (key.swizzle ? mFormatInfo.swizzle.srvFormat : mFormatInfo.srvFormat);
ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv)); ANGLE_TRY(createSRV(key.baseLevel, key.mipLevels, format, texture, &srv));
mSrvCache.insert(std::make_pair(key, srv)); mSrvCache.insert(std::make_pair(key, srv));
...@@ -271,25 +296,17 @@ gl::Error TextureStorage11::getSRVLevel(int mipLevel, ...@@ -271,25 +296,17 @@ gl::Error TextureStorage11::getSRVLevel(int mipLevel,
else else
{ {
ID3D11Resource *resource = nullptr; ID3D11Resource *resource = nullptr;
gl::Error error = getResource(&resource); ANGLE_TRY(getResource(&resource));
if (error.isError())
{
return error;
}
DXGI_FORMAT resourceFormat = DXGI_FORMAT resourceFormat =
blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat; blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
error = createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]); ANGLE_TRY(createSRV(mipLevel, 1, resourceFormat, resource, &levelSRVs[mipLevel]));
if (error.isError())
{
return error;
}
} }
} }
*outSRV = levelSRVs[mipLevel]; *outSRV = levelSRVs[mipLevel];
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
...@@ -310,14 +327,12 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, ...@@ -310,14 +327,12 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel,
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{ {
// We must ensure that the level zero texture is in sync with mipped texture. // We must ensure that the level zero texture is in sync with mipped texture.
gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); ANGLE_TRY(useLevelZeroWorkaroundTexture(mipLevels == 1));
if (error.isError())
{
return error;
}
} }
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)); ANGLE_TRY(getCachedOrCreateSRV(key, outSRV));
return gl::NoError(); return gl::NoError();
...@@ -337,35 +352,22 @@ gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarg ...@@ -337,35 +352,22 @@ gl::Error TextureStorage11::generateSwizzles(const gl::SwizzleState &swizzleTarg
{ {
// Need to re-render the swizzle for this level // Need to re-render the swizzle for this level
ID3D11ShaderResourceView *sourceSRV = nullptr; ID3D11ShaderResourceView *sourceSRV = nullptr;
gl::Error error = getSRVLevel(level, true, &sourceSRV); ANGLE_TRY(getSRVLevel(level, true, &sourceSRV));
if (error.isError())
{
return error;
}
ID3D11RenderTargetView *destRTV = nullptr; ID3D11RenderTargetView *destRTV = nullptr;
error = getSwizzleRenderTarget(level, &destRTV); ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
if (error.isError())
{
return error;
}
gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
Blit11 *blitter = mRenderer->getBlitter(); Blit11 *blitter = mRenderer->getBlitter();
error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget); ANGLE_TRY(blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleTarget));
if (error.isError())
{
return error;
}
mSwizzleCache[level] = swizzleTarget; mSwizzleCache[level] = swizzleTarget;
} }
} }
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
void TextureStorage11::markLevelDirty(int mipLevel) void TextureStorage11::markLevelDirty(int mipLevel)
...@@ -376,6 +378,8 @@ void TextureStorage11::markLevelDirty(int mipLevel) ...@@ -376,6 +378,8 @@ void TextureStorage11::markLevelDirty(int mipLevel)
// not a valid swizzle combination // not a valid swizzle combination
mSwizzleCache[mipLevel] = gl::SwizzleState(); mSwizzleCache[mipLevel] = gl::SwizzleState();
} }
SafeRelease(mDropStencilTexture);
} }
void TextureStorage11::markDirty() void TextureStorage11::markDirty()
...@@ -457,22 +461,16 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture, ...@@ -457,22 +461,16 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource *dstTexture,
ASSERT(dstTexture); ASSERT(dstTexture);
ID3D11Resource *srcTexture = nullptr; 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 // 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. // should update the mipmapped texture, even if mapmaps are currently disabled.
if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{ {
error = getMippedResource(&srcTexture); ANGLE_TRY(getMippedResource(&srcTexture));
} }
else else
{ {
error = getResource(&srcTexture); ANGLE_TRY(getResource(&srcTexture));
}
if (error.isError())
{
return error;
} }
ASSERT(srcTexture); ASSERT(srcTexture);
...@@ -514,18 +512,10 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, ...@@ -514,18 +512,10 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex,
markLevelDirty(destIndex.mipIndex); markLevelDirty(destIndex.mipIndex);
RenderTargetD3D *source = nullptr; RenderTargetD3D *source = nullptr;
gl::Error error = getRenderTarget(sourceIndex, &source); ANGLE_TRY(getRenderTarget(sourceIndex, &source));
if (error.isError())
{
return error;
}
RenderTargetD3D *dest = nullptr; RenderTargetD3D *dest = nullptr;
error = getRenderTarget(destIndex, &dest); ANGLE_TRY(getRenderTarget(destIndex, &dest));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *sourceSRV = ID3D11ShaderResourceView *sourceSRV =
GetAs<RenderTarget11>(source)->getBlitShaderResourceView(); GetAs<RenderTarget11>(source)->getBlitShaderResourceView();
...@@ -582,26 +572,18 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) ...@@ -582,26 +572,18 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
ASSERT(destStorage); ASSERT(destStorage);
ID3D11Resource *sourceResouce = nullptr; ID3D11Resource *sourceResouce = nullptr;
gl::Error error = getResource(&sourceResouce); ANGLE_TRY(getResource(&sourceResouce));
if (error.isError())
{
return error;
}
TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage); TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
ID3D11Resource *destResource = nullptr; ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource); ANGLE_TRY(dest11->getResource(&destResource));
if (error.isError())
{
return error;
}
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
immediateContext->CopyResource(destResource, sourceResouce); immediateContext->CopyResource(destResource, sourceResouce);
dest11->markDirty(); dest11->markDirty();
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error TextureStorage11::setData(const gl::ImageIndex &index, gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
...@@ -708,6 +690,12 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ...@@ -708,6 +690,12 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
return gl::NoError(); 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_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
: TextureStorage11(renderer, : TextureStorage11(renderer,
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
...@@ -831,63 +819,37 @@ gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) ...@@ -831,63 +819,37 @@ gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
// corresponding textures in destStorage. // corresponding textures in destStorage.
if (mTexture) if (mTexture)
{ {
gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(false));
if (error.isError())
{
return error;
}
ID3D11Resource *destResource = nullptr; ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource); ANGLE_TRY(dest11->getResource(&destResource));
if (error.isError())
{
return error;
}
immediateContext->CopyResource(destResource, mTexture); immediateContext->CopyResource(destResource, mTexture);
} }
if (mLevelZeroTexture) if (mLevelZeroTexture)
{ {
gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(true));
if (error.isError())
{
return error;
}
ID3D11Resource *destResource = nullptr; ID3D11Resource *destResource = nullptr;
error = dest11->getResource(&destResource); ANGLE_TRY(dest11->getResource(&destResource));
if (error.isError())
{
return error;
}
immediateContext->CopyResource(destResource, mLevelZeroTexture); 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; ID3D11Resource *sourceResouce = nullptr;
error = dest11->getResource(&destResource); ANGLE_TRY(getResource(&sourceResouce));
if (error.isError())
{
return error;
}
immediateContext->CopyResource(destResource, sourceResouce); ID3D11Resource *destResource = nullptr;
dest11->markDirty(); 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) gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
...@@ -898,11 +860,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe ...@@ -898,11 +860,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe
{ {
if (!mUseLevelZeroTexture && mTexture) if (!mUseLevelZeroTexture && mTexture)
{ {
gl::Error error = ensureTextureExists(1); ANGLE_TRY(ensureTextureExists(1));
if (error.isError())
{
return error;
}
// Pull data back from the mipped texture if necessary. // Pull data back from the mipped texture if necessary.
ASSERT(mLevelZeroTexture); ASSERT(mLevelZeroTexture);
...@@ -916,11 +874,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe ...@@ -916,11 +874,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe
{ {
if (mUseLevelZeroTexture && mLevelZeroTexture) if (mUseLevelZeroTexture && mLevelZeroTexture)
{ {
gl::Error error = ensureTextureExists(mMipLevels); ANGLE_TRY(ensureTextureExists(mMipLevels));
if (error.isError())
{
return error;
}
// Pull data back from the level zero texture if necessary. // Pull data back from the level zero texture if necessary.
ASSERT(mTexture); ASSERT(mTexture);
...@@ -947,7 +901,7 @@ gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTe ...@@ -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) void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
...@@ -1029,33 +983,23 @@ gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &inde ...@@ -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) gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
{ {
if (mUseLevelZeroTexture && mMipLevels > 1) if (mUseLevelZeroTexture && mMipLevels > 1)
{ {
gl::Error error = ensureTextureExists(1); ANGLE_TRY(ensureTextureExists(1));
if (error.isError())
{
return error;
}
*outResource = mLevelZeroTexture; *outResource = mLevelZeroTexture;
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
else
{
gl::Error error = ensureTextureExists(mMipLevels);
if (error.isError())
{
return error;
}
*outResource = mTexture; ANGLE_TRY(ensureTextureExists(mMipLevels));
return gl::Error(GL_NO_ERROR);
} *outResource = mTexture;
return gl::NoError();
} }
gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
...@@ -1063,14 +1007,10 @@ 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. // This shouldn't be called unless the zero max LOD workaround is active.
ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
gl::Error error = ensureTextureExists(mMipLevels); ANGLE_TRY(ensureTextureExists(mMipLevels));
if (error.isError())
{
return error;
}
*outResource = mTexture; *outResource = mTexture;
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
...@@ -1144,29 +1084,17 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -1144,29 +1084,17 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
if (mRenderTarget[level]) if (mRenderTarget[level])
{ {
*outRT = mRenderTarget[level]; *outRT = mRenderTarget[level];
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
ID3D11Resource *texture = nullptr; ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture); ANGLE_TRY(getResource(&texture));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *srv = nullptr; ID3D11ShaderResourceView *srv = nullptr;
error = getSRVLevel(level, false, &srv); ANGLE_TRY(getSRVLevel(level, false, &srv));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *blitSRV = nullptr; ID3D11ShaderResourceView *blitSRV = nullptr;
error = getSRVLevel(level, true, &blitSRV); ANGLE_TRY(getSRVLevel(level, true, &blitSRV));
if (error.isError())
{
return error;
}
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
...@@ -1200,7 +1128,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -1200,7 +1128,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
} }
*outRT = mLevelZeroRenderTarget; *outRT = mLevelZeroRenderTarget;
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
...@@ -1261,7 +1189,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -1261,7 +1189,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
SafeRelease(dsv); SafeRelease(dsv);
*outRT = mRenderTarget[level]; *outRT = mRenderTarget[level];
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error TextureStorage11_2D::createSRV(int baseLevel, gl::Error TextureStorage11_2D::createSRV(int baseLevel,
...@@ -1387,7 +1315,41 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render ...@@ -1387,7 +1315,41 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
} }
*outRTV = mSwizzleRenderTargets[mipLevel]; *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( TextureStorage11_External::TextureStorage11_External(
...@@ -2575,6 +2537,66 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ...@@ -2575,6 +2537,66 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
return gl::Error(GL_NO_ERROR); 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, TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
GLenum internalformat, GLenum internalformat,
bool renderTarget, bool renderTarget,
...@@ -2812,25 +2834,13 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend ...@@ -2812,25 +2834,13 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
if (!mLevelRenderTargets[mipLevel]) if (!mLevelRenderTargets[mipLevel])
{ {
ID3D11Resource *texture = nullptr; ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture); ANGLE_TRY(getResource(&texture));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *srv = nullptr; ID3D11ShaderResourceView *srv = nullptr;
error = getSRVLevel(mipLevel, false, &srv); ANGLE_TRY(getSRVLevel(mipLevel, false, &srv));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *blitSRV = nullptr; ID3D11ShaderResourceView *blitSRV = nullptr;
error = getSRVLevel(mipLevel, true, &blitSRV); ANGLE_TRY(getSRVLevel(mipLevel, true, &blitSRV));
if (error.isError())
{
return error;
}
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
...@@ -2971,11 +2981,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render ...@@ -2971,11 +2981,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
if (!mSwizzleRenderTargets[mipLevel]) if (!mSwizzleRenderTargets[mipLevel])
{ {
ID3D11Resource *swizzleTexture = nullptr; ID3D11Resource *swizzleTexture = nullptr;
gl::Error error = getSwizzleTexture(&swizzleTexture); ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
if (error.isError())
{
return error;
}
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
...@@ -3275,21 +3281,14 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, ...@@ -3275,21 +3281,14 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
HRESULT result; HRESULT result;
ID3D11Resource *texture = nullptr; ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture); ANGLE_TRY(getResource(&texture));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *srv; ID3D11ShaderResourceView *srv;
error = createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv); ANGLE_TRY(createRenderTargetSRV(texture, index, mFormatInfo.srvFormat, &srv));
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *blitSRV; ID3D11ShaderResourceView *blitSRV;
if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
{ {
error = createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV); gl::Error error =
createRenderTargetSRV(texture, index, mFormatInfo.blitSRVFormat, &blitSRV);
if (error.isError()) if (error.isError())
{ {
SafeRelease(srv); SafeRelease(srv);
...@@ -3377,7 +3376,7 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, ...@@ -3377,7 +3376,7 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index,
ASSERT(outRT); ASSERT(outRT);
*outRT = mRenderTargets[key]; *outRT = mRenderTargets[key];
return gl::Error(GL_NO_ERROR); return gl::NoError();
} }
gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
...@@ -3454,4 +3453,42 @@ gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ...@@ -3454,4 +3453,42 @@ gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
*outRTV = mSwizzleRenderTargets[mipLevel]; *outRTV = mSwizzleRenderTargets[mipLevel];
return gl::Error(GL_NO_ERROR); 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 } // namespace rx
...@@ -94,6 +94,10 @@ class TextureStorage11 : public TextureStorage ...@@ -94,6 +94,10 @@ class TextureStorage11 : public TextureStorage
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV); 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. // The baseLevel parameter should *not* have mTopLevel applied.
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const = 0; ID3D11ShaderResourceView **outSRV) const = 0;
...@@ -113,6 +117,7 @@ class TextureStorage11 : public TextureStorage ...@@ -113,6 +117,7 @@ class TextureStorage11 : public TextureStorage
unsigned int mTextureDepth; unsigned int mTextureDepth;
gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
ID3D11Texture2D *mDropStencilTexture;
private: private:
const UINT mBindFlags; const UINT mBindFlags;
...@@ -120,13 +125,14 @@ class TextureStorage11 : public TextureStorage ...@@ -120,13 +125,14 @@ class TextureStorage11 : public TextureStorage
struct SRVKey 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; bool operator<(const SRVKey &rhs) const;
int baseLevel; // Without mTopLevel applied. int baseLevel = 0; // Without mTopLevel applied.
int mipLevels; int mipLevels = 0;
bool swizzle; bool swizzle = false;
bool dropStencil = false;
}; };
typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache; typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
...@@ -142,30 +148,35 @@ class TextureStorage11_2D : public TextureStorage11 ...@@ -142,30 +148,35 @@ class TextureStorage11_2D : public TextureStorage11
public: public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); 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); gl::Error getResource(ID3D11Resource **outResource) override;
virtual gl::Error getMippedResource(ID3D11Resource **outResource); gl::Error getMippedResource(ID3D11Resource **outResource) override;
virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); 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); void associateImage(Image11 *image, const gl::ImageIndex &index) override;
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
protected: protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override;
gl::Error createDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels); gl::Error ensureTextureExists(int mipLevels);
private: private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, gl::Error createSRV(int baseLevel,
ID3D11ShaderResourceView **outSRV) const; int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
ID3D11Texture2D *mTexture; ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
...@@ -301,6 +312,8 @@ class TextureStorage11_Cube : public TextureStorage11 ...@@ -301,6 +312,8 @@ class TextureStorage11_Cube : public TextureStorage11
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error createDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels); gl::Error ensureTextureExists(int mipLevels);
private: private:
...@@ -384,6 +397,8 @@ class TextureStorage11_2DArray : public TextureStorage11 ...@@ -384,6 +397,8 @@ class TextureStorage11_2DArray : public TextureStorage11
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
gl::Error createDropStencilTexture() override;
private: private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const; ID3D11ShaderResourceView **outSRV) const;
......
...@@ -1542,6 +1542,9 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, ...@@ -1542,6 +1542,9 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
workarounds.preAddTexelFetchOffsets = (adapterDesc.VendorId == VENDOR_ID_INTEL); 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; return workarounds;
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include <cmath>
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h" #include "test_utils/gl_raii.h"
...@@ -3480,6 +3482,61 @@ TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer) ...@@ -3480,6 +3482,61 @@ TEST_P(Texture2DTestES3, UnpackOverlappingRowsFromUnpackBuffer)
EXPECT_EQ(expected, actual); 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. // 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. // TODO(oetuaho): Enable all below tests on OpenGL. Requires a fix for ANGLE bug 1278.
ANGLE_INSTANTIATE_TEST(Texture2DTest, 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