Enable TexSubImage workaround on D3D11.
This workaround uses UpdateResource instead of staging buffers for
texture data updates. It improves performance for highly dynamic
textures, especially in some benchmarks, eg the turbulenz particle
demo.
BUG=angle:729
BUG=365078
Change-Id: Idd82c27845a772199caef3695111c96735e8843e
Reviewed-on: https://chromium-review.googlesource.com/219864
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
index f61fc0d..a467238 100644
--- a/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -130,7 +130,7 @@
gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
{
- const void *pixelData = pixels;
+ const uint8_t *pixelData = static_cast<const uint8_t *>(pixels);
// CPU readback & copy where direct GPU copy is not supported
if (unpack.pixelBuffer.id() != 0)
@@ -140,7 +140,7 @@
// TODO: setImage/subImage is the only place outside of renderer that asks for a buffers raw data.
// This functionality should be moved into renderer and the getData method of BufferImpl removed.
const void *bufferData = pixelBuffer->getImplementation()->getData();
- pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+ pixelData = static_cast<const uint8_t *>(bufferData)+offset;
}
if (pixelData != NULL)
@@ -148,6 +148,16 @@
Image *image = getImage(index);
ASSERT(image);
+ gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
+ gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
+
+ // TODO(jmadill): Handle compressed internal formats
+ if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && !internalFormat.compressed)
+ {
+ return getNativeTexture()->setData(index, region, image->getInternalFormat(),
+ type, unpack, pixelData);
+ }
+
gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment,
type, pixelData);
if (error.isError())
@@ -155,7 +165,6 @@
return error;
}
- gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
error = commitRegion(index, region);
if (error.isError())
{
@@ -261,17 +270,37 @@
void TextureD3D::generateMipmaps()
{
- // Set up proper image sizes.
+ // Set up proper mipmap chain in our Image array.
initMipmapsImages();
// We know that all layers have the same dimension, for the texture to be complete
GLint layerCount = static_cast<GLint>(getLayerCount(0));
GLint mipCount = mipLevels();
- // The following will create and initialize the storage, or update it if it exists
- TextureStorage *storage = getNativeTexture();
+ // When making mipmaps with the setData workaround enabled, the texture storage has
+ // the image data already. For non-render-target storage, we have to pull it out into
+ // an image layer.
+ if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage)
+ {
+ if (!mTexStorage->isRenderTarget())
+ {
+ // Copy from the storage mip 0 to Image mip 0
+ for (GLint layer = 0; layer < layerCount; ++layer)
+ {
+ gl::ImageIndex srcIndex = getImageIndex(0, layer);
- bool renderableStorage = (storage && storage->isRenderTarget());
+ Image *image = getImage(srcIndex);
+ gl::Rectangle area(0, 0, image->getWidth(), image->getHeight());
+ image->copy(0, 0, 0, area, srcIndex, mTexStorage);
+ }
+ }
+ else
+ {
+ updateStorage();
+ }
+ }
+
+ bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget());
for (GLint layer = 0; layer < layerCount; ++layer)
{
@@ -285,7 +314,7 @@
if (renderableStorage)
{
// GPU-side mipmapping
- storage->generateMipmap(sourceIndex, destIndex);
+ mTexStorage->generateMipmap(sourceIndex, destIndex);
}
else
{
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
index da25632..35a22e0 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
@@ -323,27 +323,54 @@
void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source)
{
- RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(source);
- ASSERT(renderTarget->getTexture());
+ RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source);
+ ASSERT(sourceRenderTarget->getTexture());
- ID3D11Texture2D *colorBufferTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTarget->getTexture());
- unsigned int subresourceIndex = renderTarget->getSubresourceIndex();
+ ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(sourceRenderTarget->getTexture());
+ unsigned int subresourceIndex = sourceRenderTarget->getSubresourceIndex();
- if (!colorBufferTexture)
+ if (!sourceTexture2D)
{
// Error already generated
return;
}
- if (source->getActualFormat() == mActualFormat)
+ copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
+}
+
+void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source)
+{
+ TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source);
+
+ UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex.mipIndex, sourceIndex.layerIndex);
+ ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(sourceStorage11->getResource());
+
+ if (!sourceTexture2D)
+ {
+ // Error already generated
+ return;
+ }
+
+ copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
+}
+
+void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource)
+{
+ // TODO(jmadill): get the actual/native/dxgi format without a GetDesc query
+ D3D11_TEXTURE2D_DESC sourceDesc;
+ source->GetDesc(&sourceDesc);
+
+ if (sourceDesc.Format == mDXGIFormat)
{
// No conversion needed-- use copyback fastpath
D3D11_TEXTURE2D_DESC textureDesc;
- colorBufferTexture->GetDesc(&textureDesc);
+ source->GetDesc(&textureDesc);
ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ UINT subresourceAfterResolve = sourceSubResource;
+
ID3D11Texture2D* srcTex = NULL;
if (textureDesc.SampleDesc.Count > 1)
{
@@ -367,12 +394,12 @@
return;
}
- deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
- subresourceIndex = 0;
+ deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format);
+ subresourceAfterResolve = 0;
}
else
{
- srcTex = colorBufferTexture;
+ srcTex = source;
srcTex->AddRef();
}
@@ -384,10 +411,10 @@
srcBox.front = 0;
srcBox.back = 1;
- deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox);
+ deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);
SafeRelease(srcTex);
- SafeRelease(colorBufferTexture);
+ SafeRelease(source);
}
else
{
@@ -406,7 +433,7 @@
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- mRenderer->readTextureData(colorBufferTexture, subresourceIndex, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+ mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
unmap();
}
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/libGLESv2/renderer/d3d/d3d11/Image11.h
index 07222ba..d01b18c 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Image11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.h
@@ -52,6 +52,8 @@
const void *input);
virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
+ virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+ const gl::ImageIndex &sourceIndex, TextureStorage *source);
bool recoverFromAssociatedStorage();
bool isAssociatedStorageValid(TextureStorage11* textureStorage) const;
@@ -65,6 +67,7 @@
DISALLOW_COPY_AND_ASSIGN(Image11);
gl::Error copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource);
ID3D11Resource *getStagingTexture();
unsigned int getStagingSubresource();
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
index efdf6e2..3164ce9 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1076,6 +1076,7 @@
{
Workarounds workarounds;
workarounds.mrtPerfWorkaround = true;
+ workarounds.setDataFasterThanImageUpload = true;
return workarounds;
}
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
index a1ec0a4..10606af 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
@@ -717,4 +717,10 @@
mDirty = true;
}
+void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage)
+{
+ // Currently unreachable, due to only being used in a D3D11-only workaround
+ UNIMPLEMENTED();
+}
+
}
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/libGLESv2/renderer/d3d/d3d9/Image9.h
index a5fcfa8..125f06b 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Image9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Image9.h
@@ -55,6 +55,8 @@
const void *input);
virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
+ virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+ const gl::ImageIndex &sourceIndex, TextureStorage *source);
private:
DISALLOW_COPY_AND_ASSIGN(Image9);
diff --git a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
index 4310918..96795e4 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -543,6 +543,7 @@
{
Workarounds workarounds;
workarounds.mrtPerfWorkaround = true;
+ workarounds.setDataFasterThanImageUpload = false;
return workarounds;
}