Commit 8becd0cb by Geoff Lang

Updated Image11 to use gl::Errors for staging texture manipulation.

BUG=angle:520 Change-Id: I5792b139ddd69c2cabc3b901a7067438c1ee363b Reviewed-on: https://chromium-review.googlesource.com/221395Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 06ecf3dd
...@@ -57,18 +57,18 @@ gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src) ...@@ -57,18 +57,18 @@ gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src)
ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL);
D3D11_MAPPED_SUBRESOURCE destMapped; D3D11_MAPPED_SUBRESOURCE destMapped;
HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped);
if (FAILED(destMapResult)) if (error.isError())
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map destination image for mipmap generation, result: 0x%X", destMapResult); return error;
} }
D3D11_MAPPED_SUBRESOURCE srcMapped; D3D11_MAPPED_SUBRESOURCE srcMapped;
HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped); error = src->map(D3D11_MAP_READ, &srcMapped);
if (FAILED(srcMapResult)) if (error.isError())
{ {
dest->unmap(); dest->unmap();
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map source image for mip map generation, result: 0x%X", srcMapResult); return error;
} }
const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData); const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData);
...@@ -120,8 +120,15 @@ gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex & ...@@ -120,8 +120,15 @@ gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &
} }
} }
gl::Error error = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), ID3D11Resource *stagingTexture = NULL;
index, region); unsigned int stagingSubresourceIndex = 0;
gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
if (error.isError())
{
return error;
}
error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -149,7 +156,11 @@ gl::Error Image11::recoverFromAssociatedStorage() ...@@ -149,7 +156,11 @@ gl::Error Image11::recoverFromAssociatedStorage()
{ {
if (mRecoverFromStorage) if (mRecoverFromStorage)
{ {
createStagingTexture(); gl::Error error = createStagingTexture();
if (error.isError())
{
return error;
}
bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this);
...@@ -161,7 +172,7 @@ gl::Error Image11::recoverFromAssociatedStorage() ...@@ -161,7 +172,7 @@ gl::Error Image11::recoverFromAssociatedStorage()
{ {
// CopySubResource from the Storage to the Staging texture // CopySubResource from the Storage to the Staging texture
gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
gl::Error error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region);
if (error.isError()) if (error.isError())
{ {
return error; return error;
...@@ -217,7 +228,7 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, ...@@ -217,7 +228,7 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat,
mActualFormat = dxgiFormatInfo.internalFormat; mActualFormat = dxgiFormatInfo.internalFormat;
mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
SafeRelease(mStagingTexture); releaseStagingTexture();
mDirty = (formatInfo.dataInitializerFunction != NULL); mDirty = (formatInfo.dataInitializerFunction != NULL);
return true; return true;
...@@ -251,10 +262,10 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei ...@@ -251,10 +262,10 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei
LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
D3D11_MAPPED_SUBRESOURCE mappedImage; D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result)) if (error.isError())
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Could not map internal image for loading texture data, result: 0x%X.", result); return error;
} }
uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch));
...@@ -286,10 +297,10 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse ...@@ -286,10 +297,10 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse
LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE);
D3D11_MAPPED_SUBRESOURCE mappedImage; D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result)) if (error.isError())
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Could not map internal image for loading texture data, result: 0x%X.", result); return error;
} }
uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch +
...@@ -359,6 +370,14 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R ...@@ -359,6 +370,14 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
if (textureDesc.Format == mDXGIFormat) if (textureDesc.Format == mDXGIFormat)
{ {
// No conversion needed-- use copyback fastpath // No conversion needed-- use copyback fastpath
ID3D11Resource *stagingTexture = NULL;
unsigned int stagingSubresourceIndex = 0;
gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
if (error.isError())
{
return error;
}
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -402,7 +421,7 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R ...@@ -402,7 +421,7 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
srcBox.front = 0; srcBox.front = 0;
srcBox.back = 1; srcBox.back = 1;
deviceContext->CopySubresourceRegion(getStagingTexture(), 0, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox); deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);
if (textureDesc.SampleDesc.Count > 1) if (textureDesc.SampleDesc.Count > 1)
{ {
...@@ -413,10 +432,10 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R ...@@ -413,10 +432,10 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
{ {
// This format requires conversion, so we must copy the texture to staging and manually convert via readPixels // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
D3D11_MAPPED_SUBRESOURCE mappedImage; D3D11_MAPPED_SUBRESOURCE mappedImage;
HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
if (FAILED(result)) if (error.isError())
{ {
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map texture for Image11::copy, HRESULT: 0x%X.", result); return error;
} }
// determine the offset coordinate into the destination buffer // determine the offset coordinate into the destination buffer
...@@ -425,7 +444,7 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R ...@@ -425,7 +444,7 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
gl::Error error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
unmap(); unmap();
...@@ -440,11 +459,17 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R ...@@ -440,11 +459,17 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
ID3D11Resource *Image11::getStagingTexture() gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex)
{ {
createStagingTexture(); gl::Error error = createStagingTexture();
if (error.isError())
{
return error;
}
return mStagingTexture; *outStagingTexture = mStagingTexture;
*outSubresourceIndex = mStagingSubresource;
return gl::Error(GL_NO_ERROR);
} }
void Image11::releaseStagingTexture() void Image11::releaseStagingTexture()
...@@ -452,149 +477,149 @@ void Image11::releaseStagingTexture() ...@@ -452,149 +477,149 @@ void Image11::releaseStagingTexture()
SafeRelease(mStagingTexture); SafeRelease(mStagingTexture);
} }
unsigned int Image11::getStagingSubresource() gl::Error Image11::createStagingTexture()
{
createStagingTexture();
return mStagingSubresource;
}
void Image11::createStagingTexture()
{ {
if (mStagingTexture) if (mStagingTexture)
{ {
return; return gl::Error(GL_NO_ERROR);
} }
ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
const DXGI_FORMAT dxgiFormat = getDXGIFormat(); const DXGI_FORMAT dxgiFormat = getDXGIFormat();
if (mWidth > 0 && mHeight > 0 && mDepth > 0) ID3D11Device *device = mRenderer->getDevice();
{ HRESULT result;
ID3D11Device *device = mRenderer->getDevice();
HRESULT result;
int lodOffset = 1; int lodOffset = 1;
GLsizei width = mWidth; GLsizei width = mWidth;
GLsizei height = mHeight; GLsizei height = mHeight;
// adjust size if needed for compressed textures // adjust size if needed for compressed textures
d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
if (mTarget == GL_TEXTURE_3D) if (mTarget == GL_TEXTURE_3D)
{
ID3D11Texture3D *newTexture = NULL;
D3D11_TEXTURE3D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.Depth = mDepth;
desc.MipLevels = lodOffset + 1;
desc.Format = dxgiFormat;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
{ {
ID3D11Texture3D *newTexture = NULL; std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
D3D11_TEXTURE3D_DESC desc; d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
desc.Width = width; lodOffset + 1, &initialData, &textureData);
desc.Height = height;
desc.Depth = mDepth;
desc.MipLevels = lodOffset + 1;
desc.Format = dxgiFormat;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
lodOffset + 1, &initialData, &textureData);
result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
}
else
{
result = device->CreateTexture3D(&desc, NULL, &newTexture);
}
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
ERR("Creating image failed.");
return gl::error(GL_OUT_OF_MEMORY);
}
mStagingTexture = newTexture; result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
} }
else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) else
{ {
ID3D11Texture2D *newTexture = NULL; result = device->CreateTexture3D(&desc, NULL, &newTexture);
}
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = lodOffset + 1;
desc.ArraySize = 1;
desc.Format = dxgiFormat;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
lodOffset + 1, &initialData, &textureData);
result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); if (FAILED(result))
} {
else ASSERT(result == E_OUTOFMEMORY);
{ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
result = device->CreateTexture2D(&desc, NULL, &newTexture); }
}
if (FAILED(result)) mStagingTexture = newTexture;
{ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
ASSERT(result == E_OUTOFMEMORY); }
ERR("Creating image failed."); else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP)
return gl::error(GL_OUT_OF_MEMORY); {
} ID3D11Texture2D *newTexture = NULL;
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = lodOffset + 1;
desc.ArraySize = 1;
desc.Format = dxgiFormat;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
lodOffset + 1, &initialData, &textureData);
mStagingTexture = newTexture; result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
} }
else else
{ {
UNREACHABLE(); result = device->CreateTexture2D(&desc, NULL, &newTexture);
}
if (FAILED(result))
{
ASSERT(result == E_OUTOFMEMORY);
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
} }
mStagingTexture = newTexture;
mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
}
else
{
UNREACHABLE();
} }
mDirty = false; mDirty = false;
return gl::Error(GL_NO_ERROR);
} }
HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{ {
createStagingTexture();
// We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
recoverFromAssociatedStorage(); gl::Error error = recoverFromAssociatedStorage();
if (error.isError())
HRESULT result = E_FAIL; {
return error;
}
if (mStagingTexture) ID3D11Resource *stagingTexture = NULL;
unsigned int subresourceIndex = 0;
error = getStagingTexture(&stagingTexture, &subresourceIndex);
if (error.isError())
{ {
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); return error;
result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); }
// this can fail if the device is removed (from TDR) ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
if (d3d11::isDeviceLostError(result))
{ ASSERT(mStagingTexture);
mRenderer->notifyDeviceLost(); HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);
}
else if (SUCCEEDED(result)) // this can fail if the device is removed (from TDR)
{ if (d3d11::isDeviceLostError(result))
mDirty = true; {
} mRenderer->notifyDeviceLost();
}
else if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
} }
return result; mDirty = true;
return gl::Error(GL_NO_ERROR);
} }
void Image11::unmap() void Image11::unmap()
......
...@@ -58,7 +58,7 @@ class Image11 : public ImageD3D ...@@ -58,7 +58,7 @@ class Image11 : public ImageD3D
void disassociateStorage(); void disassociateStorage();
protected: protected:
HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
void unmap(); void unmap();
private: private:
...@@ -67,9 +67,8 @@ class Image11 : public ImageD3D ...@@ -67,9 +67,8 @@ class Image11 : public ImageD3D
gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region); gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region);
gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource); gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource);
ID3D11Resource *getStagingTexture(); gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
unsigned int getStagingSubresource(); gl::Error createStagingTexture();
void createStagingTexture();
void releaseStagingTexture(); void releaseStagingTexture();
Renderer11 *mRenderer; Renderer11 *mRenderer;
......
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