diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-07-11 18:11:13 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-07-11 18:11:13 +0200 |
commit | 4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0 (patch) | |
tree | f000dd831240707a03b8c806db292c2a15cde3ce /gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | |
parent | 3b7ffb477eec078c7036c92c6a51bb5de6de4f28 (diff) | |
download | UXP-4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0.tar UXP-4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0.tar.gz UXP-4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0.tar.lz UXP-4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0.tar.xz UXP-4f2ecd53a9daaf88bb7d075745eefb6e2e4741e0.zip |
Roll back to ANGLE/2845
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp')
-rwxr-xr-x | gfx/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 360 |
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()); |