summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp')
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp360
1 files changed, 119 insertions, 241 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 90668b759..107a577e4 100755
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -38,34 +38,12 @@ enum class CopyResult
NOT_RECREATED,
};
-void CalculateConstantBufferParams(GLintptr offset,
- GLsizeiptr size,
- UINT *outFirstConstant,
- UINT *outNumConstants)
-{
- // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
- ASSERT(offset % 256 == 0);
-
- // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must
- // be a multiple of 16 constants.
- *outFirstConstant = static_cast<UINT>(offset / 16);
-
- // The GL size is not required to be aligned to a 256 bytes boundary.
- // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
- *outNumConstants = static_cast<UINT>(rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16);
-
- // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size
- // of the buffer. This behaviour is explictly allowed according to the documentation on
- // ID3D11DeviceContext1::PSSetConstantBuffers1
- // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
-}
-
} // anonymous namespace
namespace gl_d3d11
{
-D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
+D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
{
bool readBit = ((access & GL_MAP_READ_BIT) != 0);
bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
@@ -81,8 +59,7 @@ D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
}
else if (writeBit && !readBit)
{
- // Special case for uniform storage - we only allow full buffer updates.
- return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
+ return D3D11_MAP_WRITE;
}
else if (writeBit && readBit)
{
@@ -111,7 +88,7 @@ class Buffer11::BufferStorage : angle::NonCopyable
size_t getSize() const { return mBufferSize; }
void setDataRevision(DataRevision rev) { mRevision = rev; }
- virtual bool isMappable(GLbitfield access) const = 0;
+ virtual bool isMappable() const = 0;
virtual gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
@@ -146,7 +123,7 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
const angle::BroadcastChannel *onStorageChanged);
~NativeStorage() override;
- bool isMappable(GLbitfield access) const override;
+ bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
@@ -161,18 +138,14 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
uint8_t **mapPointerOut) override;
void unmap() override;
- gl::ErrorOrResult<ID3D11ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat);
-
private:
- static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+ static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer,
BufferUsage usage,
unsigned int bufferSize);
- void clearSRVs();
ID3D11Buffer *mNativeStorage;
const angle::BroadcastChannel *mOnStorageChanged;
- std::map<DXGI_FORMAT, ID3D11ShaderResourceView *> mBufferResourceViews;
};
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
@@ -184,7 +157,7 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
EmulatedIndexedStorage(Renderer11 *renderer);
~EmulatedIndexedStorage() override;
- bool isMappable(GLbitfield access) const override { return true; }
+ bool isMappable() const override { return true; }
gl::ErrorOrResult<ID3D11Buffer *> getNativeStorage(SourceIndexData *indexInfo,
const TranslatedAttribute &attribute,
@@ -217,7 +190,7 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage
explicit PackStorage(Renderer11 *renderer);
~PackStorage() override;
- bool isMappable(GLbitfield access) const override { return true; }
+ bool isMappable() const override { return true; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
size_t size,
@@ -252,7 +225,7 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
explicit SystemMemoryStorage(Renderer11 *renderer);
~SystemMemoryStorage() override {}
- bool isMappable(GLbitfield access) const override { return true; }
+ bool isMappable() const override { return true; }
gl::ErrorOrResult<CopyResult> copyFromStorage(BufferStorage *source,
size_t sourceOffset,
size_t size,
@@ -271,16 +244,16 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
MemoryBuffer mSystemCopy;
};
-Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
- : BufferD3D(state, renderer),
+Buffer11::Buffer11(Renderer11 *renderer)
+ : BufferD3D(renderer),
mRenderer(renderer),
mSize(0),
mMappedStorage(nullptr),
- mBufferStorages({}),
- mDeallocThresholds({}),
- mIdleness({}),
+ mBufferStorages(BUFFER_USAGE_COUNT, nullptr),
mConstantBufferStorageAdditionalSize(0),
- mMaxConstantBufferLruCount(0)
+ mMaxConstantBufferLruCount(0),
+ mReadUsageCount(0),
+ mSystemMemoryDeallocThreshold(0)
{
}
@@ -299,10 +272,10 @@ Buffer11::~Buffer11()
mRenderer->onBufferDelete(this);
}
-gl::Error Buffer11::setData(GLenum target, const void *data, size_t size, GLenum usage)
+gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
{
updateD3DBufferUsage(usage);
- ANGLE_TRY(setSubData(target, data, size, 0));
+ ANGLE_TRY(setSubData(data, size, 0));
return gl::NoError();
}
@@ -311,6 +284,8 @@ gl::Error Buffer11::getData(const uint8_t **outData)
SystemMemoryStorage *systemMemoryStorage = nullptr;
ANGLE_TRY_RESULT(getSystemMemoryStorage(), systemMemoryStorage);
+ mReadUsageCount = 0;
+
ASSERT(systemMemoryStorage->getSize() >= mSize);
*outData = systemMemoryStorage->getSystemCopy()->data();
@@ -324,34 +299,16 @@ gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStor
return GetAs<SystemMemoryStorage>(storage);
}
-gl::Error Buffer11::setSubData(GLenum target, const void *data, size_t size, size_t offset)
+gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
{
size_t requiredSize = size + offset;
if (data && size > 0)
{
// Use system memory storage for dynamic buffers.
- // Try using a constant storage for constant buffers
+
BufferStorage *writeBuffer = nullptr;
- if (target == GL_UNIFORM_BUFFER)
- {
- // If we are a very large uniform buffer, keep system memory storage around so that we
- // aren't forced to read back from a constant buffer. We also check the workaround for
- // Intel - this requires us to use system memory so we don't end up having to copy from
- // a constant buffer to a staging buffer.
- // TODO(jmadill): Use Context caps.
- if (offset == 0 && size >= mSize &&
- size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
- !mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
- {
- ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), writeBuffer);
- }
- else
- {
- ANGLE_TRY_RESULT(getSystemMemoryStorage(), writeBuffer);
- }
- }
- else if (supportsDirectBinding())
+ if (supportsDirectBinding())
{
ANGLE_TRY_RESULT(getStagingStorage(), writeBuffer);
}
@@ -406,12 +363,11 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
// If copying to/from a pixel pack buffer, we must have a staging or
// pack buffer partner, because other native buffers can't be mapped
- if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable(GL_MAP_READ_BIT))
+ if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
{
ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(), copySource);
}
- else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK &&
- !copyDest->isMappable(GL_MAP_WRITE_BIT))
+ else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
{
ANGLE_TRY_RESULT(getStagingStorage(), copyDest);
}
@@ -518,81 +474,50 @@ gl::Error Buffer11::markTransformFeedbackUsage()
return gl::NoError();
}
-void Buffer11::updateDeallocThreshold(BufferUsage usage)
+void Buffer11::updateSystemMemoryDeallocThreshold()
{
// The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
// as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
- // First readback: 8 unmodified uses before we free buffer memory.
+ // First readback: 8 unmodified uses before we free system memory.
// After that, double the threshold each time until we reach the max.
- if (mDeallocThresholds[usage] == 0)
+ if (mSystemMemoryDeallocThreshold == 0)
{
- mDeallocThresholds[usage] = 8;
+ mSystemMemoryDeallocThreshold = 8;
}
- else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
+ else if (mSystemMemoryDeallocThreshold < std::numeric_limits<unsigned int>::max() / 2u)
{
- mDeallocThresholds[usage] *= 2u;
+ mSystemMemoryDeallocThreshold *= 2u;
}
else
{
- mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
+ mSystemMemoryDeallocThreshold = std::numeric_limits<unsigned int>::max();
}
}
-// Free the storage if we decide it isn't being used very often.
-gl::Error Buffer11::checkForDeallocation(BufferUsage usage)
+gl::Error Buffer11::markBufferUsage()
{
- mIdleness[usage]++;
+ mReadUsageCount++;
- BufferStorage *&storage = mBufferStorages[usage];
- if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
+ // Free the system memory storage if we decide it isn't being used very often.
+ BufferStorage *&sysMemStorage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY];
+ if (sysMemStorage != nullptr && mReadUsageCount > mSystemMemoryDeallocThreshold)
{
BufferStorage *latestStorage = nullptr;
ANGLE_TRY_RESULT(getLatestBufferStorage(), latestStorage);
- if (latestStorage != storage)
+ if (latestStorage != sysMemStorage)
{
- SafeDelete(storage);
+ SafeDelete(sysMemStorage);
}
}
return gl::NoError();
}
-// Keep system memory when we are using it for the canonical version of data.
-bool Buffer11::canDeallocateSystemMemory() const
-{
- // Must keep system memory on Intel.
- if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
- {
- return false;
- }
-
- return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
- mSize <= mRenderer->getNativeCaps().maxUniformBlockSize);
-}
-
-void Buffer11::markBufferUsage(BufferUsage usage)
-{
- mIdleness[usage] = 0;
-}
-
-gl::Error Buffer11::garbageCollection(BufferUsage currentUsage)
-{
- if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
- {
- ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_SYSTEM_MEMORY));
- }
-
- if (currentUsage != BUFFER_USAGE_STAGING)
- {
- ANGLE_TRY(checkForDeallocation(BUFFER_USAGE_STAGING));
- }
-
- return gl::NoError();
-}
-
gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(BufferUsage usage)
{
+ ANGLE_TRY(markBufferUsage());
+
BufferStorage *storage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(usage), storage);
return GetAs<NativeStorage>(storage)->getNativeStorage();
@@ -605,6 +530,8 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
{
ASSERT(indexInfo);
+ ANGLE_TRY(markBufferUsage());
+
BufferStorage *untypedStorage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX), untypedStorage);
@@ -617,37 +544,64 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
return nativeStorage;
}
-gl::Error Buffer11::getConstantBufferRange(GLintptr offset,
- GLsizeiptr size,
- ID3D11Buffer **bufferOut,
- UINT *firstConstantOut,
- UINT *numConstantsOut)
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size)
{
+ ANGLE_TRY(markBufferUsage());
+
BufferStorage *bufferStorage = nullptr;
if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
{
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_UNIFORM), bufferStorage);
- CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
}
else
{
ANGLE_TRY_RESULT(getConstantBufferRangeStorage(offset, size), bufferStorage);
- *firstConstantOut = 0;
- *numConstantsOut = 0;
}
- *bufferOut = GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
-
- return gl::NoError();
+ return GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
}
gl::ErrorOrResult<ID3D11ShaderResourceView *> Buffer11::getSRV(DXGI_FORMAT srvFormat)
{
BufferStorage *storage = nullptr;
ANGLE_TRY_RESULT(getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK), storage);
- NativeStorage *nativeStorage = GetAs<NativeStorage>(storage);
- return nativeStorage->getSRVForFormat(srvFormat);
+ ID3D11Buffer *buffer = GetAs<NativeStorage>(storage)->getNativeStorage();
+
+ 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,
@@ -689,31 +643,28 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(BufferUs
newStorage = allocateStorage(usage);
}
- markBufferUsage(usage);
-
// resize buffer
if (newStorage->getSize() < mSize)
{
ANGLE_TRY(newStorage->resize(mSize, true));
}
- ASSERT(newStorage);
-
ANGLE_TRY(updateBufferStorage(newStorage, 0, mSize));
- ANGLE_TRY(garbageCollection(usage));
return newStorage;
}
Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
{
- updateDeallocThreshold(usage);
switch (usage)
{
case BUFFER_USAGE_PIXEL_PACK:
return new PackStorage(mRenderer);
case BUFFER_USAGE_SYSTEM_MEMORY:
+ {
+ updateSystemMemoryDeallocThreshold();
return new SystemMemoryStorage(mRenderer);
+ }
case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
return new EmulatedIndexedStorage(mRenderer);
case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
@@ -744,8 +695,6 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto
newStorage = cacheEntry->storage;
}
- markBufferUsage(BUFFER_USAGE_UNIFORM);
-
if (newStorage->getSize() < static_cast<size_t>(size))
{
size_t maximumAllowedAdditionalSize = 2 * getSize();
@@ -780,7 +729,6 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto
}
ANGLE_TRY(updateBufferStorage(newStorage, offset, size));
- ANGLE_TRY(garbageCollection(BUFFER_USAGE_UNIFORM));
return newStorage;
}
@@ -791,8 +739,6 @@ gl::Error Buffer11::updateBufferStorage(BufferStorage *storage,
BufferStorage *latestBuffer = nullptr;
ANGLE_TRY_RESULT(getLatestBufferStorage(), latestBuffer);
- ASSERT(storage);
-
if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision())
{
// Copy through a staging buffer if we're copying from or to a non-staging, mappable
@@ -800,7 +746,7 @@ gl::Error Buffer11::updateBufferStorage(BufferStorage *storage,
// data directly. If we're already using a staging buffer we're fine.
if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
storage->getUsage() != BUFFER_USAGE_STAGING &&
- (!latestBuffer->isMappable(GL_MAP_READ_BIT) || !storage->isMappable(GL_MAP_WRITE_BIT)))
+ (!latestBuffer->isMappable() || !storage->isMappable()))
{
NativeStorage *stagingBuffer = nullptr;
ANGLE_TRY_RESULT(getStagingStorage(), stagingBuffer);
@@ -899,8 +845,6 @@ angle::BroadcastChannel *Buffer11::getDirectBroadcastChannel()
return &mDirectBroadcastChannel;
}
-// Buffer11::BufferStorage implementation
-
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
: mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
{
@@ -908,24 +852,18 @@ Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
{
- ASSERT(isMappable(GL_MAP_WRITE_BIT));
-
- // Uniform storage can have a different internal size than the buffer size. Ensure we don't
- // overflow.
- size_t mapSize = std::min(size, mBufferSize - offset);
+ ASSERT(isMappable());
uint8_t *writePointer = nullptr;
- ANGLE_TRY(map(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
+ ANGLE_TRY(map(offset, size, GL_MAP_WRITE_BIT, &writePointer));
- memcpy(writePointer, data, mapSize);
+ memcpy(writePointer, data, size);
unmap();
return gl::NoError();
}
-// Buffer11::NativeStorage implementation
-
Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
BufferUsage usage,
const angle::BroadcastChannel *onStorageChanged)
@@ -936,18 +874,6 @@ Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
Buffer11::NativeStorage::~NativeStorage()
{
SafeRelease(mNativeStorage);
- clearSRVs();
-}
-
-bool Buffer11::NativeStorage::isMappable(GLbitfield access) const
-{
- if ((access & GL_MAP_READ_BIT) != 0)
- {
- // Read is more exclusive than write mappability.
- return (mUsage == BUFFER_USAGE_STAGING);
- }
- ASSERT((access & GL_MAP_WRITE_BIT) != 0);
- return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM);
}
// Returns true if it recreates the direct buffer
@@ -962,38 +888,45 @@ gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(BufferSto
bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;
// (Re)initialize D3D buffer if needed
- bool preserveData = (destOffset > 0);
if (createBuffer)
{
+ bool preserveData = (destOffset > 0);
resize(requiredSize, preserveData);
}
- size_t clampedSize = size;
- if (mUsage == BUFFER_USAGE_UNIFORM)
- {
- clampedSize = std::min(clampedSize, mBufferSize - destOffset);
- }
-
if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
{
- ASSERT(source->isMappable(GL_MAP_READ_BIT) && isMappable(GL_MAP_WRITE_BIT));
-
- // Uniform buffers must be mapped with write/discard.
- ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM));
+ ASSERT(source->isMappable());
uint8_t *sourcePointer = nullptr;
- ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourcePointer));
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ ASSERT(SUCCEEDED(hr));
+ if (FAILED(hr))
+ {
+ source->unmap();
+ return gl::Error(
+ GL_OUT_OF_MEMORY,
+ "Failed to map native storage in Buffer11::NativeStorage::copyFromStorage");
+ }
+
+ uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset;
- setData(sourcePointer, destOffset, clampedSize);
+ // Offset bounds are validated at the API layer
+ ASSERT(sourceOffset + size <= destOffset + mBufferSize);
+ memcpy(destPointer, sourcePointer, size);
+ context->Unmap(mNativeStorage, 0);
source->unmap();
}
else
{
D3D11_BOX srcBox;
srcBox.left = static_cast<unsigned int>(sourceOffset);
- srcBox.right = static_cast<unsigned int>(sourceOffset + clampedSize);
+ srcBox.right = static_cast<unsigned int>(sourceOffset + size);
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
@@ -1014,7 +947,7 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
D3D11_BUFFER_DESC bufferDesc;
- FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
+ fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
ID3D11Buffer *newBuffer;
HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer);
@@ -1049,9 +982,6 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
mBufferSize = bufferDesc.ByteWidth;
- // Free the SRVs.
- clearSRVs();
-
// Notify that the storage has changed.
if (mOnStorageChanged)
{
@@ -1061,8 +991,7 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
return gl::NoError();
}
-// static
-void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer,
BufferUsage usage,
unsigned int bufferSize)
@@ -1111,9 +1040,6 @@ void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
// Constant buffers must be of a limited size, and aligned to 16 byte boundaries
// For our purposes we ignore any buffer data past the maximum constant buffer size
bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
-
- // Note: it seems that D3D11 allows larger buffers on some platforms, but not all.
- // (Windows 10 seems to allow larger constant buffers, but not Windows 7)
bufferDesc->ByteWidth =
std::min<UINT>(bufferDesc->ByteWidth,
static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
@@ -1129,11 +1055,11 @@ gl::Error Buffer11::NativeStorage::map(size_t offset,
GLbitfield access,
uint8_t **mapPointerOut)
{
- ASSERT(isMappable(access));
+ ASSERT(mUsage == BUFFER_USAGE_STAGING);
D3D11_MAPPED_SUBRESOURCE mappedResource;
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
+ D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
@@ -1150,56 +1076,11 @@ gl::Error Buffer11::NativeStorage::map(size_t offset,
void Buffer11::NativeStorage::unmap()
{
- ASSERT(isMappable(GL_MAP_WRITE_BIT) || isMappable(GL_MAP_READ_BIT));
+ ASSERT(mUsage == BUFFER_USAGE_STAGING);
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
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)
: BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr)
{
@@ -1334,7 +1215,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage(
size_t size,
size_t destOffset)
{
- ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ ASSERT(source->isMappable());
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mMemoryBuffer.size());
@@ -1372,8 +1253,6 @@ void Buffer11::EmulatedIndexedStorage::unmap()
// No-op
}
-// Buffer11::PackStorage implementation
-
Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
: BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
{
@@ -1390,8 +1269,9 @@ gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(BufferStora
{
ANGLE_TRY(flushQueuedPackCommand());
- // For all use cases of pack buffers, we must copy through a readable buffer.
- ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ // We copy through a staging buffer when drawing with a pack buffer, or for other cases where we
+ // access the pack buffer
+ ASSERT(source->isMappable() && source->getUsage() == BUFFER_USAGE_STAGING);
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mMemoryBuffer.size());
@@ -1504,8 +1384,6 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
return gl::NoError();
}
-// Buffer11::SystemMemoryStorage implementation
-
Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
: Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
{
@@ -1516,7 +1394,7 @@ gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(Buf
size_t size,
size_t destOffset)
{
- ASSERT(source->isMappable(GL_MAP_READ_BIT));
+ ASSERT(source->isMappable());
uint8_t *sourceData = nullptr;
ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mSystemCopy.size());