Commit 2e60034b by Jamie Madill Committed by Commit Bot

D3D11: Store Buffer SRVs in native storage.

This allows us to not store std::pairs to identify SRVs. Instead we can release the cached SRVs directly when we re-create the native buffer. BUG=angleproject:1513 Change-Id: I6f6d5edc659aa843c9439b97661073415f1a772b Reviewed-on: https://chromium-review.googlesource.com/385818 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 30e11ab2
...@@ -139,14 +139,18 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage ...@@ -139,14 +139,18 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
uint8_t **mapPointerOut) override; uint8_t **mapPointerOut) override;
void unmap() override; void unmap() override;
gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat);
private: private:
static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer, Renderer11 *renderer,
BufferUsage usage, BufferUsage usage,
unsigned int bufferSize); unsigned int bufferSize);
void clearSRVs();
ID3D11Buffer *mNativeStorage; ID3D11Buffer *mNativeStorage;
const angle::BroadcastChannel *mOnStorageChanged; const angle::BroadcastChannel *mOnStorageChanged;
std::map<DXGI_FORMAT, ID3D11ShaderResourceView *> mBufferResourceViews;
}; };
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data // A emulated indexed buffer storage represents an underlying D3D11 buffer for data
...@@ -271,11 +275,6 @@ Buffer11::~Buffer11() ...@@ -271,11 +275,6 @@ Buffer11::~Buffer11()
} }
mRenderer->onBufferDelete(this); mRenderer->onBufferDelete(this);
for (auto &srv : mBufferResourceViews)
{
SafeRelease(srv.second.second);
}
} }
gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage) gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage)
...@@ -577,42 +576,8 @@ gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFo ...@@ -577,42 +576,8 @@ gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFo
{ {
BufferStorage *storage = nullptr; BufferStorage *storage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage); ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage);
ID3D11Buffer *buffer = GetAs<NativeStorage>(storage)->getNativeStorage(); NativeStorage *nativeStorage = GetAs<NativeStorage>(storage);
return nativeStorage->getSRVForFormat(srvFormat);
auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
if (bufferSRVIt != mBufferResourceViews.end())
{
if (bufferSRVIt->second.first == buffer)
{
return bufferSRVIt->second.second;
}
else
{
// The underlying buffer has changed since the SRV was created: recreate the SRV.
SafeRelease(bufferSRVIt->second.second);
}
}
ID3D11Device *device = mRenderer->getDevice();
ID3D11ShaderResourceView *bufferSRV = nullptr;
const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
bufferSRVDesc.Buffer.ElementOffset = 0;
bufferSRVDesc.Buffer.ElementWidth =
static_cast<unsigned int>(mSize) / dxgiFormatInfo.pixelBytes;
bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
bufferSRVDesc.Format = srvFormat;
HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);
return bufferSRV;
} }
gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment,
...@@ -856,6 +821,8 @@ angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel() ...@@ -856,6 +821,8 @@ angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel()
return &mDirectBroadcastChannel; return &mDirectBroadcastChannel;
} }
// Buffer11::BufferStorage implementation
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
: mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
{ {
...@@ -875,6 +842,8 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s ...@@ -875,6 +842,8 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s
return gl::NoError(); return gl::NoError();
} }
// Buffer11::NativeStorage implementation
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
BufferUsage usage, BufferUsage usage,
const angle::BroadcastChannel *onStorageChanged) const angle::BroadcastChannel *onStorageChanged)
...@@ -885,6 +854,7 @@ Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, ...@@ -885,6 +854,7 @@ Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
Buffer11::NativeStorage::~NativeStorage() Buffer11::NativeStorage::~NativeStorage()
{ {
SafeRelease(mNativeStorage); SafeRelease(mNativeStorage);
clearSRVs();
} }
bool Buffer11::NativeStorage::isMappable(GLbitfield access) const bool Buffer11::NativeStorage::isMappable(GLbitfield access) const
...@@ -969,7 +939,7 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) ...@@ -969,7 +939,7 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
ID3D11DeviceContext *context = mRenderer->getDeviceContext(); ID3D11DeviceContext *context = mRenderer->getDeviceContext();
D3D11_BUFFER_DESC bufferDesc; D3D11_BUFFER_DESC bufferDesc;
fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size)); FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
ID3D11Buffer *newBuffer; ID3D11Buffer *newBuffer;
HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer); HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer);
...@@ -1004,6 +974,9 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) ...@@ -1004,6 +974,9 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
mBufferSize = bufferDesc.ByteWidth; mBufferSize = bufferDesc.ByteWidth;
// Free the SRVs.
clearSRVs();
// Notify that the storage has changed. // Notify that the storage has changed.
if (mOnStorageChanged) if (mOnStorageChanged)
{ {
...@@ -1013,7 +986,8 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) ...@@ -1013,7 +986,8 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
return gl::NoError(); return gl::NoError();
} }
void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, // static
void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer, Renderer11 *renderer,
BufferUsage usage, BufferUsage usage,
unsigned int bufferSize) unsigned int bufferSize)
...@@ -1103,6 +1077,51 @@ void Buffer11::NativeStorage::unmap() ...@@ -1103,6 +1077,51 @@ void Buffer11::NativeStorage::unmap()
context->Unmap(mNativeStorage, 0); context->Unmap(mNativeStorage, 0);
} }
gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat(
DXGI_FORMAT srvFormat)
{
auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
if (bufferSRVIt != mBufferResourceViews.end())
{
return bufferSRVIt->second;
}
ID3D11Device *device = mRenderer->getDevice();
ID3D11ShaderResourceView *bufferSRV = nullptr;
const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
bufferSRVDesc.Buffer.ElementOffset = 0;
bufferSRVDesc.Buffer.ElementWidth = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes;
bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
bufferSRVDesc.Format = srvFormat;
HRESULT result = device->CreateShaderResourceView(mNativeStorage, &bufferSRVDesc, &bufferSRV);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY,
"Error creating buffer SRV in Buffer11::NativeStorage::getSRVForFormat");
}
mBufferResourceViews[srvFormat] = bufferSRV;
return bufferSRV;
}
void Buffer11::NativeStorage::clearSRVs()
{
for (auto &srv : mBufferResourceViews)
{
SafeRelease(srv.second);
}
mBufferResourceViews.clear();
}
// Buffer11::EmulatedIndexStorage implementation
Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
: BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr)
{ {
...@@ -1275,6 +1294,8 @@ void Buffer11::EmulatedIndexedStorage::unmap() ...@@ -1275,6 +1294,8 @@ void Buffer11::EmulatedIndexedStorage::unmap()
// No-op // No-op
} }
// Buffer11::PackStorage implementation
Buffer11::PackStorage::PackStorage(Renderer11 *renderer) Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
: BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
{ {
...@@ -1406,6 +1427,8 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() ...@@ -1406,6 +1427,8 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
return gl::NoError(); return gl::NoError();
} }
// Buffer11::SystemMemoryStorage implementation
Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
: Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
{ {
......
...@@ -130,9 +130,6 @@ class Buffer11 : public BufferD3D ...@@ -130,9 +130,6 @@ class Buffer11 : public BufferD3D
size_t mConstantBufferStorageAdditionalSize; size_t mConstantBufferStorageAdditionalSize;
unsigned int mMaxConstantBufferLruCount; unsigned int mMaxConstantBufferLruCount;
typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair;
std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews;
unsigned int mReadUsageCount; unsigned int mReadUsageCount;
unsigned int mSystemMemoryDeallocThreshold; unsigned int mSystemMemoryDeallocThreshold;
......
...@@ -3566,7 +3566,7 @@ TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer) ...@@ -3566,7 +3566,7 @@ TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127); std::vector<GLubyte> bufferData(getWindowWidth() * getWindowHeight(), 127);
// Pull in the color data from the unpack buffer. // Pull in the color data from the unpack buffer.
angle::GLBuffer unpackBuffer; GLBuffer unpackBuffer;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get()); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(), glBufferData(GL_PIXEL_UNPACK_BUFFER, getWindowWidth() * getWindowHeight(), bufferData.data(),
...@@ -3581,12 +3581,51 @@ TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer) ...@@ -3581,12 +3581,51 @@ TEST_P(Texture2DTestES3, UnsizedAlphaUnpackBuffer)
// Draw with the alpha texture and verify. // Draw with the alpha texture and verify.
drawQuad(mProgram, "position", 0.5f); drawQuad(mProgram, "position", 0.5f);
swapBuffers();
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1); EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 127, 1);
} }
// Ensure stale unpack data doesn't propagate in D3D11.
TEST_P(Texture2DTestES3, StaleUnpackData)
{
// Init unpack buffer.
GLsizei pixelCount = getWindowWidth() * getWindowHeight() / 2;
std::vector<GLColor> pixels(pixelCount, GLColor::red);
GLBuffer unpackBuffer;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBuffer.get());
GLsizei bufferSize = pixelCount * sizeof(GLColor);
glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, pixels.data(), GL_STATIC_DRAW);
// Create from unpack buffer.
glBindTexture(GL_TEXTURE_2D, mTexture2D);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth() / 2, getWindowHeight() / 2, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
drawQuad(mProgram, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
// Fill unpack with green, recreating buffer.
pixels.assign(getWindowWidth() * getWindowHeight(), GLColor::green);
GLsizei size2 = getWindowWidth() * getWindowHeight() * sizeof(GLColor);
glBufferData(GL_PIXEL_UNPACK_BUFFER, size2, pixels.data(), GL_STATIC_DRAW);
// Reinit texture with green.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
GL_UNSIGNED_BYTE, nullptr);
drawQuad(mProgram, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// 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